fix: load room availability separately

This commit is contained in:
Joakim Jäderberg
2024-11-18 15:25:46 +01:00
parent 260be9b641
commit 4b6abb0a31
2 changed files with 80 additions and 98 deletions

View File

@@ -1,22 +1,16 @@
import { notFound } from "next/navigation" import { notFound } from "next/navigation"
import { Suspense } from "react"
import { dt } from "@/lib/dt" import { dt } from "@/lib/dt"
import { import { getHotelData, getLocations } from "@/lib/trpc/memoizedRequests"
getHotelData,
getLocations,
getProfileSafely,
} from "@/lib/trpc/memoizedRequests"
import { serverClient } from "@/lib/trpc/server"
import LoadingSpinner from "@/components/Current/LoadingSpinner"
import HotelInfoCard from "@/components/HotelReservation/SelectRate/HotelInfoCard" import HotelInfoCard from "@/components/HotelReservation/SelectRate/HotelInfoCard"
import Rooms from "@/components/HotelReservation/SelectRate/Rooms" import { RoomsContainer } from "@/components/HotelReservation/SelectRate/Rooms/RoomsContainer"
import { import { getHotelReservationQueryParams } from "@/components/HotelReservation/SelectRate/RoomSelection/utils"
generateChildrenString,
getHotelReservationQueryParams,
} from "@/components/HotelReservation/SelectRate/RoomSelection/utils"
import { setLang } from "@/i18n/serverContext" import { setLang } from "@/i18n/serverContext"
import { safeTry } from "@/utils/safeTry"
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate" import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
import type { LangParams, PageArgs } from "@/types/params" import type { LangParams, PageArgs } from "@/types/params"
@@ -45,71 +39,48 @@ export default async function SelectRatePage({
return notFound() return notFound()
} }
const validFromDate = const fromDate =
searchParams.fromDate && searchParams.fromDate &&
dt(searchParams.fromDate).isAfter(dt().subtract(1, "day")) dt(searchParams.fromDate).isAfter(dt().subtract(1, "day"))
? searchParams.fromDate ? dt(searchParams.fromDate)
: dt().utc().format("YYYY-MM-DD") : dt().utc()
const validToDate = const toDate =
searchParams.toDate && dt(searchParams.toDate).isAfter(validFromDate) searchParams.toDate && dt(searchParams.toDate).isAfter(fromDate)
? searchParams.toDate ? dt(searchParams.toDate)
: dt().utc().add(1, "day").format("YYYY-MM-DD") : dt().utc().add(1, "day")
const adults = selectRoomParamsObject.room[0].adults || 1 // TODO: Handle multiple rooms const adults = selectRoomParamsObject.room[0].adults || 1 // TODO: Handle multiple rooms
const childrenCount = selectRoomParamsObject.room[0].child?.length const children = selectRoomParamsObject.room[0].child // TODO: Handle multiple rooms
const children = selectRoomParamsObject.room[0].child
? generateChildrenString(selectRoomParamsObject.room[0].child)
: undefined // TODO: Handle multiple rooms
const [hotelData, roomsAvailability, packages, user] = await Promise.all([ const [hotelData, hotelDataError] = await safeTry(
getHotelData({ hotelId: searchParams.hotel, language: params.lang }), getHotelData({ hotelId: searchParams.hotel, language: params.lang })
serverClient().hotel.availability.rooms({
hotelId: parseInt(searchParams.hotel, 10),
roomStayStartDate: validFromDate,
roomStayEndDate: validToDate,
adults,
children,
}),
serverClient().hotel.packages.get({
hotelId: searchParams.hotel,
startDate: searchParams.fromDate,
endDate: searchParams.toDate,
adults,
children: childrenCount,
packageCodes: [
RoomPackageCodeEnum.ACCESSIBILITY_ROOM,
RoomPackageCodeEnum.PET_ROOM,
RoomPackageCodeEnum.ALLERGY_ROOM,
],
}),
getProfileSafely(),
])
if (!roomsAvailability) {
return "No rooms found" // TODO: Add a proper error message
}
if (!hotelData) {
return "No hotel data found" // TODO: Add a proper error message
}
const roomCategories = hotelData?.included
const noRoomsAvailable = roomsAvailability.roomConfigurations.reduce(
(acc, room) => {
return acc && room.status === "NotAvailable"
},
true
) )
if (!hotelData && !hotelDataError) {
return notFound()
}
const hotelId = +searchParams.hotel
return ( return (
<> <>
<HotelInfoCard hotelData={hotelData} noAvailability={noRoomsAvailable} /> <HotelInfoCard
<Rooms hotelId={hotelId}
roomsAvailability={roomsAvailability} lang={params.lang}
roomCategories={roomCategories ?? []} fromDate={fromDate.toDate()}
user={user} toDate={toDate.toDate()}
packages={packages ?? []} adultCount={adults}
childArray={children ?? []}
/> />
<Suspense key={hotelId} fallback={<LoadingSpinner />}>
<RoomsContainer
hotelId={hotelId}
lang={params.lang}
fromDate={fromDate.toDate()}
toDate={toDate.toDate()}
adultCount={adults}
childArray={children ?? []}
/>
</Suspense>
</> </>
) )
} }

