Files
web/packages/booking-flow/lib/components/BookingConfirmation/index.tsx
Bianca Widstam 57d0e1b27b Merged in fix/BOOK-662-handle-overlapping-dates-timezone (pull request #3319)
Fix/BOOK-662 handle overlapping dates timezone

* fix(BOOK-662): handle overlapping dates alerts

* fix(BOOK-662): handle overlapping dates alerts

* fix(BOOK-662): add test same dates


Approved-by: Anton Gunnarsson
2025-12-19 14:03:30 +00:00

132 lines
4.5 KiB
TypeScript

import { notFound } from "next/navigation"
import { AlertTypeEnum } from "@scandic-hotels/common/constants/alert"
import { dt } from "@scandic-hotels/common/dt"
import { Alert } from "@scandic-hotels/design-system/Alert"
import { Divider } from "@scandic-hotels/design-system/Divider"
import { HotelTypeEnum } from "@scandic-hotels/trpc/enums/hotelType"
import { env } from "../../../env/server"
import { BookingConfirmationProvider } from "../../providers/BookingConfirmationProvider"
import { getBookingConfirmation } from "../../trpc/memoizedRequests/getBookingConfirmation"
import { filterOverlappingDates } from "../../utils/SelectRate"
import { SidePanel } from "../SidePanel"
import { Confirmation } from "./Confirmation"
import { HotelDetails } from "./HotelDetails"
import { PaymentDetails } from "./PaymentDetails"
import { Promos } from "./Promos"
import { Receipt } from "./Receipt"
import { Rooms } from "./Rooms"
import BookingConfirmationTracking from "./Tracking"
import { mapRoomState } from "./utils"
import styles from "./bookingConfirmation.module.css"
import type { BookingConfirmation } from "@scandic-hotels/trpc/types/bookingConfirmation"
import type { IntlShape } from "react-intl"
type BookingConfirmationProps = {
intl: IntlShape
refId: string
membershipFailedError: boolean
}
export async function BookingConfirmation({
intl,
refId,
membershipFailedError,
}: BookingConfirmationProps) {
const bookingConfirmation = await getBookingConfirmation(refId)
if (!bookingConfirmation) {
return notFound()
}
const { booking, url, hotel, room, roomCategories } = bookingConfirmation
const baseUrl = env.PUBLIC_URL || "https://www.scandichotels.com"
const hotelUrl = new URL(`${baseUrl}${url}`)
if (!room) {
return notFound()
}
const validAlerts = filterOverlappingDates(
hotel.specialAlerts.filter((alert) => alert.displayInBookingFlow),
dt.utc(booking.checkInDate),
dt.utc(booking.checkOutDate)
)
return (
<BookingConfirmationProvider
bookingCode={booking.bookingCode}
currencyCode={booking.currencyCode}
fromDate={booking.checkInDate}
hotelOffersBreakfast={hotel.hotelType !== HotelTypeEnum.ScandicGo}
toDate={booking.checkOutDate}
roomCategories={roomCategories}
rooms={[
mapRoomState(booking, room, intl),
// null represents "known but not yet fetched rooms" and is used to render placeholders correctly
...Array(booking.linkedReservations.length).fill(null),
]}
vat={booking.vatPercentage}
>
<Confirmation
url={hotelUrl.toString()}
booking={booking}
hotel={hotel}
room={room}
>
<div className={styles.booking}>
{membershipFailedError && (
<Alert
type={AlertTypeEnum.Info}
heading={intl.formatMessage({
id: "bookingConfirmation.membershipVerificationFailed",
defaultMessage: "Failed to verify membership",
})}
text={intl.formatMessage({
id: "bookingConfirmation.bookingConfirmedMembershipFailedInfo",
defaultMessage:
"Your booking(s) is confirmed but we could not verify your membership. If you have booked with a member discount, you'll either need to present your existing membership number upon check-in, become a member or pay the price difference at the hotel. Signing up is preferably done online before the stay.",
})}
/>
)}
<Rooms
booking={booking}
checkInTime={hotel.hotelFacts.checkin.checkInTime}
checkOutTime={hotel.hotelFacts.checkin.checkOutTime}
mainRoom={room}
/>
<PaymentDetails />
<Divider color="Border/Divider/Subtle" />
<HotelDetails url={hotelUrl.toString()} hotel={hotel} />
{validAlerts.map((alert) => (
<div key={alert.id}>
<Alert
type={alert.type}
heading={alert.heading}
text={alert.text}
/>
</div>
))}
<Promos booking={booking} />
<div className={styles.mobileReceipt}>
<Receipt />
</div>
</div>
<aside className={styles.aside}>
<SidePanel variant="receipt">
<Receipt />
</SidePanel>
</aside>
</Confirmation>
<BookingConfirmationTracking
bookingConfirmation={bookingConfirmation}
refId={refId}
/>
</BookingConfirmationProvider>
)
}