fix(SW-3551): Fix issue with BookingConfigProvider in RSC * wip move config to pages * Move config providing to pages
174 lines
5.8 KiB
TypeScript
174 lines
5.8 KiB
TypeScript
import { cookies } from "next/headers"
|
|
import { notFound } from "next/navigation"
|
|
import { Suspense } from "react"
|
|
|
|
import { FamilyAndFriendsCodes } from "@scandic-hotels/common/constants/familyAndFriends"
|
|
|
|
import { BookingFlowConfig } from "../bookingFlowConfig/bookingFlowConfig"
|
|
import HotelHeader from "../components/EnterDetails/Header"
|
|
import Payment from "../components/EnterDetails/Payment"
|
|
import Multiroom from "../components/EnterDetails/Room/Multiroom"
|
|
import RoomOne from "../components/EnterDetails/Room/One"
|
|
import DesktopSummary from "../components/EnterDetails/Summary/Desktop"
|
|
import MobileSummary from "../components/EnterDetails/Summary/Mobile"
|
|
import EnterDetailsTrackingWrapper from "../components/EnterDetails/Tracking"
|
|
import FnFNotAllowedAlert from "../components/FnFNotAllowedAlert"
|
|
import EnterDetailsProvider from "../contexts/EnterDetails/EnterDetailsContext"
|
|
import { RoomProvider } from "../contexts/EnterDetails/RoomContext"
|
|
import { getBreakfastPackages } from "../trpc/memoizedRequests/getBreakfastPackages"
|
|
import { getHotel } from "../trpc/memoizedRequests/getHotel"
|
|
import { getProfileSafely } from "../trpc/memoizedRequests/getProfile"
|
|
import { getSelectedRoomsAvailabilityEnterDetails } from "../trpc/memoizedRequests/getSelectedRoomsAvailabilityEnterDetails"
|
|
import { parseDetailsSearchParams } from "../utils/url"
|
|
|
|
import styles from "./EnterDetailsPage.module.css"
|
|
|
|
import type { Lang } from "@scandic-hotels/common/constants/language"
|
|
|
|
import type { NextSearchParams } from "../types"
|
|
|
|
export async function EnterDetailsPage({
|
|
lang,
|
|
searchParams,
|
|
config,
|
|
}: {
|
|
lang: Lang
|
|
searchParams: NextSearchParams
|
|
config: BookingFlowConfig
|
|
}) {
|
|
const selectRoomParams = new URLSearchParams(
|
|
searchParams as Record<string, string>
|
|
)
|
|
|
|
const booking = parseDetailsSearchParams(searchParams)
|
|
|
|
if (!booking) return notFound()
|
|
|
|
if (selectRoomParams.has("activeRoomIndex")) {
|
|
selectRoomParams.delete("activeRoomIndex")
|
|
}
|
|
|
|
if (
|
|
booking.bookingCode &&
|
|
FamilyAndFriendsCodes.includes(booking.bookingCode)
|
|
) {
|
|
const cookieStore = await cookies()
|
|
const isInValidFNF = cookieStore.get("sc")?.value !== "1"
|
|
|
|
if (isInValidFNF) {
|
|
return <FnFNotAllowedAlert />
|
|
}
|
|
}
|
|
|
|
const breakfastInput = {
|
|
adults: 1,
|
|
fromDate: booking.fromDate,
|
|
hotelId: booking.hotelId,
|
|
toDate: booking.toDate,
|
|
}
|
|
const hotelInput = {
|
|
hotelId: booking.hotelId,
|
|
// TODO: Remove this from input since it forces
|
|
// waterfalls for no other reason than to
|
|
// set merchantInformationData.alternatePaymentOptions
|
|
// to an empty array
|
|
isCardOnlyPayment: false,
|
|
language: lang,
|
|
}
|
|
const getHotelPromise = getHotel(hotelInput)
|
|
const getBreakfastPackagesPromise = getBreakfastPackages(breakfastInput)
|
|
const getProfilePromise = getProfileSafely()
|
|
|
|
const rooms = await getSelectedRoomsAvailabilityEnterDetails({
|
|
booking,
|
|
lang,
|
|
})
|
|
|
|
const hotelData = await getHotelPromise
|
|
|
|
if (!hotelData || !rooms.length) {
|
|
return notFound()
|
|
}
|
|
|
|
const breakfastPackages = await getBreakfastPackagesPromise
|
|
const user = await getProfilePromise
|
|
|
|
const isCardOnlyPayment = rooms.some((room) => room.mustBeGuaranteed)
|
|
const { hotel } = hotelData
|
|
// TODO: Temp fix to avoid waterfall fetch and moving this
|
|
// logic from the route here for now
|
|
if (isCardOnlyPayment) {
|
|
hotel.merchantInformationData.alternatePaymentOptions = []
|
|
}
|
|
|
|
const firstRoom = rooms[0]
|
|
const multirooms = rooms.slice(1)
|
|
|
|
const { rateDefinition, rateDefinitionMember } = firstRoom.roomRate
|
|
if (user && rateDefinitionMember) {
|
|
const rateCode = selectRoomParams.get("room[0].ratecode")
|
|
if (rateDefinitionMember.rateCode !== rateCode) {
|
|
booking.rooms[0].rateCode = rateDefinitionMember.rateCode
|
|
selectRoomParams.set("room[0].ratecode", rateDefinitionMember.rateCode)
|
|
booking.rooms[0].counterRateCode = rateDefinition.rateCode
|
|
selectRoomParams.set("room[0].counterratecode", rateDefinition.rateCode)
|
|
}
|
|
}
|
|
|
|
// attribute data-footer-spacing used to add spacing
|
|
// beneath footer to be able to show entire footer upon
|
|
// scrolling down to the bottom of the page
|
|
return (
|
|
<BookingFlowConfig config={config}>
|
|
<main data-footer-spacing>
|
|
<EnterDetailsProvider
|
|
booking={booking}
|
|
breakfastPackages={breakfastPackages}
|
|
lang={lang}
|
|
rooms={rooms}
|
|
searchParamsStr={selectRoomParams.toString()}
|
|
user={user}
|
|
vat={hotel.vat}
|
|
roomCategories={hotelData.roomCategories}
|
|
>
|
|
<HotelHeader hotelData={hotelData} />
|
|
<div className={styles.container}>
|
|
<div className={styles.content}>
|
|
<RoomProvider idx={0} room={firstRoom}>
|
|
<RoomOne user={user} />
|
|
</RoomProvider>
|
|
{multirooms.map((room, idx) => (
|
|
// Need to start idx from 1 since first room is
|
|
// rendered above
|
|
<RoomProvider key={idx + 1} idx={idx + 1} room={room}>
|
|
<Multiroom />
|
|
</RoomProvider>
|
|
))}
|
|
<Suspense>
|
|
<Payment
|
|
otherPaymentOptions={
|
|
hotel.merchantInformationData.alternatePaymentOptions
|
|
}
|
|
supportedCards={hotel.merchantInformationData.cards}
|
|
/>
|
|
</Suspense>
|
|
</div>
|
|
<aside className={styles.summary}>
|
|
<MobileSummary isUserLoggedIn={!!user} />
|
|
<DesktopSummary isUserLoggedIn={!!user} />
|
|
</aside>
|
|
</div>
|
|
|
|
<EnterDetailsTrackingWrapper
|
|
booking={booking}
|
|
hotel={hotel}
|
|
isMember={!!user}
|
|
lang={lang}
|
|
rooms={rooms}
|
|
/>
|
|
</EnterDetailsProvider>
|
|
</main>
|
|
</BookingFlowConfig>
|
|
)
|
|
}
|