diff --git a/components/HotelReservation/EnterDetails/SectionAccordion/index.tsx b/components/HotelReservation/EnterDetails/SectionAccordion/index.tsx index f9a68d2bb..0ab7d589c 100644 --- a/components/HotelReservation/EnterDetails/SectionAccordion/index.tsx +++ b/components/HotelReservation/EnterDetails/SectionAccordion/index.tsx @@ -1,6 +1,5 @@ "use client" -import { animate, motion, scroll, useAnimate } from "framer-motion" -import { useEffect, useRef, useState } from "react" +import { useCallback, useEffect, useRef, useState } from "react" import { useIntl } from "react-intl" import { useEnterDetailsStore } from "@/stores/enter-details" @@ -14,6 +13,55 @@ import styles from "./sectionAccordion.module.css" import type { SectionAccordionProps } from "@/types/components/hotelReservation/selectRate/sectionAccordion" import { StepEnum } from "@/types/enums/step" +function useScrollToActiveSection( + step: StepEnum, + steps: StepEnum[], + isActive: boolean +) { + const handleScroll = useCallback(() => { + const isMobile = window.matchMedia("(max-width: 768px)").matches + if (!isMobile) return + + const currentElement = document.querySelector( + `[data-step="${step}"]` + ) + const prevOpenElement = + document.querySelector(`[data-open="true"]`) + + const currentStepIndex = steps.indexOf(step) + const prevStep = prevOpenElement?.dataset.step as StepEnum + const prevStepIndex = steps.indexOf(prevStep) + + if (currentElement) { + const BOOKING_WIDGET_OFFSET = 71 + + const prevElementContent = prevOpenElement?.querySelector("header + div") + + let collapsedSpace = 0 + if (prevElementContent && prevStepIndex < currentStepIndex) { + collapsedSpace = prevElementContent.clientHeight + } + + const currentElementTop = + currentElement.getBoundingClientRect().top + window.scrollY + + const scrollTarget = Math.round( + currentElementTop - BOOKING_WIDGET_OFFSET - collapsedSpace + ) + + window.scrollTo({ + top: scrollTarget, + behavior: "smooth", + }) + } + }, [step, steps]) + + useEffect(() => { + if (!isActive) return + handleScroll() + }, [isActive, handleScroll]) +} + export default function SectionAccordion({ children, header, @@ -22,6 +70,7 @@ export default function SectionAccordion({ }: React.PropsWithChildren) { const intl = useIntl() const currentStep = useEnterDetailsStore((state) => state.currentStep) + const steps = useEnterDetailsStore((state) => state.steps) const [isComplete, setIsComplete] = useState(false) const [isOpen, setIsOpen] = useState(false) const isValid = useEnterDetailsStore((state) => state.isValid[step]) @@ -35,6 +84,8 @@ export default function SectionAccordion({ const noBreakfastTitle = intl.formatMessage({ id: "No breakfast" }) const breakfastTitle = intl.formatMessage({ id: "Breakfast buffet" }) + useScrollToActiveSection(step, steps, currentStep === step) + useEffect(() => { if (step === StepEnum.selectBed && bedType) { setTitle(bedType.description) diff --git a/stores/enter-details/helpers.ts b/stores/enter-details/helpers.ts index e01aa2a63..f76caeb19 100644 --- a/stores/enter-details/helpers.ts +++ b/stores/enter-details/helpers.ts @@ -42,16 +42,6 @@ export function extractGuestFromUser(user: NonNullable) { export function navigate(step: StepEnum, searchParams: string) { window.history.pushState({ step }, "", `${step}?${searchParams}`) - - const element = document.querySelector(`[data-step='${step}']`) - const isMobile = window.matchMedia("(max-width: 768px)").matches - if (element && isMobile) { - element.addEventListener( - "transitionend", - () => element?.scrollIntoView({ behavior: "smooth" }), - { once: true } - ) - } } export function checkIsSameBooking(prev: BookingData, next: BookingData) {