feat: consume serach params in summary and step page
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
import {
|
||||
getHotelData,
|
||||
getProfileSafely,
|
||||
getRoomAvailability,
|
||||
} from "@/lib/trpc/memoizedRequests"
|
||||
import { HotelIncludeEnum } from "@/server/routers/hotels/input"
|
||||
|
||||
import Summary from "@/components/HotelReservation/EnterDetails/Summary"
|
||||
import { getQueryParamsForEnterDetails } from "@/components/HotelReservation/SelectRate/RoomSelection/utils"
|
||||
import { formatNumber } from "@/utils/format"
|
||||
|
||||
import { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||
import { LangParams, PageArgs, SearchParams } from "@/types/params"
|
||||
|
||||
export default async function SummaryPage({
|
||||
params,
|
||||
searchParams,
|
||||
}: PageArgs<LangParams, SearchParams<SelectRateSearchParams>>) {
|
||||
const selectRoomParams = new URLSearchParams(searchParams)
|
||||
const { hotel, adults, children, roomTypeCode, rateCode, fromDate, toDate } =
|
||||
getQueryParamsForEnterDetails(selectRoomParams)
|
||||
|
||||
const user = await getProfileSafely()
|
||||
const hotelData = await getHotelData(hotel, params.lang, undefined, [HotelIncludeEnum.RoomCategories])
|
||||
const availability = await getRoomAvailability({
|
||||
hotelId: parseInt(hotel),
|
||||
adults,
|
||||
children,
|
||||
roomStayStartDate: fromDate,
|
||||
roomStayEndDate: toDate,
|
||||
})
|
||||
|
||||
if (!hotelData?.data || !hotelData?.included || !availability) {
|
||||
console.error("No hotel or availability data", hotelData, availability)
|
||||
|
||||
// TODO: handle this case
|
||||
return null
|
||||
}
|
||||
|
||||
const chosenRoom = availability.roomConfigurations.find(
|
||||
(availRoom) => availRoom.roomTypeCode === roomTypeCode
|
||||
)
|
||||
|
||||
if (!chosenRoom) {
|
||||
// TODO: handle this case
|
||||
console.error("No chosen room", chosenRoom)
|
||||
return null
|
||||
}
|
||||
|
||||
const cancellationText =
|
||||
availability?.rateDefinitions.find((rate) => rate.rateCode === rateCode)
|
||||
?.cancellationText ?? ""
|
||||
|
||||
const memberPrice =
|
||||
chosenRoom.products.find(
|
||||
(rate) => rate.productType.member?.rateCode === rateCode
|
||||
)?.productType.member?.localPrice.pricePerStay ?? "0"
|
||||
|
||||
const publicPrice =
|
||||
chosenRoom.products.find(
|
||||
(rate) => rate.productType.public?.rateCode === rateCode
|
||||
)?.productType.public?.localPrice.pricePerStay ?? "0"
|
||||
|
||||
const price = user ? memberPrice : publicPrice
|
||||
|
||||
return (
|
||||
<Summary
|
||||
isMember={!!user}
|
||||
room={{
|
||||
roomType: chosenRoom.roomType,
|
||||
price: formatNumber(parseInt(price)),
|
||||
adults,
|
||||
cancellationText,
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import EnterDetailsProvider from "@/components/HotelReservation/EnterDetails/Provider"
|
||||
import SelectedRoom from "@/components/HotelReservation/EnterDetails/SelectedRoom"
|
||||
import Summary from "@/components/HotelReservation/EnterDetails/Summary"
|
||||
import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
import { preload } from "./page"
|
||||
@@ -11,6 +10,7 @@ import { StepEnum } from "@/types/components/hotelReservation/enterDetails/step"
|
||||
import type { LangParams, LayoutArgs } from "@/types/params"
|
||||
|
||||
export default async function StepLayout({
|
||||
summary,
|
||||
children,
|
||||
hotelHeader,
|
||||
params,
|
||||
@@ -19,6 +19,7 @@ export default async function StepLayout({
|
||||
LayoutArgs<LangParams & { step: StepEnum }> & {
|
||||
hotelHeader: React.ReactNode
|
||||
sidePeek: React.ReactNode
|
||||
summary: React.ReactNode
|
||||
}>) {
|
||||
setLang(params.lang)
|
||||
preload()
|
||||
@@ -29,9 +30,7 @@ export default async function StepLayout({
|
||||
<div className={styles.content}>
|
||||
<SelectedRoom />
|
||||
{children}
|
||||
<aside className={styles.summary}>
|
||||
<Summary isMember={false} />
|
||||
</aside>
|
||||
<aside className={styles.summary}>{summary}</aside>
|
||||
</div>
|
||||
{sidePeek}
|
||||
</main>
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
getProfileSafely,
|
||||
getRoomAvailability,
|
||||
} from "@/lib/trpc/memoizedRequests"
|
||||
import { HotelIncludeEnum } from "@/server/routers/hotels/input"
|
||||
|
||||
import BedType from "@/components/HotelReservation/EnterDetails/BedType"
|
||||
import Breakfast from "@/components/HotelReservation/EnterDetails/Breakfast"
|
||||
@@ -14,11 +15,12 @@ import Details from "@/components/HotelReservation/EnterDetails/Details"
|
||||
import HistoryStateManager from "@/components/HotelReservation/EnterDetails/HistoryStateManager"
|
||||
import Payment from "@/components/HotelReservation/EnterDetails/Payment"
|
||||
import SectionAccordion from "@/components/HotelReservation/EnterDetails/SectionAccordion"
|
||||
import getHotelReservationQueryParams from "@/components/HotelReservation/SelectRate/RoomSelection/utils"
|
||||
import { getQueryParamsForEnterDetails } from "@/components/HotelReservation/SelectRate/RoomSelection/utils"
|
||||
import { getIntl } from "@/i18n"
|
||||
|
||||
import { StepEnum } from "@/types/components/hotelReservation/enterDetails/step"
|
||||
import type { LangParams, PageArgs } from "@/types/params"
|
||||
import { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||
import type { LangParams, PageArgs, } from "@/types/params"
|
||||
|
||||
export function preload() {
|
||||
void getProfileSafely()
|
||||
@@ -32,35 +34,52 @@ function isValidStep(step: string): step is StepEnum {
|
||||
export default async function StepPage({
|
||||
params,
|
||||
searchParams,
|
||||
}: PageArgs<LangParams & { step: StepEnum }, { hotel: string }>) {
|
||||
}: PageArgs<
|
||||
LangParams & { step: StepEnum },
|
||||
SelectRateSearchParams
|
||||
>) {
|
||||
if (!searchParams.hotel) {
|
||||
redirect(`/${params.lang}`)
|
||||
}
|
||||
void getBreakfastPackages(searchParams.hotel)
|
||||
const stepParams = new URLSearchParams(searchParams)
|
||||
const paramsObject = getHotelReservationQueryParams(stepParams)
|
||||
void getRoomAvailability({
|
||||
hotelId: paramsObject.hotel,
|
||||
adults: paramsObject.room[0].adults,
|
||||
roomStayStartDate: paramsObject.fromDate,
|
||||
roomStayEndDate: paramsObject.toDate,
|
||||
})
|
||||
const intl = await getIntl()
|
||||
|
||||
const hotel = await getHotelData(searchParams.hotel, params.lang)
|
||||
const intl = await getIntl()
|
||||
const selectRoomParams = new URLSearchParams(searchParams)
|
||||
const {
|
||||
hotel: hotelId,
|
||||
adults,
|
||||
children,
|
||||
roomTypeCode,
|
||||
rateCode,
|
||||
fromDate,
|
||||
toDate,
|
||||
} = getQueryParamsForEnterDetails(selectRoomParams)
|
||||
|
||||
void getRoomAvailability({
|
||||
hotelId: parseInt(hotelId),
|
||||
adults,
|
||||
children,
|
||||
roomStayStartDate: fromDate,
|
||||
roomStayEndDate: toDate,
|
||||
rateCode
|
||||
})
|
||||
|
||||
const hotelData = await getHotelData(hotelId, params.lang, undefined, [HotelIncludeEnum.RoomCategories])
|
||||
|
||||
const user = await getProfileSafely()
|
||||
const savedCreditCards = await getCreditCardsSafely()
|
||||
const breakfastPackages = await getBreakfastPackages(searchParams.hotel)
|
||||
|
||||
const roomAvailability = await getRoomAvailability({
|
||||
hotelId: paramsObject.hotel,
|
||||
adults: paramsObject.room[0].adults,
|
||||
roomStayStartDate: paramsObject.fromDate,
|
||||
roomStayEndDate: paramsObject.toDate,
|
||||
rateCode: paramsObject.room[0].ratecode,
|
||||
hotelId: parseInt(hotelId),
|
||||
adults,
|
||||
children,
|
||||
roomStayStartDate: fromDate,
|
||||
roomStayEndDate: toDate,
|
||||
rateCode
|
||||
})
|
||||
|
||||
if (!isValidStep(params.step) || !hotel || !roomAvailability) {
|
||||
if (!isValidStep(params.step) || !hotelData || !roomAvailability) {
|
||||
return notFound()
|
||||
}
|
||||
|
||||
@@ -79,16 +98,32 @@ export default async function StepPage({
|
||||
id: "Select payment method",
|
||||
})
|
||||
|
||||
const availableRoom = roomAvailability?.roomConfigurations
|
||||
.filter((room) => room.status === "Available")
|
||||
.find((room) => room.roomTypeCode === roomTypeCode)?.roomType
|
||||
const roomTypes = hotelData.included
|
||||
?.find((room) => room.name === availableRoom)
|
||||
?.roomTypes.map((room) => ({
|
||||
description: room.mainBed.description,
|
||||
size: room.mainBed.widthRange,
|
||||
value: room.code,
|
||||
}))
|
||||
|
||||
return (
|
||||
<section>
|
||||
<HistoryStateManager />
|
||||
<SectionAccordion
|
||||
header={intl.formatMessage({ id: "Select bed" })}
|
||||
step={StepEnum.selectBed}
|
||||
label={intl.formatMessage({ id: "Request bedtype" })}
|
||||
>
|
||||
<BedType />
|
||||
</SectionAccordion>
|
||||
|
||||
{/* TODO: How to handle no beds found? */}
|
||||
{roomTypes ? (
|
||||
<SectionAccordion
|
||||
header="Select bed"
|
||||
step={StepEnum.selectBed}
|
||||
label={intl.formatMessage({ id: "Request bedtype" })}
|
||||
>
|
||||
<BedType roomTypes={roomTypes} />
|
||||
</SectionAccordion>
|
||||
) : null}
|
||||
|
||||
<SectionAccordion
|
||||
header={intl.formatMessage({ id: "Food options" })}
|
||||
step={StepEnum.breakfast}
|
||||
@@ -111,13 +146,13 @@ export default async function StepPage({
|
||||
<Payment
|
||||
hotelId={searchParams.hotel}
|
||||
otherPaymentOptions={
|
||||
hotel.data.attributes.merchantInformationData
|
||||
hotelData.data.attributes.merchantInformationData
|
||||
.alternatePaymentOptions
|
||||
}
|
||||
savedCreditCards={savedCreditCards}
|
||||
mustBeGuaranteed={mustBeGuaranteed}
|
||||
/>
|
||||
</SectionAccordion>
|
||||
</section>
|
||||
</section >
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
} from "@/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/utils"
|
||||
import HotelCardListing from "@/components/HotelReservation/HotelCardListing"
|
||||
import HotelFilter from "@/components/HotelReservation/SelectHotel/HotelFilter"
|
||||
import getHotelReservationQueryParams from "@/components/HotelReservation/SelectRate/RoomSelection/utils"
|
||||
import { getHotelReservationQueryParams } from "@/components/HotelReservation/SelectRate/RoomSelection/utils"
|
||||
import { ChevronRightIcon } from "@/components/Icons"
|
||||
import StaticMap from "@/components/Maps/StaticMap"
|
||||
import Link from "@/components/TempDesignSystem/Link"
|
||||
|
||||
@@ -2,10 +2,11 @@ import { notFound } from "next/navigation"
|
||||
|
||||
import { getProfileSafely } from "@/lib/trpc/memoizedRequests"
|
||||
import { serverClient } from "@/lib/trpc/server"
|
||||
import { HotelIncludeEnum } from "@/server/routers/hotels/input"
|
||||
|
||||
import HotelInfoCard from "@/components/HotelReservation/SelectRate/HotelInfoCard"
|
||||
import Rooms from "@/components/HotelReservation/SelectRate/Rooms"
|
||||
import getHotelReservationQueryParams from "@/components/HotelReservation/SelectRate/RoomSelection/utils"
|
||||
import { getHotelReservationQueryParams } from "@/components/HotelReservation/SelectRate/RoomSelection/utils"
|
||||
import { setLang } from "@/i18n/serverContext"
|
||||
|
||||
import { generateChildrenString } from "../select-hotel/utils"
|
||||
@@ -38,7 +39,7 @@ export default async function SelectRatePage({
|
||||
serverClient().hotel.hotelData.get({
|
||||
hotelId: searchParams.hotel,
|
||||
language: params.lang,
|
||||
include: ["RoomCategories"],
|
||||
include: [HotelIncludeEnum.RoomCategories],
|
||||
}),
|
||||
serverClient().hotel.availability.rooms({
|
||||
hotelId: parseInt(searchParams.hotel, 10),
|
||||
|
||||
Reference in New Issue
Block a user