Files
web/packages/booking-flow/lib/pages/AlternativeHotelsPage.tsx
Joakim Jäderberg 7dee6d5083 Merged in chore/move-enter-details (pull request #2778)
Chore/move enter details

Approved-by: Anton Gunnarsson
2025-09-11 07:16:24 +00:00

133 lines
3.9 KiB
TypeScript

import stringify from "json-stable-stringify-without-jsonify"
import { cookies } from "next/headers"
import { notFound } from "next/navigation"
import { Suspense } from "react"
import { FamilyAndFriendsCodes } from "@scandic-hotels/common/constants/familyAndFriends"
import { TrackingSDK } from "@scandic-hotels/tracking/TrackingSDK"
import { AlternativeHotelsPageTitle } from "../components/AlternativeHotelsPageTitle"
import FnFNotAllowedAlert from "../components/FnFNotAllowedAlert"
import { SelectHotel } from "../components/SelectHotel"
import { getHotels } from "../components/SelectHotel/helpers"
import { getHotelSearchDetails } from "../misc/getHotelSearchDetails"
import { getSelectHotelTracking } from "../misc/selectHotelTracking"
import { parseSelectHotelSearchParams } from "../utils/url"
import type { Lang } from "@scandic-hotels/common/constants/language"
import type { NextSearchParams } from "../types"
export async function AlternativeHotelsPage({
lang,
searchParams,
}: {
lang: Lang
searchParams: NextSearchParams
}) {
const booking = parseSelectHotelSearchParams(searchParams)
if (!booking) return notFound()
const searchDetails = await getHotelSearchDetails({
...booking,
lang,
isAlternativeHotels: true,
})
if (!searchDetails || !searchDetails.hotel || !searchDetails.city) {
return notFound()
}
// TODO move logic to function to reuse
if (
booking.bookingCode &&
FamilyAndFriendsCodes.includes(booking.bookingCode)
) {
const cookieStore = await cookies()
const isInvalidFNF = cookieStore.get("sc")?.value !== "1"
if (isInvalidFNF) {
return <FnFNotAllowedAlert />
}
}
// TODO: This needs to be refactored into its
// own functions
const hotels = await getHotels({
fromDate: booking.fromDate,
toDate: booking.toDate,
rooms: booking.rooms,
isAlternativeFor: searchDetails.hotel,
bookingCode: booking.bookingCode,
city: searchDetails.city,
redemption: !!searchDetails.redemption,
lang,
})
const arrivalDate = new Date(booking.fromDate)
const departureDate = new Date(booking.toDate)
const isRedemptionAvailability = searchDetails.redemption
? hotels.some(
(hotel) => hotel.availability.productType?.redemptions?.length
)
: false
const isBookingCodeRateAvailable = booking.bookingCode
? hotels.some(
(hotel) =>
hotel.availability.bookingCode &&
hotel.availability.status === "Available"
)
: false
const { hotelsTrackingData, pageTrackingData } = getSelectHotelTracking({
lang,
pageId: searchDetails.hotel ? "alternative-hotels" : "select-hotel",
pageName: searchDetails.hotel
? "hotelreservation|alternative-hotels"
: "hotelreservation|select-hotel",
siteSections: searchDetails.hotel
? "hotelreservation|alternative-hotels"
: "hotelreservation|select-hotel",
arrivalDate,
departureDate,
rooms: booking.rooms,
hotelsResult: hotels?.length ?? 0,
searchTerm: searchDetails.hotel
? booking.hotelId
: searchDetails.cityIdentifier,
country: hotels?.[0]?.hotel.address.country,
hotelCity: hotels?.[0]?.hotel.address.city,
bookingCode: booking.bookingCode,
isBookingCodeRateAvailable,
isRedemption: searchDetails.redemption,
isRedemptionAvailable: isRedemptionAvailability,
})
const suspenseKey = stringify(searchParams)
return (
<>
<SelectHotel
bookingCode={booking.bookingCode}
city={searchDetails.city}
hotels={hotels}
isAlternative={!!searchDetails.hotel}
isBookingCodeRateAvailable={isBookingCodeRateAvailable}
title={
<AlternativeHotelsPageTitle hotelName={searchDetails.hotel.name} />
}
lang={lang}
/>
<Suspense key={`${suspenseKey}-tracking`} fallback={null}>
<TrackingSDK
hotelInfo={hotelsTrackingData}
pageData={pageTrackingData}
/>
</Suspense>
</>
)
}