"use client" import { useEffect, useRef, useState } from "react" import { useIntl } from "react-intl" import { useEnterDetailsStore } from "@/stores/enter-details" import { selectBookingProgress, selectRoom, selectRoomStatus, } from "@/stores/enter-details/helpers" import { CheckIcon, ChevronDownIcon } from "@/components/Icons" import Footnote from "@/components/TempDesignSystem/Text/Footnote" import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" import useStickyPosition from "@/hooks/useStickyPosition" import styles from "./sectionAccordion.module.css" import type { SectionAccordionProps } from "@/types/components/hotelReservation/selectRate/sectionAccordion" import { StepEnum } from "@/types/enums/step" export default function SectionAccordion({ children, header, label, step, roomIndex, }: React.PropsWithChildren) { const intl = useIntl() const roomStatus = useEnterDetailsStore((state) => selectRoomStatus(state, roomIndex) ) const stickyPosition = useStickyPosition({}) const setStep = useEnterDetailsStore((state) => state.actions.setStep) const { bedType, breakfast } = useEnterDetailsStore((state) => selectRoom(state, roomIndex) ) const { roomStatuses, currentRoomIndex } = useEnterDetailsStore((state) => selectBookingProgress(state) ) const [isComplete, setIsComplete] = useState(false) const [isOpen, setIsOpen] = useState(false) const isValid = roomStatus.steps[step]?.isValid ?? false const [title, setTitle] = useState(label) const noBreakfastTitle = intl.formatMessage({ id: "No breakfast" }) const breakfastTitle = intl.formatMessage({ id: "Breakfast buffet" }) // useScrollToActiveSection(step, steps, roomStatus.currentStep === step) useEffect(() => { if (step === StepEnum.selectBed && bedType) { setTitle(bedType.description) } // If breakfast step, check if an option has been selected if (step === StepEnum.breakfast && breakfast !== undefined) { if (breakfast === false) { setTitle(noBreakfastTitle) } else { setTitle(breakfastTitle) } } }, [bedType, breakfast, setTitle, step, breakfastTitle, noBreakfastTitle]) useEffect(() => { setIsComplete(isValid) }, [isValid, setIsComplete]) const accordionRef = useRef(null) useEffect(() => { const shouldBeOpen = roomStatus.currentStep === step && currentRoomIndex === roomIndex setIsOpen(shouldBeOpen) // Scroll to this section when it is opened, but wait for the accordion animations to // finish, else the height calculations will not be correct and the scroll position // will be off. if (shouldBeOpen) { setTimeout(() => { if (accordionRef.current) { window.scrollTo({ top: accordionRef.current.offsetTop - stickyPosition.getTopOffset(), behavior: "smooth", }) } }, 250) } // eslint-disable-next-line react-hooks/exhaustive-deps }, [currentRoomIndex, roomIndex, roomStatus.currentStep, setIsOpen, step]) function onModify() { setStep(step, roomIndex) } function close() { setIsOpen(false) const nextRoom = roomStatuses.find((room) => !room.isComplete) const nextStep = nextRoom ? Object.values(nextRoom.steps).find((step) => !step.isValid)?.step : null if (nextRoom !== undefined && nextStep !== undefined) { setStep(nextStep, roomStatuses.indexOf(nextRoom)) } else { // Time for payment, collapse any open step setStep(null) } } const textColor = isComplete || isOpen ? "uiTextHighContrast" : "baseTextDisabled" return (
{isComplete ? ( ) : null}
{children}
) }