"use client" import { notFound } from "next/navigation" import { use, useRef } from "react" import { useIntl } from "react-intl" import { dt } from "@scandic-hotels/common/dt" import { trpc } from "@scandic-hotels/trpc/client" import { createMyStayStore } from "@/stores/my-stay" import { MyStaySkeleton } from "@/components/HotelReservation/MyStay/myStaySkeleton" import { MyStayContext } from "@/contexts/MyStay" import type { Lang } from "@scandic-hotels/common/constants/language" import type { BookingConfirmation, BookingConfirmationSchema, } from "@scandic-hotels/trpc/types/bookingConfirmation" import type { RoomCategories } from "@scandic-hotels/trpc/types/hotel" import type { CreditCard } from "@scandic-hotels/trpc/types/user" import type { Packages } from "@/types/components/myPages/myStay/ancillaries" import type { MyStayStore } from "@/types/contexts/my-stay" interface MyStayProviderProps { bookingConfirmation: BookingConfirmation breakfastPackages: Packages | null isLoggedIn?: boolean lang: Lang linkedReservationsPromise: Promise refId: string roomCategories: RoomCategories savedCreditCards: CreditCard[] | null } export default function MyStayProvider({ bookingConfirmation, breakfastPackages, children, lang, linkedReservationsPromise, refId, roomCategories, savedCreditCards, isLoggedIn, }: React.PropsWithChildren) { const storeRef = useRef(undefined) const intl = useIntl() const { data, error, isFetching, isFetchedAfterMount } = trpc.booking.get.useQuery( { refId: bookingConfirmation.booking.refId, lang, }, { initialData: bookingConfirmation, refetchOnMount: false, refetchOnWindowFocus: false, } ) // We need this two-step business since `use` must resolve // the promise passed from the server whereas `useQuery` // needs to own the data when in the client so that invalidations // actually triggers a refetch of the data const linkedReservationsResponses = use(linkedReservationsPromise) const { data: linkedReservations, error: linkedReservationsError, isFetching: linkedReservationsIsFetching, isFetchedAfterMount: linkedReservationsIsFetchedAfterMount, } = trpc.booking.linkedReservations.useQuery( { lang, refId: bookingConfirmation.booking.refId, }, { initialData: linkedReservationsResponses, refetchOnMount: false, refetchOnWindowFocus: false, } ) if (isFetching || linkedReservationsIsFetching) { return } if (!data || error || linkedReservationsError) { return notFound() } const rooms = [data.booking, ...linkedReservations] // Following the API logic for determining if booking is in the past. // This is the same logic as used for separating stays in /future and /past endpoints on the API const now = dt() const isPastBooking = dt(data.booking.checkOutDate).isBefore(now, "day") const hasInvalidatedQueryAndRefetched = (isFetchedAfterMount && data) || (linkedReservationsIsFetchedAfterMount && linkedReservations) // eslint-disable-next-line react-hooks/refs if (!storeRef.current || hasInvalidatedQueryAndRefetched) { storeRef.current = createMyStayStore({ breakfastPackages, hotel: bookingConfirmation.hotel, intl, refId, roomCategories, rooms, savedCreditCards, isLoggedIn, isPastBooking, }) } return ( // eslint-disable-next-line react-hooks/refs {children} ) }