feat: add multiroom signup
This commit is contained in:
@@ -9,48 +9,33 @@ import {
|
||||
getSelectedRoomAvailability,
|
||||
} from "@/lib/trpc/memoizedRequests"
|
||||
|
||||
import BedType from "@/components/HotelReservation/EnterDetails/BedType"
|
||||
import Breakfast from "@/components/HotelReservation/EnterDetails/Breakfast"
|
||||
import Details from "@/components/HotelReservation/EnterDetails/Details"
|
||||
import HotelHeader from "@/components/HotelReservation/EnterDetails/Header"
|
||||
import Payment from "@/components/HotelReservation/EnterDetails/Payment"
|
||||
import SectionAccordion from "@/components/HotelReservation/EnterDetails/SectionAccordion"
|
||||
import SelectedRoom from "@/components/HotelReservation/EnterDetails/SelectedRoom"
|
||||
import Multiroom from "@/components/HotelReservation/EnterDetails/Room/Multiroom"
|
||||
import RoomOne from "@/components/HotelReservation/EnterDetails/Room/One"
|
||||
import DesktopSummary from "@/components/HotelReservation/EnterDetails/Summary/Desktop"
|
||||
import MobileSummary from "@/components/HotelReservation/EnterDetails/Summary/Mobile"
|
||||
import { generateChildrenString } from "@/components/HotelReservation/utils"
|
||||
import Title from "@/components/TempDesignSystem/Text/Title"
|
||||
import { getIntl } from "@/i18n"
|
||||
import RoomProvider from "@/providers/Details/RoomProvider"
|
||||
import EnterDetailsProvider from "@/providers/EnterDetailsProvider"
|
||||
import { convertSearchParamsToObj } from "@/utils/url"
|
||||
|
||||
import styles from "./page.module.css"
|
||||
|
||||
import type { BedTypeSelection } from "@/types/components/hotelReservation/enterDetails/bedType"
|
||||
import type { RoomRate } from "@/types/components/hotelReservation/enterDetails/details"
|
||||
import { type SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||
import { StepEnum } from "@/types/enums/step"
|
||||
import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||
import type { LangParams, PageArgs } from "@/types/params"
|
||||
import type { Packages } from "@/types/requests/packages"
|
||||
|
||||
export interface RoomData {
|
||||
bedTypes?: BedTypeSelection[]
|
||||
mustBeGuaranteed?: boolean
|
||||
breakfastIncluded?: boolean
|
||||
packages: Packages | null
|
||||
cancellationText: string
|
||||
rateDetails: string[]
|
||||
roomType: string
|
||||
roomRate: RoomRate
|
||||
}
|
||||
import type { Room } from "@/types/providers/details/room"
|
||||
|
||||
export default async function DetailsPage({
|
||||
params: { lang },
|
||||
searchParams,
|
||||
}: PageArgs<LangParams, SelectRateSearchParams>) {
|
||||
const intl = await getIntl()
|
||||
const selectRoomParams = new URLSearchParams(searchParams)
|
||||
selectRoomParams.delete("modifyRateIndex")
|
||||
const booking = convertSearchParamsToObj<SelectRateSearchParams>(searchParams)
|
||||
if ("modifyRateIndex" in booking) {
|
||||
delete booking.modifyRateIndex
|
||||
}
|
||||
|
||||
void getProfileSafely()
|
||||
|
||||
@@ -61,7 +46,7 @@ export default async function DetailsPage({
|
||||
toDate: booking.toDate,
|
||||
}
|
||||
const breakfastPackages = await getBreakfastPackages(breakfastInput)
|
||||
const roomsData: RoomData[] = []
|
||||
const rooms: Room[] = []
|
||||
|
||||
for (let room of booking.rooms) {
|
||||
const childrenAsString =
|
||||
@@ -92,21 +77,22 @@ export default async function DetailsPage({
|
||||
: null
|
||||
|
||||
const roomAvailability = await getSelectedRoomAvailability(
|
||||
selectedRoomAvailabilityInput //
|
||||
selectedRoomAvailabilityInput
|
||||
)
|
||||
|
||||
if (!roomAvailability) {
|
||||
continue // TODO: handle no room availability
|
||||
}
|
||||
|
||||
roomsData.push({
|
||||
rooms.push({
|
||||
bedTypes: roomAvailability.bedTypes,
|
||||
packages,
|
||||
mustBeGuaranteed: roomAvailability.mustBeGuaranteed,
|
||||
breakfastIncluded: roomAvailability.breakfastIncluded,
|
||||
cancellationText: roomAvailability.cancellationText,
|
||||
mustBeGuaranteed: roomAvailability.mustBeGuaranteed,
|
||||
packages,
|
||||
rateDetails: roomAvailability.rateDetails ?? [],
|
||||
roomType: roomAvailability.selectedRoom.roomType,
|
||||
roomTypeCode: roomAvailability.selectedRoom.roomTypeCode,
|
||||
roomRate: {
|
||||
memberRate: roomAvailability?.memberRate,
|
||||
publicRate: roomAvailability.publicRate,
|
||||
@@ -114,7 +100,7 @@ export default async function DetailsPage({
|
||||
})
|
||||
}
|
||||
|
||||
const isCardOnlyPayment = roomsData.some((room) => room?.mustBeGuaranteed)
|
||||
const isCardOnlyPayment = rooms.some((room) => room?.mustBeGuaranteed)
|
||||
const hotelData = await getHotel({
|
||||
hotelId: booking.hotelId,
|
||||
isCardOnlyPayment,
|
||||
@@ -123,13 +109,13 @@ export default async function DetailsPage({
|
||||
const user = await getProfileSafely()
|
||||
// const userTrackingData = await getUserTracking()
|
||||
|
||||
if (!hotelData || !roomsData) {
|
||||
if (!hotelData || !rooms) {
|
||||
return notFound()
|
||||
}
|
||||
|
||||
// const arrivalDate = new Date(booking.fromDate)
|
||||
// const departureDate = new Date(booking.toDate)
|
||||
const hotelAttributes = hotelData.hotel
|
||||
const { hotel } = hotelData
|
||||
|
||||
// TODO: add tracking
|
||||
// const initialHotelsTrackingData: TrackingSDKHotelInfo = {
|
||||
@@ -147,111 +133,49 @@ export default async function DetailsPage({
|
||||
// leadTime: differenceInCalendarDays(arrivalDate, new Date()),
|
||||
// searchType: "hotel",
|
||||
// bookingTypeofDay: isWeekend(arrivalDate) ? "weekend" : "weekday",
|
||||
// country: hotelAttributes?.address.country,
|
||||
// hotelID: hotelAttributes?.operaId,
|
||||
// region: hotelAttributes?.address.city,
|
||||
// country: hotel?.address.country,
|
||||
// hotelID: hotel?.operaId,
|
||||
// region: hotel?.address.city,
|
||||
// }
|
||||
|
||||
const showBreakfastStep = Boolean(
|
||||
breakfastPackages?.length && !roomsData[0]?.breakfastIncluded
|
||||
)
|
||||
|
||||
const firstRoom = rooms[0]
|
||||
const multirooms = rooms.slice(1)
|
||||
return (
|
||||
<EnterDetailsProvider
|
||||
booking={booking}
|
||||
showBreakfastStep={showBreakfastStep}
|
||||
roomsData={roomsData}
|
||||
breakfastPackages={breakfastPackages}
|
||||
rooms={rooms}
|
||||
searchParamsStr={selectRoomParams.toString()}
|
||||
user={user}
|
||||
vat={hotelAttributes.vat}
|
||||
vat={hotel.vat}
|
||||
>
|
||||
<main>
|
||||
<HotelHeader hotelData={hotelData} />
|
||||
<div className={styles.container}>
|
||||
<div className={styles.content}>
|
||||
{roomsData.map((room, idx) => (
|
||||
<section key={idx}>
|
||||
{roomsData.length > 1 && (
|
||||
<header className={styles.header}>
|
||||
<Title level="h2" as="h4">
|
||||
{intl.formatMessage({ id: "Room" })} {idx + 1}
|
||||
</Title>
|
||||
</header>
|
||||
)}
|
||||
<SelectedRoom
|
||||
hotelId={booking.hotelId}
|
||||
roomType={room.roomType}
|
||||
roomTypeCode={booking.rooms[idx].roomTypeCode}
|
||||
rateDescription={room.cancellationText}
|
||||
roomIndex={idx}
|
||||
searchParamsStr={selectRoomParams.toString()}
|
||||
/>
|
||||
|
||||
{room.bedTypes ? (
|
||||
<SectionAccordion
|
||||
header={intl.formatMessage({ id: "Select bed" })}
|
||||
label={intl.formatMessage({ id: "Request bedtype" })}
|
||||
step={StepEnum.selectBed}
|
||||
roomIndex={idx}
|
||||
>
|
||||
<BedType bedTypes={room.bedTypes} roomIndex={idx} />
|
||||
</SectionAccordion>
|
||||
) : null}
|
||||
|
||||
{showBreakfastStep ? (
|
||||
<SectionAccordion
|
||||
header={intl.formatMessage({ id: "Food options" })}
|
||||
label={intl.formatMessage({
|
||||
id: "Select breakfast options",
|
||||
})}
|
||||
step={StepEnum.breakfast}
|
||||
roomIndex={idx}
|
||||
>
|
||||
<Breakfast packages={breakfastPackages!} roomIndex={idx} />
|
||||
</SectionAccordion>
|
||||
) : null}
|
||||
|
||||
<SectionAccordion
|
||||
header={intl.formatMessage({ id: "Details" })}
|
||||
step={StepEnum.details}
|
||||
label={intl.formatMessage({ id: "Enter your details" })}
|
||||
roomIndex={idx}
|
||||
>
|
||||
<Details
|
||||
user={idx === 0 ? user : null}
|
||||
memberPrice={{
|
||||
currency:
|
||||
room?.roomRate.memberRate?.localPrice.currency ?? "", // TODO: how to handle undefined,
|
||||
price:
|
||||
room?.roomRate.memberRate?.localPrice.pricePerNight ??
|
||||
0, // TODO: how to handle undefined,
|
||||
}}
|
||||
roomIndex={idx}
|
||||
/>
|
||||
</SectionAccordion>
|
||||
</section>
|
||||
<RoomProvider idx={0} room={firstRoom}>
|
||||
<RoomOne user={user} />
|
||||
</RoomProvider>
|
||||
{multirooms.map((room, idx) => (
|
||||
// Need to start idx from 1 since first room is
|
||||
// rendered above
|
||||
<RoomProvider key={idx + 1} idx={idx + 1} room={room}>
|
||||
<Multiroom />
|
||||
</RoomProvider>
|
||||
))}
|
||||
<Suspense>
|
||||
<Payment
|
||||
user={user}
|
||||
otherPaymentOptions={
|
||||
hotelAttributes.merchantInformationData
|
||||
.alternatePaymentOptions
|
||||
hotel.merchantInformationData.alternatePaymentOptions
|
||||
}
|
||||
supportedCards={hotelAttributes.merchantInformationData.cards}
|
||||
supportedCards={hotel.merchantInformationData.cards}
|
||||
mustBeGuaranteed={isCardOnlyPayment}
|
||||
/>
|
||||
</Suspense>
|
||||
</div>
|
||||
<aside className={styles.summary}>
|
||||
<MobileSummary
|
||||
isMember={!!user}
|
||||
breakfastIncluded={roomsData[0]?.breakfastIncluded ?? false}
|
||||
/>
|
||||
<DesktopSummary
|
||||
isMember={!!user}
|
||||
breakfastIncluded={roomsData[0]?.breakfastIncluded ?? false}
|
||||
/>
|
||||
<MobileSummary isMember={!!user} />
|
||||
<DesktopSummary isMember={!!user} />
|
||||
</aside>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
Reference in New Issue
Block a user