import { differenceInCalendarDays, format, isWeekend } from "date-fns" import { notFound } from "next/navigation" import { Suspense } from "react" import { alternativeHotels, alternativeHotelsMap, selectHotel, selectHotelMap, } from "@/constants/routes/hotelReservation" import { fetchAlternativeHotels, fetchAvailableHotels, fetchBookingCodeAvailableHotels, getFiltersFromHotels, } from "@/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/utils" import { getHotelSearchDetails } from "@/app/[lang]/(live)/(public)/hotelreservation/(standard)/utils" import { ChevronRightIcon } from "@/components/Icons" import StaticMap from "@/components/Maps/StaticMap" import Breadcrumbs from "@/components/TempDesignSystem/Breadcrumbs" import Button from "@/components/TempDesignSystem/Button" import Link from "@/components/TempDesignSystem/Link" import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" import TrackingSDK from "@/components/TrackingSDK" import { getIntl } from "@/i18n" import { safeTry } from "@/utils/safeTry" import { convertObjToSearchParams } from "@/utils/url" import HotelCardListing from "../HotelCardListing" import BookingCodeFilter from "./BookingCodeFilter" import HotelCount from "./HotelCount" import HotelFilter from "./HotelFilter" import HotelSorter from "./HotelSorter" import MobileMapButtonContainer from "./MobileMapButtonContainer" import NoAvailabilityAlert from "./NoAvailabilityAlert" import styles from "./selectHotel.module.css" import { ChildBedMapEnum } from "@/types/components/bookingWidget/enums" import type { HotelData } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps" import type { SelectHotelProps } from "@/types/components/hotelReservation/selectHotel/selectHotel" import type { SelectHotelSearchParams } from "@/types/components/hotelReservation/selectHotel/selectHotelSearchParams" import { TrackingChannelEnum, type TrackingSDKHotelInfo, type TrackingSDKPageData, } from "@/types/components/tracking" export default async function SelectHotel({ params, searchParams, isAlternativeHotels, }: SelectHotelProps) { const intl = await getIntl() const getHotelSearchDetailsPromise = safeTry( getHotelSearchDetails( { searchParams: searchParams as SelectHotelSearchParams & { [key: string]: string }, }, isAlternativeHotels ) ) const [searchDetails] = await getHotelSearchDetailsPromise if (!searchDetails) return notFound() const { city, selectHotelParams, adultsInRoom, childrenInRoomString, childrenInRoom, hotel: isAlternativeFor, bookingCode, } = searchDetails if (!city) return notFound() const hotelsPromise = isAlternativeFor ? safeTry( fetchAlternativeHotels(isAlternativeFor.id, { roomStayStartDate: selectHotelParams.fromDate, roomStayEndDate: selectHotelParams.toDate, adults: adultsInRoom[0], children: childrenInRoomString, bookingCode, }) ) : bookingCode ? safeTry( fetchBookingCodeAvailableHotels({ cityId: city.id, roomStayStartDate: selectHotelParams.fromDate, roomStayEndDate: selectHotelParams.toDate, adults: adultsInRoom[0], children: childrenInRoomString, bookingCode, }) ) : safeTry( fetchAvailableHotels({ cityId: city.id, roomStayStartDate: selectHotelParams.fromDate, roomStayEndDate: selectHotelParams.toDate, adults: adultsInRoom[0], children: childrenInRoomString, }) ) const [hotels] = await hotelsPromise const arrivalDate = new Date(selectHotelParams.fromDate) const departureDate = new Date(selectHotelParams.toDate) const isCityWithCountry = (city: any): city is { country: string } => "country" in city const validHotels = hotels?.filter((hotel): hotel is HotelData => hotel?.hotelData !== null) || [] const filterList = getFiltersFromHotels(validHotels) const convertedSearchParams = convertObjToSearchParams(selectHotelParams) const breadcrumbs = [ { title: intl.formatMessage({ id: "Home" }), href: `/${params.lang}`, uid: "home-page", }, { title: intl.formatMessage({ id: "Hotel reservation" }), href: `/${params.lang}/hotelreservation`, uid: "hotel-reservation", }, isAlternativeFor ? { title: intl.formatMessage({ id: "Alternative hotels" }), href: `${alternativeHotels(params.lang)}/?${convertedSearchParams}`, uid: "alternative-hotels", } : { title: intl.formatMessage({ id: "Select hotel" }), href: `${selectHotel(params.lang)}/?${convertedSearchParams}`, uid: "select-hotel", }, isAlternativeFor ? { title: isAlternativeFor.name, uid: isAlternativeFor.id, } : { title: city.name, uid: city.id, }, ] const isAllUnavailable = hotels?.every((hotel) => hotel.price === undefined) || false const pageTrackingData: TrackingSDKPageData = { pageId: isAlternativeFor ? "alternative-hotels" : "select-hotel", domainLanguage: params.lang, channel: TrackingChannelEnum["hotelreservation"], pageName: isAlternativeFor ? "hotelreservation|alternative-hotels" : "hotelreservation|select-hotel", siteSections: isAlternativeFor ? "hotelreservation|alternative-hotels" : "hotelreservation|select-hotel", pageType: "bookinghotelspage", siteVersion: "new-web", } const hotelsTrackingData: TrackingSDKHotelInfo = { availableResults: validHotels.length, searchTerm: isAlternativeFor ? selectHotelParams.hotelId : (selectHotelParams.city as string), arrivalDate: format(arrivalDate, "yyyy-MM-dd"), departureDate: format(departureDate, "yyyy-MM-dd"), noOfAdults: adultsInRoom[0], // TODO: Handle multiple rooms, noOfChildren: childrenInRoom?.length, ageOfChildren: childrenInRoom?.map((c) => c.age).join(","), childBedPreference: childrenInRoom ?.map((c) => ChildBedMapEnum[c.bed]) .join("|"), noOfRooms: 1, // // TODO: Handle multiple rooms duration: differenceInCalendarDays(departureDate, arrivalDate), leadTime: differenceInCalendarDays(arrivalDate, new Date()), searchType: "destination", bookingTypeofDay: isWeekend(arrivalDate) ? "weekend" : "weekday", country: validHotels?.[0]?.hotelData.address.country, region: validHotels?.[0]?.hotelData.address.city, } return ( <> {isAlternativeFor ? `${intl.formatMessage({ id: "Alternatives for" })} ${isAlternativeFor.name}` : city.name} {bookingCode ? : null} {hotels && hotels.length > 0 ? ( // TODO: Temp fix until API returns hotels that are not available {intl.formatMessage({ id: "See map" })} ) : ( )} > ) }