feat: add packages info to summary

This commit is contained in:
Christel Westerberg
2024-11-12 10:06:13 +01:00
parent dbb5367df2
commit dc3516f4e1
16 changed files with 116 additions and 105 deletions

View File

@@ -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>

View File

@@ -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,

View File

@@ -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

View File

@@ -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>

View File

@@ -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,

View File

@@ -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}" },
{

View File

@@ -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>

View File

@@ -73,7 +73,7 @@ export default function HotelListingMapContent({
</span>
<Body
asChild
color={isActiveOrHovered ? "white" : "textHighContrast"}
color={isActiveOrHovered ? "white" : "baseTextHighContrast"}
>
<span>
{pin.memberPrice} {pin.currency}

View File

@@ -80,7 +80,7 @@
color: var(--Base-Text-Medium-contrast);
}
.textHighContrast {
.baseTextHighContrast {
color: var(--Base-Text-High-contrast);
}

View File

@@ -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,

View File

@@ -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(),

View File

@@ -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(),
})

View File

@@ -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

View File

@@ -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
}

View File

@@ -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

View File

@@ -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> {}