diff --git a/components/HotelReservation/SelectRate/RateSummary/index.tsx b/components/HotelReservation/SelectRate/RateSummary/index.tsx index f26c4da87..bf4b6f9f3 100644 --- a/components/HotelReservation/SelectRate/RateSummary/index.tsx +++ b/components/HotelReservation/SelectRate/RateSummary/index.tsx @@ -31,6 +31,7 @@ export default function RateSummary({ return () => clearTimeout(timer) }, []) + if (rateSummary.length === 0) return null const { member, public: publicRate, @@ -38,7 +39,7 @@ export default function RateSummary({ roomType, priceName, priceTerm, - } = rateSummary + } = rateSummary[0] // TODO: Support multiple rooms const isPetRoomSelected = features.some( (feature) => feature.code === RoomPackageCodeEnum.PET_ROOM diff --git a/components/HotelReservation/SelectRate/RoomFilter/index.tsx b/components/HotelReservation/SelectRate/RoomFilter/index.tsx index f1f2f26be..f8eb91356 100644 --- a/components/HotelReservation/SelectRate/RoomFilter/index.tsx +++ b/components/HotelReservation/SelectRate/RoomFilter/index.tsx @@ -2,7 +2,7 @@ import { zodResolver } from "@hookform/resolvers/zod" import { useSearchParams } from "next/navigation" -import { useCallback, useEffect, useMemo, useState } from "react" +import { useCallback, useEffect, useMemo, useRef, useState } from "react" import { FormProvider, useForm } from "react-hook-form" import { useIntl } from "react-intl" import { useMediaQuery } from "usehooks-ts" @@ -26,26 +26,34 @@ export default function RoomFilter({ numberOfRooms, onFilter, filterOptions, + roomListIndex, }: RoomFilterProps) { const isTabletAndUp = useMediaQuery("(min-width: 768px)") const [isAboveMobile, setIsAboveMobile] = useState(false) + const onFilterRef = useRef(onFilter) const searchParams = useSearchParams() + const initialFilterValues = useMemo(() => { const packagesFromSearchParams = - searchParams.get("room[0].packages")?.split(",") ?? [] + searchParams.get(`room[${roomListIndex}].packages`)?.split(",") ?? [] - const values = filterOptions.reduce( + return filterOptions.reduce( (acc, option) => { acc[option.code] = packagesFromSearchParams.includes(option.code) return acc }, {} as Record ) + }, [filterOptions, searchParams, roomListIndex]) - onFilter(values) - return values - }, [filterOptions, onFilter, searchParams]) + useEffect(() => { + onFilterRef.current = onFilter + }, [onFilter]) + + useEffect(() => { + onFilterRef.current(initialFilterValues) + }, [initialFilterValues]) const intl = useIntl() const methods = useForm>({ @@ -64,15 +72,19 @@ export default function RoomFilter({ const tooltipText = intl.formatMessage({ id: "Pet-friendly rooms have an additional fee of 20 EUR per stay", }) - const submitFilter = useCallback(() => { - const data = getValues() - onFilter(data) - }, [onFilter, getValues]) + const submitFilter = useCallback( + (data: Record) => { + onFilter(data) + }, + [onFilter] + ) useEffect(() => { - const subscription = watch(() => handleSubmit(submitFilter)()) + const subscription = watch((_, { name }) => { + if (name) submitFilter(getValues()) + }) return () => subscription.unsubscribe() - }, [handleSubmit, watch, submitFilter]) + }, [watch, submitFilter, getValues]) useEffect(() => { setIsAboveMobile(isTabletAndUp) diff --git a/components/HotelReservation/SelectRate/RoomList/FlexibilityOption/index.tsx b/components/HotelReservation/SelectRate/RoomList/FlexibilityOption/index.tsx index c29619c10..a79227d0a 100644 --- a/components/HotelReservation/SelectRate/RoomList/FlexibilityOption/index.tsx +++ b/components/HotelReservation/SelectRate/RoomList/FlexibilityOption/index.tsx @@ -4,7 +4,7 @@ import { useSearchParams } from "next/navigation" import { useEffect, useRef } from "react" import { useIntl } from "react-intl" -import { CheckCircleIcon, CheckIcon, InfoCircleIcon } from "@/components/Icons" +import { CheckIcon, InfoCircleIcon } from "@/components/Icons" import Modal from "@/components/Modal" import Button from "@/components/TempDesignSystem/Button" import Label from "@/components/TempDesignSystem/Form/Label" @@ -25,9 +25,15 @@ export default function FlexibilityOption({ roomTypeCode, petRoomPackage, handleSelectRate, + roomListIndex, }: FlexibilityOptionProps) { const intl = useIntl() const inputElementRef = useRef(null) + const handleSelectRateRef = useRef(handleSelectRate) + + useEffect(() => { + handleSelectRateRef.current = handleSelectRate + }, [handleSelectRate]) const searchParams = useSearchParams() @@ -35,8 +41,12 @@ export default function FlexibilityOption({ // want to preselect the selection. This happens e.g. when you do a selection, // go to the enter details page and then want to change the room. useEffect(() => { - const ratecodeSearchParam = searchParams.get("room[0].ratecode") - const roomtypeSearchParam = searchParams.get("room[0].roomtype") + const ratecodeSearchParam = searchParams.get( + `room[${roomListIndex}].ratecode` + ) + const roomtypeSearchParam = searchParams.get( + `room[${roomListIndex}].roomtype` + ) // If this is not the room and rate we want to preselect, abort if ( @@ -47,7 +57,7 @@ export default function FlexibilityOption({ return } - handleSelectRate((prev) => { + handleSelectRateRef.current((prev) => { // If the user already has made a new selection we respect that and don't do anything else if (prev) { return prev @@ -64,7 +74,7 @@ export default function FlexibilityOption({ paymentTerm: paymentTerm, } }) - }, [handleSelectRate, name, paymentTerm, product, roomTypeCode, searchParams]) + }, [searchParams, roomListIndex, product, roomTypeCode, name, paymentTerm]) if (!product) { return ( @@ -88,7 +98,7 @@ export default function FlexibilityOption({ const { public: publicPrice, member: memberPrice } = product.productType const onClick: React.MouseEventHandler = (e) => { - handleSelectRate((prev) => { + handleSelectRateRef.current((prev) => { if ( prev && prev.publicRateCode === publicPrice.rateCode && @@ -110,7 +120,7 @@ export default function FlexibilityOption({