"use client" import { usePathname, useRouter, useSearchParams } from "next/navigation" import { useEffect, useMemo } from "react" import { useIntl } from "react-intl" import { useRateSelectionStore } from "@/stores/select-rate/rate-selection" import { useRoomFilteringStore } from "@/stores/select-rate/room-filtering" import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" import { trackLowestRoomPrice } from "@/utils/tracking" import { convertObjToSearchParams, convertSearchParamsToObj } from "@/utils/url" import RateSummary from "../RateSummary" import { RoomSelectionPanel } from "../RoomSelectionPanel" import SelectedRoomPanel from "../SelectedRoomPanel" import { roomSelectionPanelVariants } from "./variants" import styles from "./rooms.module.css" import { type DefaultFilterOptions, RoomPackageCodeEnum, } from "@/types/components/hotelReservation/selectRate/roomFilter" import type { SelectRateProps } from "@/types/components/hotelReservation/selectRate/roomSelection" import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate" export default function Rooms({ availablePackages, hotelType, isUserLoggedIn, roomsAvailability, roomCategories = [], }: SelectRateProps) { const router = useRouter() const pathname = usePathname() const searchParams = useSearchParams() const intl = useIntl() const hotelId = searchParams.get("hotel") const arrivalDate = searchParams.get("fromDate") const departureDate = searchParams.get("toDate") const { selectedRates, rateSummary, calculateRateSummary, initializeRates } = useRateSelectionStore() const { selectedPackagesByRoom, visibleRooms, setVisibleRooms, setRoomsAvailability, getFilteredRooms, } = useRoomFilteringStore() const bookingWidgetSearchData = useMemo( () => convertSearchParamsToObj( Object.fromEntries(searchParams) ), [searchParams] ) const isMultipleRooms = bookingWidgetSearchData.rooms.length > 1 useEffect(() => { initializeRates(bookingWidgetSearchData.rooms.length) }, [initializeRates, bookingWidgetSearchData.rooms.length]) const defaultPackages: DefaultFilterOptions[] = useMemo( () => [ { code: RoomPackageCodeEnum.ACCESSIBILITY_ROOM, description: intl.formatMessage({ id: "Accessible Room" }), itemCode: availablePackages.find( (pkg) => pkg.code === RoomPackageCodeEnum.ACCESSIBILITY_ROOM )?.itemCode, }, { code: RoomPackageCodeEnum.ALLERGY_ROOM, description: intl.formatMessage({ id: "Allergy Room" }), itemCode: availablePackages.find( (pkg) => pkg.code === RoomPackageCodeEnum.ALLERGY_ROOM )?.itemCode, }, { code: RoomPackageCodeEnum.PET_ROOM, description: intl.formatMessage({ id: "Pet Room" }), itemCode: availablePackages.find( (pkg) => pkg.code === RoomPackageCodeEnum.PET_ROOM )?.itemCode, }, ], [availablePackages, intl] ) useEffect(() => { setRoomsAvailability(roomsAvailability) setVisibleRooms() }, [roomsAvailability, setRoomsAvailability, setVisibleRooms]) useEffect(() => { if ( selectedRates.length > 0 && selectedRates.some((rate) => rate !== undefined) ) { calculateRateSummary({ getFilteredRooms, availablePackages, roomCategories, selectedPackagesByRoom, }) } }, [ selectedRates, getFilteredRooms, availablePackages, roomCategories, selectedPackagesByRoom, calculateRateSummary, ]) useEffect(() => { if (!rateSummary?.some((rate) => rate === null)) return const hasAnySelection = selectedRates.some((rate) => rate !== undefined) if (!hasAnySelection) return }, [rateSummary, selectedRates]) useEffect(() => { const pricesWithCurrencies = visibleRooms.flatMap((room) => room.products.map((product) => ({ price: product.productType.public.localPrice.pricePerNight, currency: product.productType.public.localPrice.currency, })) ) const lowestPrice = pricesWithCurrencies.reduce( (minPrice, { price }) => Math.min(minPrice, price), Infinity ) const currency = pricesWithCurrencies[0]?.currency trackLowestRoomPrice({ hotelId, arrivalDate, departureDate, lowestPrice: lowestPrice, currency: currency, }) }, [arrivalDate, departureDate, hotelId, visibleRooms]) const queryParams = useMemo(() => { const rooms = rateSummary.map((rate, index) => ({ roomTypeCode: rate?.roomTypeCode, rateCode: rate?.public.rateCode, counterRateCode: rate?.member?.rateCode, packages: selectedPackagesByRoom[index] || [], })) const newSearchParams = convertObjToSearchParams({ rooms }, searchParams) return newSearchParams }, [searchParams, rateSummary, selectedPackagesByRoom]) function handleSubmit(e: React.FormEvent) { e.preventDefault() window.history.pushState(null, "", `${pathname}?${queryParams.toString()}`) router.push(`select-bed?${queryParams}`) } useEffect(() => { requestAnimationFrame(() => { const SCROLL_OFFSET = 100 const roomElements = document.querySelectorAll(`.${styles.roomContainer}`) const index = selectedRates.findIndex((rate) => rate === undefined) const targetIndex = index === -1 ? selectedRates.length - 1 : index - 1 const selectedRoom = roomElements[targetIndex] if (selectedRoom) { const elementPosition = selectedRoom.getBoundingClientRect().top const offsetPosition = elementPosition + window.scrollY - SCROLL_OFFSET window.scrollTo({ top: offsetPosition, behavior: "smooth", }) } }) }, [selectedRates]) return (
{isMultipleRooms ? ( bookingWidgetSearchData.rooms.map((room, index) => { const classNames = roomSelectionPanelVariants({ active: (index === 0 || selectedRates[index - 1] !== undefined) && selectedRates[index] === undefined, selected: selectedRates[index] !== undefined, }) return (
{selectedRates[index] === undefined && ( {intl.formatMessage( { id: "Room {roomIndex}" }, { roomIndex: index + 1 } )} ,{" "} {intl.formatMessage( { id: room.childrenInRoom?.length ? "{adults} adults, {children} children" : "{adults} adults", }, { adults: room.adults, children: room.childrenInRoom?.length, } )} )}
) }) ) : ( )} {rateSummary && (
)}
) }