View File

@@ -1,7 +1,8 @@
"use client" import { Suspense, useEffect } from "react"
import { useEffect } from "react"
import { useIntl } from "react-intl" import { useIntl } from "react-intl"
import { Lang } from "@/constants/languages"
import { getHotelData } from "@/lib/trpc/memoizedRequests"
import useRoomAvailableStore from "@/stores/roomAvailability" import useRoomAvailableStore from "@/stores/roomAvailability"
import { mapFacilityToIcon } from "@/components/ContentType/HotelPage/data" import { mapFacilityToIcon } from "@/components/ContentType/HotelPage/data"
@@ -11,38 +12,54 @@ import Divider from "@/components/TempDesignSystem/Divider"
import Body from "@/components/TempDesignSystem/Text/Body" import Body from "@/components/TempDesignSystem/Text/Body"
import Caption from "@/components/TempDesignSystem/Text/Caption" import Caption from "@/components/TempDesignSystem/Text/Caption"
import Title from "@/components/TempDesignSystem/Text/Title" import Title from "@/components/TempDesignSystem/Text/Title"
import { getIntl } from "@/i18n"
import ReadMore from "../../ReadMore" import ReadMore from "../../ReadMore"
import TripAdvisorChip from "../../TripAdvisorChip" import TripAdvisorChip from "../../TripAdvisorChip"
import { NoRoomsAlert } from "./NoRoomsAlert"
import styles from "./hotelInfoCard.module.css" import styles from "./hotelInfoCard.module.css"
import type { HotelInfoCardProps } from "@/types/components/hotelReservation/selectRate/hotelInfoCardProps" import { Child } from "@/types/components/hotelReservation/selectRate/selectRate"
import { AlertTypeEnum } from "@/types/enums/alert"
type Props = {
hotelId: number
lang: Lang
fromDate: Date
toDate: Date
adultCount: number
childArray: Child[]
}
export default async function HotelInfoCard({
hotelId,
lang,
...props
}: Props) {
const hotelData = await getHotelData({
hotelId: hotelId.toString(),
language: lang,
})
export default function HotelInfoCard({
hotelData,
noAvailability = false,
}: HotelInfoCardProps) {
const hotelAttributes = hotelData?.data.attributes const hotelAttributes = hotelData?.data.attributes
const intl = useIntl() const intl = await getIntl()
const noRoomsAvailable = useRoomAvailableStore( // const noRoomsAvailable = useRoomAvailableStore(
(state) => state.noRoomsAvailable // (state) => state.noRoomsAvailable
) // )
const setNoRoomsAvailable = useRoomAvailableStore( // const setNoRoomsAvailable = useRoomAvailableStore(
(state) => state.setNoRoomsAvailable // (state) => state.setNoRoomsAvailable
) // )
const sortedFacilities = hotelAttributes?.detailedFacilities const sortedFacilities = hotelAttributes?.detailedFacilities
.sort((a, b) => b.sortOrder - a.sortOrder) .sort((a, b) => b.sortOrder - a.sortOrder)
.slice(0, 5) .slice(0, 5)
useEffect(() => { // useEffect(() => {
if (noAvailability) { // if (noAvailability) {
setNoRoomsAvailable() // setNoRoomsAvailable()
} // }
}, [noAvailability, setNoRoomsAvailable]) // }, [noAvailability, setNoRoomsAvailable])
return ( return (
<article className={styles.container}> <article className={styles.container}>
@@ -117,16 +134,10 @@ export default function HotelInfoCard({
</div> </div>
) )
})} })}
{noRoomsAvailable ? (
<div className={styles.hotelAlert}> <Suspense fallback={null} key={hotelId}>
<Alert <NoRoomsAlert hotelId={hotelId} lang={lang} {...props} />
type={AlertTypeEnum.Info} </Suspense>
text={intl.formatMessage({
id: "There are no rooms available that match your request",
})}
/>
</div>
) : null}
</article> </article>
) )
} }