import { cookies } from "next/headers" import { notFound } from "next/navigation" import { Suspense } from "react" import { FamilyAndFriendsCodes } from "@scandic-hotels/common/constants/familyAndFriends" import { SEARCH_TYPE_REDEMPTION } from "@scandic-hotels/trpc/constants/booking" 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 ) const booking = parseDetailsSearchParams(searchParams) if (!booking) return notFound() // This should never happen unless a user tampers with the URL if ( !config.redemptionEnabled && booking.searchType === SEARCH_TYPE_REDEMPTION ) { throw new Error("Redemptions are disabled") } 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 } } 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 (
{multirooms.map((room, idx) => ( // Need to start idx from 1 since first room is // rendered above ))}
) }