"use client" import { animate, motion, scroll, useAnimate } from "framer-motion" import { useEffect, useRef, useState } from "react" import { useIntl } from "react-intl" import { useEnterDetailsStore } from "@/stores/enter-details" import { CheckIcon, ChevronDownIcon } from "@/components/Icons" import Footnote from "@/components/TempDesignSystem/Text/Footnote" import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" 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, }: React.PropsWithChildren) { const intl = useIntl() const currentStep = useEnterDetailsStore((state) => state.currentStep) const [isComplete, setIsComplete] = useState(false) const [isOpen, setIsOpen] = useState(false) const isValid = useEnterDetailsStore((state) => state.isValid[step]) const navigate = useEnterDetailsStore((state) => state.actions.navigate) const { bedType, breakfast } = useEnterDetailsStore((state) => ({ bedType: state.bedType, breakfast: state.breakfast, })) const [title, setTitle] = useState(label) const noBreakfastTitle = intl.formatMessage({ id: "No breakfast" }) const breakfastTitle = intl.formatMessage({ id: "Breakfast buffet" }) const accordionRef = useRef(null) const [scope, animate] = useAnimate() 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]) useEffect(() => { setIsOpen(currentStep === step) }, [currentStep, setIsOpen, step]) useEffect(() => { if (!accordionRef.current) return const animateAccordion = async () => { // Measure the initial position of the accordion const initialOffset = accordionRef.current?.offsetTop || 0 // Start the accordion expansion animation const accordionAnimation = animate( scope.current, { gridTemplateRows: isOpen ? "var(--header-height) 1fr" : "var(--header-height) 0fr", }, { duration: 0.3, ease: "easeInOut" } ) if (isOpen) { // Start scrolling immediately const scrollAnimation = animate( window.scrollY, initialOffset - 100, // 100px offset from top { duration: 0.3, ease: "easeInOut", onUpdate: (latest) => { window.scrollTo(0, latest) }, } ) // Wait for both animations to complete await Promise.all([accordionAnimation, scrollAnimation]) } else { // If closing, just wait for the accordion animation await accordionAnimation } } animateAccordion() }, [isOpen, scope, animate]) function onModify() { navigate(step) } const textColor = isComplete || isOpen ? "uiTextHighContrast" : "baseTextDisabled" return (
{isComplete ? ( ) : null}
{children}
) }