Files
web/packages/booking-flow/lib/pages/AlternativeHotelsPage.tsx
Anton Gunnarsson 87402a2092 Merged in feat/sw-2873-move-selecthotel-to-booking-flow (pull request #2727)
feat(SW-2873): Move select-hotel to booking flow

* crude setup of select-hotel in partner-sas

* wip

* Fix linting

* restructure tracking files

* Remove dependency on trpc in tracking hooks

* Move pageview tracking to common

* Fix some lint and import issues

* Add AlternativeHotelsPage

* Add SelectHotelMapPage

* Add AlternativeHotelsMapPage

* remove next dependency in tracking store

* Remove dependency on react in tracking hooks

* move isSameBooking to booking-flow

* Inject searchParamsComparator into tracking store

* Move useTrackHardNavigation to common

* Move useTrackSoftNavigation to common

* Add TrackingSDK to partner-sas

* call serverclient in layout

* Remove unused css

* Update types

* Move HotelPin type

* Fix todos

* Merge branch 'master' into feat/sw-2873-move-selecthotel-to-booking-flow

* Merge branch 'master' into feat/sw-2873-move-selecthotel-to-booking-flow

* Fix component


Approved-by: Joakim Jäderberg
2025-09-01 08:37:00 +00:00

138 lines
4.1 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 { 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 {
TrackingSDKHotelInfo,
TrackingSDKPageData,
} from "@scandic-hotels/common/tracking/types"
import type { NextSearchParams } from "../types"
export async function AlternativeHotelsPage({
lang,
searchParams,
renderTracking,
}: {
lang: Lang
searchParams: NextSearchParams
renderTracking: (trackingProps: {
hotelsTrackingData: TrackingSDKHotelInfo
pageTrackingData: TrackingSDKPageData
}) => React.ReactNode
}) {
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}>
{renderTracking({ hotelsTrackingData, pageTrackingData })}
</Suspense>
</>
)
}