feat: add packages info to summary
This commit is contained in:
@@ -46,14 +46,17 @@ export default async function SummaryPage({
|
||||
packageCodes,
|
||||
})
|
||||
const user = await getProfileSafely()
|
||||
const packages = await getPackages({
|
||||
hotelId: hotel,
|
||||
startDate: fromDate,
|
||||
endDate: toDate,
|
||||
adults,
|
||||
children: children?.length,
|
||||
packageCodes,
|
||||
})
|
||||
|
||||
const packages = packageCodes
|
||||
? await getPackages({
|
||||
hotelId: hotel,
|
||||
startDate: fromDate,
|
||||
endDate: toDate,
|
||||
adults,
|
||||
children: children?.length,
|
||||
packageCodes,
|
||||
})
|
||||
: null
|
||||
|
||||
if (!availability || !availability.selectedRoom) {
|
||||
console.error("No hotel or availability data", availability)
|
||||
@@ -84,7 +87,6 @@ export default async function SummaryPage({
|
||||
},
|
||||
}
|
||||
|
||||
console.log({ packages })
|
||||
return (
|
||||
<>
|
||||
<div className={styles.mobileSummary}>
|
||||
@@ -99,6 +101,7 @@ export default async function SummaryPage({
|
||||
adults,
|
||||
children,
|
||||
cancellationText: availability.cancellationText,
|
||||
packages,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@@ -116,6 +119,7 @@ export default async function SummaryPage({
|
||||
adults,
|
||||
children,
|
||||
cancellationText: availability.cancellationText,
|
||||
packages,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -46,7 +46,13 @@ export default async function StepPage({
|
||||
toDate,
|
||||
} = getQueryParamsForEnterDetails(selectRoomParams)
|
||||
|
||||
const { adults, children, roomTypeCode, rateCode, packages } = rooms[0] // TODO: Handle multiple rooms
|
||||
const {
|
||||
adults,
|
||||
children,
|
||||
roomTypeCode,
|
||||
rateCode,
|
||||
packages: packageCodes,
|
||||
} = rooms[0] // TODO: Handle multiple rooms
|
||||
|
||||
const childrenAsString = children && generateChildrenString(children)
|
||||
|
||||
@@ -60,7 +66,7 @@ export default async function StepPage({
|
||||
roomStayEndDate: toDate,
|
||||
rateCode,
|
||||
roomTypeCode,
|
||||
packageCodes: packages,
|
||||
packageCodes,
|
||||
})
|
||||
|
||||
const roomAvailability = await getSelectedRoomAvailability({
|
||||
@@ -71,7 +77,7 @@ export default async function StepPage({
|
||||
roomStayEndDate: toDate,
|
||||
rateCode,
|
||||
roomTypeCode,
|
||||
packageCodes: packages,
|
||||
packageCodes,
|
||||
})
|
||||
const hotelData = await getHotelData({
|
||||
hotelId,
|
||||
|
||||
@@ -29,7 +29,7 @@ export default function Counter({
|
||||
>
|
||||
<MinusIcon color="burgundy" />
|
||||
</Button>
|
||||
<Body color="textHighContrast" textAlign="center">
|
||||
<Body color="baseTextHighContrast" textAlign="center">
|
||||
{count}
|
||||
</Body>
|
||||
<Button
|
||||
|
||||
@@ -48,7 +48,7 @@ export default function MyPagesMenu({
|
||||
onClick={() => toggleDropdown(DropdownTypeEnum.MyPagesMenu)}
|
||||
>
|
||||
<Avatar initials={getInitials(user.firstName, user.lastName)} />
|
||||
<Body textTransform="bold" color="textHighContrast" asChild>
|
||||
<Body textTransform="bold" color="baseTextHighContrast" asChild>
|
||||
<span>
|
||||
{intl.formatMessage({ id: "Hi" })} {user.firstName}!
|
||||
</span>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
"use client"
|
||||
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { isValidPhoneNumber, parsePhoneNumber } from "libphonenumber-js"
|
||||
import { useRouter, useSearchParams } from "next/navigation"
|
||||
import { useEffect, useState } from "react"
|
||||
import { Label as AriaLabel } from "react-aria-components"
|
||||
@@ -77,6 +76,7 @@ export default function Payment({
|
||||
countryCode,
|
||||
breakfast,
|
||||
bedType,
|
||||
membershipNo,
|
||||
} = userData
|
||||
const { toDate, fromDate, rooms: rooms, hotel } = roomData
|
||||
|
||||
@@ -147,17 +147,6 @@ export default function Payment({
|
||||
(card) => card.id === data.paymentMethod
|
||||
)
|
||||
|
||||
let phone: string
|
||||
let phoneCountryCodePrefix: string | null = null
|
||||
|
||||
if (isValidPhoneNumber(phoneNumber)) {
|
||||
const parsedPhone = parsePhoneNumber(phoneNumber)
|
||||
phone = parsedPhone.nationalNumber
|
||||
phoneCountryCodePrefix = parsedPhone.countryCallingCode
|
||||
} else {
|
||||
phone = phoneNumber
|
||||
}
|
||||
|
||||
initiateBooking.mutate({
|
||||
hotelId: hotel,
|
||||
checkInDate: fromDate,
|
||||
@@ -175,9 +164,9 @@ export default function Payment({
|
||||
firstName,
|
||||
lastName,
|
||||
email,
|
||||
phoneCountryCodePrefix,
|
||||
phoneNumber: phone,
|
||||
phoneNumber,
|
||||
countryCode,
|
||||
membershipNumber: membershipNo,
|
||||
},
|
||||
packages: {
|
||||
breakfast: breakfast !== BreakfastPackageEnum.NO_BREAKFAST,
|
||||
@@ -186,7 +175,8 @@ export default function Payment({
|
||||
petFriendly:
|
||||
room.packages?.includes(RoomPackageCodeEnum.PET_ROOM) ?? false,
|
||||
accessibility:
|
||||
room.packages?.includes(RoomPackageCodeEnum.ALLERGY_ROOM) ?? false,
|
||||
room.packages?.includes(RoomPackageCodeEnum.ACCESSIBILITY_ROOM) ??
|
||||
false,
|
||||
},
|
||||
smsConfirmationRequested: data.smsConfirmation,
|
||||
roomPrice,
|
||||
|
||||
@@ -35,10 +35,6 @@ function storeSelector(state: EnterDetailsState) {
|
||||
}
|
||||
}
|
||||
|
||||
function parsePrice(price: string | undefined) {
|
||||
return price ? parseInt(price) : 0
|
||||
}
|
||||
|
||||
export default function Summary({
|
||||
showMemberPrice,
|
||||
room,
|
||||
@@ -74,53 +70,54 @@ export default function Summary({
|
||||
color = "red"
|
||||
}
|
||||
|
||||
const additionalPackageCost = room.packages?.reduce(
|
||||
(acc, curr) => {
|
||||
acc.local = acc.local + parseInt(curr.localPrice.totalPrice)
|
||||
acc.euro = acc.euro + parseInt(curr.requestedPrice.totalPrice)
|
||||
return acc
|
||||
},
|
||||
{ local: 0, euro: 0 }
|
||||
) || { local: 0, euro: 0 }
|
||||
|
||||
const roomsPriceLocal = room.localPrice.price + additionalPackageCost.local
|
||||
const roomsPriceEuro = room.euroPrice.price + additionalPackageCost.euro
|
||||
|
||||
useEffect(() => {
|
||||
setChosenBed(bedType)
|
||||
setChosenBreakfast(breakfast)
|
||||
|
||||
if (breakfast) {
|
||||
setChosenBreakfast(breakfast)
|
||||
if (breakfast === BreakfastPackageEnum.NO_BREAKFAST) {
|
||||
setTotalPrice({
|
||||
local: {
|
||||
price: parsePrice(room.localPrice.price),
|
||||
currency: room.localPrice.currency,
|
||||
},
|
||||
euro: {
|
||||
price: parsePrice(room.euroPrice.price),
|
||||
currency: room.euroPrice.currency,
|
||||
},
|
||||
})
|
||||
} else {
|
||||
setTotalPrice({
|
||||
local: {
|
||||
price:
|
||||
parsePrice(room.localPrice.price) +
|
||||
parsePrice(breakfast.localPrice.totalPrice),
|
||||
currency: room.localPrice.currency,
|
||||
},
|
||||
euro: {
|
||||
price:
|
||||
parsePrice(room.euroPrice.price) +
|
||||
parsePrice(breakfast.requestedPrice.totalPrice),
|
||||
currency: room.euroPrice.currency,
|
||||
},
|
||||
})
|
||||
}
|
||||
if (breakfast && breakfast !== BreakfastPackageEnum.NO_BREAKFAST) {
|
||||
setTotalPrice({
|
||||
local: {
|
||||
price: roomsPriceLocal + parseInt(breakfast.localPrice.totalPrice),
|
||||
currency: room.localPrice.currency,
|
||||
},
|
||||
euro: {
|
||||
price: roomsPriceEuro + parseInt(breakfast.requestedPrice.totalPrice),
|
||||
currency: room.euroPrice.currency,
|
||||
},
|
||||
})
|
||||
} else {
|
||||
setTotalPrice({
|
||||
local: {
|
||||
price: roomsPriceLocal,
|
||||
currency: room.localPrice.currency,
|
||||
},
|
||||
euro: {
|
||||
price: roomsPriceEuro,
|
||||
currency: room.euroPrice.currency,
|
||||
},
|
||||
})
|
||||
}
|
||||
}, [bedType, breakfast, room.localPrice, room.euroPrice, setTotalPrice])
|
||||
|
||||
useEffect(() => {
|
||||
setTotalPrice({
|
||||
local: {
|
||||
price: parsePrice(room.localPrice.price),
|
||||
currency: room.localPrice.currency,
|
||||
},
|
||||
euro: {
|
||||
price: parsePrice(room.euroPrice.price),
|
||||
currency: room.euroPrice.currency,
|
||||
},
|
||||
})
|
||||
}, [room.localPrice, room.euroPrice, setTotalPrice])
|
||||
}, [
|
||||
bedType,
|
||||
breakfast,
|
||||
roomsPriceLocal,
|
||||
room.localPrice.currency,
|
||||
room.euroPrice.currency,
|
||||
roomsPriceEuro,
|
||||
setTotalPrice,
|
||||
])
|
||||
|
||||
return (
|
||||
<section className={styles.summary}>
|
||||
@@ -146,14 +143,12 @@ export default function Summary({
|
||||
<div className={styles.addOns}>
|
||||
<div>
|
||||
<div className={styles.entry}>
|
||||
<Body color="textHighContrast">{room.roomType}</Body>
|
||||
<Body color="uiTextHighContrast">{room.roomType}</Body>
|
||||
<Caption color={color}>
|
||||
{intl.formatMessage(
|
||||
{ id: "{amount} {currency}" },
|
||||
{
|
||||
amount: intl.formatNumber(
|
||||
parseInt(room.localPrice.price ?? "0")
|
||||
),
|
||||
amount: intl.formatNumber(room.localPrice.price),
|
||||
currency: room.localPrice.currency,
|
||||
}
|
||||
)}
|
||||
@@ -180,17 +175,37 @@ export default function Summary({
|
||||
{intl.formatMessage({ id: "Rate details" })}
|
||||
</Link>
|
||||
</div>
|
||||
{room.packages
|
||||
? room.packages.map((roomPackage) => (
|
||||
<div className={styles.entry} key={roomPackage.code}>
|
||||
<div>
|
||||
<Body color="uiTextHighContrast">
|
||||
{roomPackage.description}
|
||||
</Body>
|
||||
</div>
|
||||
|
||||
<Caption color="uiTextHighContrast">
|
||||
{intl.formatMessage(
|
||||
{ id: "{amount} {currency}" },
|
||||
{
|
||||
amount: roomPackage.localPrice.price,
|
||||
currency: roomPackage.localPrice.currency,
|
||||
}
|
||||
)}
|
||||
</Caption>
|
||||
</div>
|
||||
))
|
||||
: null}
|
||||
{chosenBed ? (
|
||||
<div className={styles.entry}>
|
||||
<div>
|
||||
<Body color="textHighContrast">{chosenBed.description}</Body>
|
||||
<Body color="uiTextHighContrast">{chosenBed.description}</Body>
|
||||
<Caption color="uiTextMediumContrast">
|
||||
{intl.formatMessage({ id: "Based on availability" })}
|
||||
</Caption>
|
||||
</div>
|
||||
|
||||
<Caption color="uiTextMediumContrast">
|
||||
<Caption color="uiTextHighContrast">
|
||||
{intl.formatMessage(
|
||||
{ id: "{amount} {currency}" },
|
||||
{ amount: "0", currency: room.localPrice.currency }
|
||||
@@ -202,10 +217,10 @@ export default function Summary({
|
||||
{chosenBreakfast ? (
|
||||
chosenBreakfast === BreakfastPackageEnum.NO_BREAKFAST ? (
|
||||
<div className={styles.entry}>
|
||||
<Body color="textHighContrast">
|
||||
<Body color="uiTextHighContrast">
|
||||
{intl.formatMessage({ id: "No breakfast" })}
|
||||
</Body>
|
||||
<Caption color="uiTextMediumContrast">
|
||||
<Caption color="uiTextHighContrast">
|
||||
{intl.formatMessage(
|
||||
{ id: "{amount} {currency}" },
|
||||
{ amount: "0", currency: room.localPrice.currency }
|
||||
@@ -214,10 +229,10 @@ export default function Summary({
|
||||
</div>
|
||||
) : (
|
||||
<div className={styles.entry}>
|
||||
<Body color="textHighContrast">
|
||||
<Body color="uiTextHighContrast">
|
||||
{intl.formatMessage({ id: "Breakfast buffet" })}
|
||||
</Body>
|
||||
<Caption color="uiTextMediumContrast">
|
||||
<Caption color="uiTextHighContrast">
|
||||
{intl.formatMessage(
|
||||
{ id: "{amount} {currency}" },
|
||||
{
|
||||
|
||||
@@ -41,7 +41,7 @@ export default function HotelSelectionHeader({
|
||||
<Divider variant="vertical" color="subtle" />
|
||||
</div>
|
||||
<div className={styles.descriptionContainer}>
|
||||
<Body color="textHighContrast">
|
||||
<Body color="baseTextHighContrast">
|
||||
{hotel.hotelContent.texts.descriptions.short}
|
||||
</Body>
|
||||
</div>
|
||||
|
||||
@@ -73,7 +73,7 @@ export default function HotelListingMapContent({
|
||||
</span>
|
||||
<Body
|
||||
asChild
|
||||
color={isActiveOrHovered ? "white" : "textHighContrast"}
|
||||
color={isActiveOrHovered ? "white" : "baseTextHighContrast"}
|
||||
>
|
||||
<span>
|
||||
{pin.memberPrice} {pin.currency}
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
color: var(--Base-Text-Medium-contrast);
|
||||
}
|
||||
|
||||
.textHighContrast {
|
||||
.baseTextHighContrast {
|
||||
color: var(--Base-Text-High-contrast);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ const config = {
|
||||
red: styles.red,
|
||||
textMediumContrast: styles.textMediumContrast,
|
||||
baseTextMediumContrast: styles.baseTextMediumContrast,
|
||||
textHighContrast: styles.textHighContrast,
|
||||
baseTextHighContrast: styles.baseTextHighContrast,
|
||||
white: styles.white,
|
||||
peach50: styles.peach50,
|
||||
uiTextHighContrast: styles.uiTextHighContrast,
|
||||
|
||||
@@ -14,13 +14,11 @@ const roomsSchema = z.array(
|
||||
)
|
||||
.default([]),
|
||||
rateCode: z.string(),
|
||||
roomTypeCode: z.string(),
|
||||
roomTypeCode: z.coerce.string(),
|
||||
guest: z.object({
|
||||
title: z.string(),
|
||||
firstName: z.string(),
|
||||
lastName: z.string(),
|
||||
email: z.string().email(),
|
||||
phoneCountryCodePrefix: z.string().nullable(),
|
||||
phoneNumber: z.string(),
|
||||
countryCode: z.string(),
|
||||
membershipNumber: z.string().optional(),
|
||||
|
||||
@@ -541,8 +541,8 @@ export type HotelsAvailabilityPrices =
|
||||
HotelsAvailability["data"][number]["attributes"]["bestPricePerNight"]
|
||||
|
||||
export const priceSchema = z.object({
|
||||
pricePerNight: z.string(),
|
||||
pricePerStay: z.string(),
|
||||
pricePerNight: z.coerce.number(),
|
||||
pricePerStay: z.coerce.number(),
|
||||
currency: z.string(),
|
||||
})
|
||||
|
||||
|
||||
@@ -724,8 +724,6 @@ export const hotelQueryRouter = router({
|
||||
ctx.serviceToken
|
||||
)
|
||||
|
||||
console.log({ packageCodes })
|
||||
|
||||
const availableRooms =
|
||||
validateAvailabilityData.data.roomConfigurations.filter((room) => {
|
||||
if (packageCodes) {
|
||||
@@ -740,7 +738,6 @@ export const hotelQueryRouter = router({
|
||||
return room.status === "Available"
|
||||
})
|
||||
|
||||
console.log("hrteij", JSON.stringify(availableRooms, null, 4))
|
||||
const selectedRoom = availableRooms.find(
|
||||
(room) => room.roomTypeCode === roomTypeCode
|
||||
)
|
||||
@@ -748,11 +745,6 @@ export const hotelQueryRouter = router({
|
||||
const availableRoomsInCategory = availableRooms.filter(
|
||||
(room) => room.roomType === selectedRoom?.roomType
|
||||
)
|
||||
|
||||
console.log(
|
||||
"availableRoomsInCategory",
|
||||
JSON.stringify(availableRoomsInCategory, null, 4)
|
||||
)
|
||||
if (!selectedRoom) {
|
||||
console.error("No matching room found")
|
||||
return null
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { RoomPackageCodeEnum } from "../selectRate/roomFilter"
|
||||
import { Child } from "../selectRate/selectRate"
|
||||
|
||||
import { Packages } from "@/types/requests/packages"
|
||||
|
||||
interface Room {
|
||||
adults: number
|
||||
roomTypeCode: string
|
||||
@@ -16,7 +18,7 @@ export interface BookingData {
|
||||
}
|
||||
|
||||
type Price = {
|
||||
price: string
|
||||
price: number
|
||||
currency: string
|
||||
}
|
||||
|
||||
@@ -27,4 +29,5 @@ export type RoomsData = {
|
||||
adults: number
|
||||
children?: Child[]
|
||||
cancellationText: string
|
||||
packages: Packages | null
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ export interface BreakfastSelectionProps extends SectionProps {
|
||||
export interface DetailsProps extends SectionProps {}
|
||||
|
||||
export interface PaymentProps {
|
||||
roomPrice: string
|
||||
roomPrice: number
|
||||
otherPaymentOptions: string[]
|
||||
savedCreditCards: CreditCard[] | null
|
||||
mustBeGuaranteed: boolean
|
||||
|
||||
@@ -4,9 +4,12 @@ import {
|
||||
getBreakfastPackageInputSchema,
|
||||
getRoomPackagesInputSchema,
|
||||
} from "@/server/routers/hotels/input"
|
||||
import { getRoomPackagesSchema } from "@/server/routers/hotels/output"
|
||||
|
||||
export interface BreackfastPackagesInput
|
||||
extends z.input<typeof getBreakfastPackageInputSchema> {}
|
||||
|
||||
export interface PackagesInput
|
||||
extends z.input<typeof getRoomPackagesInputSchema> {}
|
||||
|
||||
export interface Packages extends z.output<typeof getRoomPackagesSchema> {}
|
||||
|
||||
Reference in New Issue
Block a user