Merged in feat(SW-2083)-missing-booking-codes-scenarios-my-stay (pull request #1680)
Feat(SW-2083) missing booking codes scenarios my stay * feat(SW-2083) Show points instead of reward nights * feat(SW-2083) added support for cheque and voucher for totalPrice Approved-by: Niclas Edenvin
This commit is contained in:
@@ -30,8 +30,14 @@ export default function BookingSummary({ hotel }: BookingSummaryProps) {
|
|||||||
|
|
||||||
const bookedRoom = useMyStayRoomDetailsStore((state) => state.bookedRoom)
|
const bookedRoom = useMyStayRoomDetailsStore((state) => state.bookedRoom)
|
||||||
|
|
||||||
const { isCancelled, createDateTime, guaranteeInfo, checkInDate, isPrePaid } =
|
const {
|
||||||
bookedRoom
|
isCancelled,
|
||||||
|
createDateTime,
|
||||||
|
guaranteeInfo,
|
||||||
|
checkInDate,
|
||||||
|
isPrePaid,
|
||||||
|
priceType,
|
||||||
|
} = bookedRoom
|
||||||
|
|
||||||
const directionsUrl = `https://www.google.com/maps/dir/?api=1&destination=${hotel.location.latitude},${hotel.location.longitude}`
|
const directionsUrl = `https://www.google.com/maps/dir/?api=1&destination=${hotel.location.latitude},${hotel.location.longitude}`
|
||||||
|
|
||||||
@@ -57,7 +63,9 @@ export default function BookingSummary({ hotel }: BookingSummaryProps) {
|
|||||||
</Typography>
|
</Typography>
|
||||||
<div className={styles.bookingSummaryContent}>
|
<div className={styles.bookingSummaryContent}>
|
||||||
<SummaryCard
|
<SummaryCard
|
||||||
title={<TotalPrice variant="Body/Paragraph/mdBold" />}
|
title={
|
||||||
|
<TotalPrice variant="Body/Paragraph/mdBold" type={priceType} />
|
||||||
|
}
|
||||||
image={{
|
image={{
|
||||||
src: "/_static/img/scandic-coin.svg",
|
src: "/_static/img/scandic-coin.svg",
|
||||||
alt: "Scandic coin",
|
alt: "Scandic coin",
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ export default function ActionPanel({ hotel }: ActionPanelProps) {
|
|||||||
createDateTime,
|
createDateTime,
|
||||||
canChangeDate,
|
canChangeDate,
|
||||||
isPrePaid,
|
isPrePaid,
|
||||||
|
priceType,
|
||||||
} = bookedRoom
|
} = bookedRoom
|
||||||
|
|
||||||
const datetimeIsInThePast = useMemo(
|
const datetimeIsInThePast = useMemo(
|
||||||
@@ -71,6 +72,7 @@ export default function ActionPanel({ hotel }: ActionPanelProps) {
|
|||||||
datetimeIsInThePast,
|
datetimeIsInThePast,
|
||||||
isCancelled: bookedRoom.isCancelled,
|
isCancelled: bookedRoom.isCancelled,
|
||||||
isPrePaid,
|
isPrePaid,
|
||||||
|
isRewardNight: priceType === "points",
|
||||||
})
|
})
|
||||||
|
|
||||||
const isCancelable = checkCancelable({
|
const isCancelable = checkCancelable({
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ interface ModificationConditions {
|
|||||||
isNotPast: boolean
|
isNotPast: boolean
|
||||||
isNotCancelled: boolean
|
isNotCancelled: boolean
|
||||||
isNotPrePaid: boolean
|
isNotPrePaid: boolean
|
||||||
|
isNotRewardNight: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GuaranteeConditions {
|
interface GuaranteeConditions {
|
||||||
@@ -25,17 +26,20 @@ export function checkDateModifiable({
|
|||||||
datetimeIsInThePast,
|
datetimeIsInThePast,
|
||||||
isCancelled,
|
isCancelled,
|
||||||
isPrePaid,
|
isPrePaid,
|
||||||
|
isRewardNight,
|
||||||
}: {
|
}: {
|
||||||
canChangeDate: boolean
|
canChangeDate: boolean
|
||||||
datetimeIsInThePast: boolean
|
datetimeIsInThePast: boolean
|
||||||
isCancelled: boolean
|
isCancelled: boolean
|
||||||
isPrePaid: boolean
|
isPrePaid: boolean
|
||||||
|
isRewardNight: boolean
|
||||||
}): boolean {
|
}): boolean {
|
||||||
const conditions: ModificationConditions = {
|
const conditions: ModificationConditions = {
|
||||||
canModify: canChangeDate,
|
canModify: canChangeDate,
|
||||||
isNotPast: !datetimeIsInThePast,
|
isNotPast: !datetimeIsInThePast,
|
||||||
isNotCancelled: !isCancelled,
|
isNotCancelled: !isCancelled,
|
||||||
isNotPrePaid: !isPrePaid,
|
isNotPrePaid: !isPrePaid,
|
||||||
|
isNotRewardNight: !isRewardNight,
|
||||||
}
|
}
|
||||||
|
|
||||||
return Object.values(conditions).every(Boolean)
|
return Object.values(conditions).every(Boolean)
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import IconChip from "@/components/TempDesignSystem/IconChip"
|
|||||||
import useLang from "@/hooks/useLang"
|
import useLang from "@/hooks/useLang"
|
||||||
|
|
||||||
import { IconForFeatureCode } from "../../utils"
|
import { IconForFeatureCode } from "../../utils"
|
||||||
|
import Points from "../Points"
|
||||||
import Price from "../Price"
|
import Price from "../Price"
|
||||||
import { hasBreakfastPackage } from "../utils/hasBreakfastPackage"
|
import { hasBreakfastPackage } from "../utils/hasBreakfastPackage"
|
||||||
import { mapRoomDetails } from "../utils/mapRoomDetails"
|
import { mapRoomDetails } from "../utils/mapRoomDetails"
|
||||||
@@ -91,6 +92,7 @@ export default function MultiRoom({
|
|||||||
totalPrice: isBookingCancelled ? 0 : bookingInfo.totalPrice,
|
totalPrice: isBookingCancelled ? 0 : bookingInfo.totalPrice,
|
||||||
currencyCode: bookingInfo.currencyCode,
|
currencyCode: bookingInfo.currencyCode,
|
||||||
isMainBooking: false,
|
isMainBooking: false,
|
||||||
|
roomPoints: bookingInfo.roomPoints,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Add room details to the store
|
// Add room details to the store
|
||||||
@@ -120,10 +122,13 @@ export default function MultiRoom({
|
|||||||
confirmationNumber,
|
confirmationNumber,
|
||||||
cancellationNumber,
|
cancellationNumber,
|
||||||
hotelId,
|
hotelId,
|
||||||
|
roomPoints,
|
||||||
roomPrice,
|
roomPrice,
|
||||||
packages,
|
packages,
|
||||||
rateDefinition,
|
rateDefinition,
|
||||||
isCancelled,
|
isCancelled,
|
||||||
|
priceType,
|
||||||
|
vouchers,
|
||||||
} = multiRoom
|
} = multiRoom
|
||||||
|
|
||||||
const fromDate = dt(checkInDate).locale(lang)
|
const fromDate = dt(checkInDate).locale(lang)
|
||||||
@@ -293,11 +298,24 @@ export default function MultiRoom({
|
|||||||
<Typography variant="Body/Lead text">
|
<Typography variant="Body/Lead text">
|
||||||
<p>{intl.formatMessage({ id: "Room total" })}</p>
|
<p>{intl.formatMessage({ id: "Room total" })}</p>
|
||||||
</Typography>
|
</Typography>
|
||||||
<Price
|
{priceType === "points" ? (
|
||||||
price={isCancelled ? 0 : roomPrice.perStay.local.price}
|
<Points points={roomPoints} variant="Body/Paragraph/mdBold" />
|
||||||
variant="Body/Paragraph/mdBold"
|
) : priceType === "voucher" ? (
|
||||||
isMember={rateDefinition.isMemberRate}
|
<Typography variant="Body/Paragraph/mdBold">
|
||||||
/>
|
<p>
|
||||||
|
{intl.formatMessage(
|
||||||
|
{ id: "{count} voucher" },
|
||||||
|
{ count: vouchers }
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</Typography>
|
||||||
|
) : (
|
||||||
|
<Price
|
||||||
|
price={isCancelled ? 0 : roomPrice.perStay.local.price}
|
||||||
|
variant="Body/Paragraph/mdBold"
|
||||||
|
isMember={rateDefinition.isMemberRate}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
|
|
||||||
|
import SkeletonShimmer from "@/components/SkeletonShimmer"
|
||||||
|
|
||||||
|
import type { Variant } from "../Rooms/TotalPrice"
|
||||||
|
|
||||||
|
export default function Points({
|
||||||
|
points,
|
||||||
|
variant,
|
||||||
|
}: {
|
||||||
|
points: number | null
|
||||||
|
variant: Variant
|
||||||
|
}) {
|
||||||
|
const intl = useIntl()
|
||||||
|
|
||||||
|
if (points === null) {
|
||||||
|
return <SkeletonShimmer width={"100px"} />
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Typography variant={variant}>
|
||||||
|
<p>
|
||||||
|
{intl.formatNumber(points)} {intl.formatMessage({ id: "Points" })}
|
||||||
|
</p>
|
||||||
|
</Typography>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -11,10 +11,7 @@ import { formatPrice } from "@/utils/numberFormatting"
|
|||||||
|
|
||||||
import styles from "./price.module.css"
|
import styles from "./price.module.css"
|
||||||
|
|
||||||
export type Variant =
|
import type { Variant } from "../Rooms/TotalPrice"
|
||||||
| "Title/Subtitle/lg"
|
|
||||||
| "Title/Subtitle/md"
|
|
||||||
| "Body/Paragraph/mdBold"
|
|
||||||
|
|
||||||
export default function Price({
|
export default function Price({
|
||||||
price,
|
price,
|
||||||
|
|||||||
@@ -66,7 +66,6 @@ export function ReferenceCard({
|
|||||||
const addRoomPrice = useMyStayTotalPriceStore(
|
const addRoomPrice = useMyStayTotalPriceStore(
|
||||||
(state) => state.actions.addRoomPrice
|
(state) => state.actions.addRoomPrice
|
||||||
)
|
)
|
||||||
|
|
||||||
// Initialize store with server data
|
// Initialize store with server data
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Add price and details for booked room (main room or single room)
|
// Add price and details for booked room (main room or single room)
|
||||||
@@ -78,6 +77,7 @@ export function ReferenceCard({
|
|||||||
: booking.totalPrice,
|
: booking.totalPrice,
|
||||||
currencyCode: booking.currencyCode,
|
currencyCode: booking.currencyCode,
|
||||||
isMainBooking: true,
|
isMainBooking: true,
|
||||||
|
roomPoints: booking.roomPoints,
|
||||||
})
|
})
|
||||||
addBookedRoom(
|
addBookedRoom(
|
||||||
mapRoomDetails({
|
mapRoomDetails({
|
||||||
@@ -99,6 +99,8 @@ export function ReferenceCard({
|
|||||||
checkOutDate,
|
checkOutDate,
|
||||||
isCancelled,
|
isCancelled,
|
||||||
bookingCode,
|
bookingCode,
|
||||||
|
rateDefinition,
|
||||||
|
priceType,
|
||||||
} = bookedRoom
|
} = bookedRoom
|
||||||
|
|
||||||
const fromDate = dt(checkInDate).locale(lang)
|
const fromDate = dt(checkInDate).locale(lang)
|
||||||
@@ -270,7 +272,7 @@ export function ReferenceCard({
|
|||||||
<Typography variant="Title/Overline/sm">
|
<Typography variant="Title/Overline/sm">
|
||||||
<p>{intl.formatMessage({ id: "Total" })}</p>
|
<p>{intl.formatMessage({ id: "Total" })}</p>
|
||||||
</Typography>
|
</Typography>
|
||||||
<TotalPrice variant="Title/Subtitle/md" />
|
<TotalPrice variant="Title/Subtitle/md" type={priceType} />
|
||||||
</div>
|
</div>
|
||||||
{bookingCode && (
|
{bookingCode && (
|
||||||
<div className={styles.referenceRow}>
|
<div className={styles.referenceRow}>
|
||||||
@@ -315,7 +317,7 @@ export function ReferenceCard({
|
|||||||
<p
|
<p
|
||||||
className={`${styles.note} ${allRoomsCancelled ? styles.cancelledNote : ""}`}
|
className={`${styles.note} ${allRoomsCancelled ? styles.cancelledNote : ""}`}
|
||||||
>
|
>
|
||||||
{booking.rateDefinition.generalTerms.map((term) => (
|
{rateDefinition.generalTerms.map((term) => (
|
||||||
<span key={term}>
|
<span key={term}>
|
||||||
{term}
|
{term}
|
||||||
{term.endsWith(".") ? " " : ". "}
|
{term.endsWith(".") ? " " : ". "}
|
||||||
|
|||||||
@@ -1,11 +1,73 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
|
|
||||||
|
import { useMyStayRoomDetailsStore } from "@/stores/my-stay/myStayRoomDetailsStore"
|
||||||
import { useMyStayTotalPriceStore } from "@/stores/my-stay/myStayTotalPrice"
|
import { useMyStayTotalPriceStore } from "@/stores/my-stay/myStayTotalPrice"
|
||||||
|
|
||||||
import Price, { type Variant } from "../../Price"
|
import Points from "../../Points"
|
||||||
|
import Price from "../../Price"
|
||||||
|
|
||||||
export default function TotalPrice({ variant }: { variant: Variant }) {
|
import styles from "./totalPrice.module.css"
|
||||||
const { totalPrice } = useMyStayTotalPriceStore()
|
|
||||||
|
|
||||||
return <Price price={totalPrice} variant={variant} />
|
import type { PriceType } from "@/types/components/hotelReservation/myStay/myStay"
|
||||||
|
|
||||||
|
export type Variant =
|
||||||
|
| "Title/Subtitle/lg"
|
||||||
|
| "Title/Subtitle/md"
|
||||||
|
| "Body/Paragraph/mdBold"
|
||||||
|
|
||||||
|
interface TotalPriceProps {
|
||||||
|
variant: Variant
|
||||||
|
type?: PriceType
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function TotalPrice({
|
||||||
|
variant,
|
||||||
|
type = "money",
|
||||||
|
}: TotalPriceProps) {
|
||||||
|
const totalPrice = useMyStayTotalPriceStore((state) => state.totalPrice)
|
||||||
|
const totalPoints = useMyStayTotalPriceStore((state) => state.totalPoints)
|
||||||
|
const bookedRoom = useMyStayRoomDetailsStore((state) => state.bookedRoom)
|
||||||
|
|
||||||
|
const { vouchers, cheques } = bookedRoom
|
||||||
|
|
||||||
|
const intl = useIntl()
|
||||||
|
if (type === "money") {
|
||||||
|
return <Price price={totalPrice} variant={variant} />
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === "voucher") {
|
||||||
|
return (
|
||||||
|
<Typography variant={variant}>
|
||||||
|
<p>
|
||||||
|
{intl.formatMessage({ id: "{count} voucher" }, { count: vouchers })}
|
||||||
|
</p>
|
||||||
|
</Typography>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === "cheque") {
|
||||||
|
return (
|
||||||
|
<div className={styles.totalPrice}>
|
||||||
|
<Typography variant={variant}>
|
||||||
|
<p>{cheques} CC + </p>
|
||||||
|
</Typography>
|
||||||
|
<Price price={totalPrice} variant={variant} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalPrice && totalPrice > 0 && type === "points") {
|
||||||
|
return (
|
||||||
|
<div className={styles.totalPrice}>
|
||||||
|
<Points points={totalPoints} variant={variant} /> +{" "}
|
||||||
|
<Price price={totalPrice} variant={variant} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Points points={totalPoints} variant={variant} />
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.totalPrice {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ import MultiRoom from "../MultiRoom"
|
|||||||
import MultiRoomSkeleton from "../MultiRoom/MultiRoomSkeleton"
|
import MultiRoomSkeleton from "../MultiRoom/MultiRoomSkeleton"
|
||||||
import PriceDetails from "../PriceDetails"
|
import PriceDetails from "../PriceDetails"
|
||||||
import { SingleRoom } from "../SingleRoom"
|
import { SingleRoom } from "../SingleRoom"
|
||||||
|
import { getPriceType } from "../utils/getPriceType"
|
||||||
import TotalPrice from "./TotalPrice"
|
import TotalPrice from "./TotalPrice"
|
||||||
|
|
||||||
import styles from "./rooms.module.css"
|
import styles from "./rooms.module.css"
|
||||||
@@ -92,7 +93,14 @@ export default async function Rooms({
|
|||||||
<Typography variant="Body/Lead text">
|
<Typography variant="Body/Lead text">
|
||||||
<p>{intl.formatMessage({ id: "Booking total" })}:</p>
|
<p>{intl.formatMessage({ id: "Booking total" })}:</p>
|
||||||
</Typography>
|
</Typography>
|
||||||
<TotalPrice variant="Title/Subtitle/lg" />
|
<TotalPrice
|
||||||
|
variant="Title/Subtitle/lg"
|
||||||
|
type={getPriceType({
|
||||||
|
rateDefinition: booking.rateDefinition,
|
||||||
|
vouchers: booking.vouchers,
|
||||||
|
cheques: booking.cheques,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<PriceDetails />
|
<PriceDetails />
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import IconChip from "@/components/TempDesignSystem/IconChip"
|
|||||||
import useLang from "@/hooks/useLang"
|
import useLang from "@/hooks/useLang"
|
||||||
|
|
||||||
import GuestDetails from "../GuestDetails"
|
import GuestDetails from "../GuestDetails"
|
||||||
|
import Points from "../Points"
|
||||||
import Price from "../Price"
|
import Price from "../Price"
|
||||||
import PriceDetails from "../PriceDetails"
|
import PriceDetails from "../PriceDetails"
|
||||||
import { hasBreakfastPackage } from "../utils/hasBreakfastPackage"
|
import { hasBreakfastPackage } from "../utils/hasBreakfastPackage"
|
||||||
@@ -62,9 +63,12 @@ export function SingleRoom({ bedType, image, hotel, user }: RoomProps) {
|
|||||||
confirmationNumber,
|
confirmationNumber,
|
||||||
bookingCode,
|
bookingCode,
|
||||||
roomPrice,
|
roomPrice,
|
||||||
|
roomPoints,
|
||||||
packages,
|
packages,
|
||||||
rateDefinition,
|
rateDefinition,
|
||||||
isCancelled,
|
isCancelled,
|
||||||
|
priceType,
|
||||||
|
vouchers,
|
||||||
} = bookedRoom
|
} = bookedRoom
|
||||||
|
|
||||||
const mainBedWidthValueMsg = intl.formatMessage(
|
const mainBedWidthValueMsg = intl.formatMessage(
|
||||||
@@ -357,11 +361,24 @@ export function SingleRoom({ bedType, image, hotel, user }: RoomProps) {
|
|||||||
{intl.formatMessage({ id: "Room total" })}
|
{intl.formatMessage({ id: "Room total" })}
|
||||||
</p>
|
</p>
|
||||||
</Typography>
|
</Typography>
|
||||||
<Price
|
{priceType === "points" ? (
|
||||||
price={isCancelled ? 0 : roomPrice.perStay.local.price}
|
<Points points={roomPoints} variant="Title/Subtitle/lg" />
|
||||||
variant="Title/Subtitle/lg"
|
) : priceType === "voucher" ? (
|
||||||
isMember={rateDefinition.isMemberRate}
|
<Typography variant="Title/Subtitle/lg">
|
||||||
/>
|
<p>
|
||||||
|
{intl.formatMessage(
|
||||||
|
{ id: "{count} voucher" },
|
||||||
|
{ count: vouchers }
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</Typography>
|
||||||
|
) : (
|
||||||
|
<Price
|
||||||
|
price={isCancelled ? 0 : roomPrice.perStay.local.price}
|
||||||
|
variant="Title/Subtitle/lg"
|
||||||
|
isMember={rateDefinition.isMemberRate}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import type { PriceType } from "@/types/components/hotelReservation/myStay/myStay"
|
||||||
|
import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation"
|
||||||
|
|
||||||
|
type PriceTypeParams = Pick<
|
||||||
|
BookingConfirmation["booking"],
|
||||||
|
"rateDefinition" | "vouchers" | "cheques"
|
||||||
|
>
|
||||||
|
|
||||||
|
export function getPriceType({
|
||||||
|
rateDefinition,
|
||||||
|
vouchers,
|
||||||
|
cheques,
|
||||||
|
}: PriceTypeParams): PriceType {
|
||||||
|
if (rateDefinition.title === "Reward Night") return "points"
|
||||||
|
if (vouchers > 0) return "voucher"
|
||||||
|
if (cheques > 0) return "cheque"
|
||||||
|
return "money"
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import { dt } from "@/lib/dt"
|
|||||||
|
|
||||||
import { formatChildBedPreferences } from "../utils"
|
import { formatChildBedPreferences } from "../utils"
|
||||||
import { convertToChildType } from "./convertToChildType"
|
import { convertToChildType } from "./convertToChildType"
|
||||||
|
import { getPriceType } from "./getPriceType"
|
||||||
|
|
||||||
import type { BreakfastPackage } from "@/types/components/hotelReservation/breakfast"
|
import type { BreakfastPackage } from "@/types/components/hotelReservation/breakfast"
|
||||||
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
|
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
|
||||||
@@ -76,6 +77,12 @@ export function mapRoomDetails({
|
|||||||
booking.rateDefinition.cancellationRule !==
|
booking.rateDefinition.cancellationRule !==
|
||||||
CancellationRuleEnum.CancellableBefore6PM
|
CancellationRuleEnum.CancellableBefore6PM
|
||||||
|
|
||||||
|
const priceType = getPriceType({
|
||||||
|
rateDefinition: booking.rateDefinition,
|
||||||
|
vouchers: booking.vouchers,
|
||||||
|
cheques: booking.cheques,
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
hotelId: booking.hotelId,
|
hotelId: booking.hotelId,
|
||||||
roomTypeCode: booking.roomTypeCode,
|
roomTypeCode: booking.roomTypeCode,
|
||||||
@@ -90,6 +97,8 @@ export function mapRoomDetails({
|
|||||||
guaranteeInfo: booking.guaranteeInfo,
|
guaranteeInfo: booking.guaranteeInfo,
|
||||||
linkedReservations: booking.linkedReservations,
|
linkedReservations: booking.linkedReservations,
|
||||||
bookingCode: booking.bookingCode,
|
bookingCode: booking.bookingCode,
|
||||||
|
cheques: booking.cheques,
|
||||||
|
vouchers: booking.vouchers,
|
||||||
isCancelable: booking.isCancelable,
|
isCancelable: booking.isCancelable,
|
||||||
multiRoom: booking.multiRoom,
|
multiRoom: booking.multiRoom,
|
||||||
canChangeDate: booking.canChangeDate,
|
canChangeDate: booking.canChangeDate,
|
||||||
@@ -123,6 +132,7 @@ export function mapRoomDetails({
|
|||||||
description: room?.bedType.mainBed.description ?? "",
|
description: room?.bedType.mainBed.description ?? "",
|
||||||
roomTypeCode: room?.bedType.code ?? "",
|
roomTypeCode: room?.bedType.code ?? "",
|
||||||
},
|
},
|
||||||
|
roomPoints: booking.roomPoints,
|
||||||
roomPrice: {
|
roomPrice: {
|
||||||
perNight: {
|
perNight: {
|
||||||
local: {
|
local: {
|
||||||
@@ -141,5 +151,6 @@ export function mapRoomDetails({
|
|||||||
},
|
},
|
||||||
breakfast,
|
breakfast,
|
||||||
isPrePaid,
|
isPrePaid,
|
||||||
|
priceType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -973,6 +973,7 @@
|
|||||||
"{count} number": "{count} nummer",
|
"{count} number": "{count} nummer",
|
||||||
"{count} special character": "{count} speciel karakter",
|
"{count} special character": "{count} speciel karakter",
|
||||||
"{count} uppercase letter": "{count} stort bogstav",
|
"{count} uppercase letter": "{count} stort bogstav",
|
||||||
|
"{count} voucher": "{count} voucher",
|
||||||
"{difference}{amount} {currency}": "{difference}{amount} {currency}",
|
"{difference}{amount} {currency}": "{difference}{amount} {currency}",
|
||||||
"{distanceInKm} km": "{distanceInKm} km",
|
"{distanceInKm} km": "{distanceInKm} km",
|
||||||
"{guests, plural, one {# guest} other {# guests}}": "{guests, plural, one {# gæst} other {# gæster}}",
|
"{guests, plural, one {# guest} other {# guests}}": "{guests, plural, one {# gæst} other {# gæster}}",
|
||||||
|
|||||||
@@ -971,6 +971,7 @@
|
|||||||
"{count} number": "{count} nummer",
|
"{count} number": "{count} nummer",
|
||||||
"{count} special character": "{count} sonderzeichen",
|
"{count} special character": "{count} sonderzeichen",
|
||||||
"{count} uppercase letter": "{count} großbuchstabe",
|
"{count} uppercase letter": "{count} großbuchstabe",
|
||||||
|
"{count} voucher": "{count} voucher",
|
||||||
"{difference}{amount} {currency}": "{difference}{amount} {currency}",
|
"{difference}{amount} {currency}": "{difference}{amount} {currency}",
|
||||||
"{distanceInKm} km": "{distanceInKm} km",
|
"{distanceInKm} km": "{distanceInKm} km",
|
||||||
"{guests, plural, one {# guest} other {# guests}}": "{guests, plural, one {# gast} other {# gäste}}",
|
"{guests, plural, one {# guest} other {# guests}}": "{guests, plural, one {# gast} other {# gäste}}",
|
||||||
|
|||||||
@@ -966,6 +966,7 @@
|
|||||||
"{count} number": "{count} number",
|
"{count} number": "{count} number",
|
||||||
"{count} special character": "{count} special character",
|
"{count} special character": "{count} special character",
|
||||||
"{count} uppercase letter": "{count} uppercase letter",
|
"{count} uppercase letter": "{count} uppercase letter",
|
||||||
|
"{count} voucher": "{count} voucher",
|
||||||
"{difference}{amount} {currency}": "{difference}{amount} {currency}",
|
"{difference}{amount} {currency}": "{difference}{amount} {currency}",
|
||||||
"{distanceInKm} km": "{distanceInKm} km",
|
"{distanceInKm} km": "{distanceInKm} km",
|
||||||
"{guests, plural, one {# guest} other {# guests}}": "{guests, plural, one {# guest} other {# guests}}",
|
"{guests, plural, one {# guest} other {# guests}}": "{guests, plural, one {# guest} other {# guests}}",
|
||||||
|
|||||||
@@ -971,6 +971,7 @@
|
|||||||
"{count} number": "{count} määrä",
|
"{count} number": "{count} määrä",
|
||||||
"{count} special character": "{count} erikoishahmo",
|
"{count} special character": "{count} erikoishahmo",
|
||||||
"{count} uppercase letter": "{count} iso kirjain",
|
"{count} uppercase letter": "{count} iso kirjain",
|
||||||
|
"{count} voucher": "{count} voucher",
|
||||||
"{difference}{amount} {currency}": "{difference}{amount} {currency}",
|
"{difference}{amount} {currency}": "{difference}{amount} {currency}",
|
||||||
"{distanceInKm} km": "{distanceInKm} km",
|
"{distanceInKm} km": "{distanceInKm} km",
|
||||||
"{guests, plural, one {# guest} other {# guests}}": "{guests, plural, one {# vieras} other {# vieraita}}",
|
"{guests, plural, one {# guest} other {# guests}}": "{guests, plural, one {# vieras} other {# vieraita}}",
|
||||||
|
|||||||
@@ -967,6 +967,7 @@
|
|||||||
"{count} number": "{count} antall",
|
"{count} number": "{count} antall",
|
||||||
"{count} special character": "{count} spesiell karakter",
|
"{count} special character": "{count} spesiell karakter",
|
||||||
"{count} uppercase letter": "{count} stor bokstav",
|
"{count} uppercase letter": "{count} stor bokstav",
|
||||||
|
"{count} voucher": "{count} voucher",
|
||||||
"{difference}{amount} {currency}": "{difference}{amount} {currency}",
|
"{difference}{amount} {currency}": "{difference}{amount} {currency}",
|
||||||
"{distanceInKm} km": "{distanceInKm} km",
|
"{distanceInKm} km": "{distanceInKm} km",
|
||||||
"{guests, plural, one {# guest} other {# guests}}": "{guests, plural, one {# gjest} other {# gjester}}",
|
"{guests, plural, one {# guest} other {# guests}}": "{guests, plural, one {# gjest} other {# gjester}}",
|
||||||
|
|||||||
@@ -971,6 +971,7 @@
|
|||||||
"{count} number": "{count} nummer",
|
"{count} number": "{count} nummer",
|
||||||
"{count} special character": "{count} speciell karaktär",
|
"{count} special character": "{count} speciell karaktär",
|
||||||
"{count} uppercase letter": "{count} stor bokstav",
|
"{count} uppercase letter": "{count} stor bokstav",
|
||||||
|
"{count} voucher": "{count} voucher",
|
||||||
"{difference}{amount} {currency}": "{difference}{amount} {currency}",
|
"{difference}{amount} {currency}": "{difference}{amount} {currency}",
|
||||||
"{distanceInKm} km": "{distanceInKm} km",
|
"{distanceInKm} km": "{distanceInKm} km",
|
||||||
"{guests, plural, one {# guest} other {# guests}}": "{guests, plural, one {# gäst} other {# gäster}}",
|
"{guests, plural, one {# guest} other {# guests}}": "{guests, plural, one {# gäst} other {# gäster}}",
|
||||||
|
|||||||
@@ -205,6 +205,8 @@ export const bookingConfirmationSchema = z
|
|||||||
childrenAges: z.array(z.number().int()).default([]),
|
childrenAges: z.array(z.number().int()).default([]),
|
||||||
canChangeDate: z.boolean(),
|
canChangeDate: z.boolean(),
|
||||||
bookingCode: z.string().nullable(),
|
bookingCode: z.string().nullable(),
|
||||||
|
cheques: z.number(),
|
||||||
|
vouchers: z.number(),
|
||||||
guaranteeInfo: z
|
guaranteeInfo: z
|
||||||
.object({
|
.object({
|
||||||
maskedCard: z.string(),
|
maskedCard: z.string(),
|
||||||
@@ -227,8 +229,10 @@ export const bookingConfirmationSchema = z
|
|||||||
packages: z.array(packageSchema).default([]),
|
packages: z.array(packageSchema).default([]),
|
||||||
rateDefinition: rateDefinitionSchema,
|
rateDefinition: rateDefinitionSchema,
|
||||||
reservationStatus: z.string().nullable().default(""),
|
reservationStatus: z.string().nullable().default(""),
|
||||||
|
roomPoints: z.number(),
|
||||||
roomPrice: z.number(),
|
roomPrice: z.number(),
|
||||||
roomTypeCode: z.string().default(""),
|
roomTypeCode: z.string().default(""),
|
||||||
|
totalPoints: z.number(),
|
||||||
totalPrice: z.number(),
|
totalPrice: z.number(),
|
||||||
totalPriceExVat: z.number(),
|
totalPriceExVat: z.number(),
|
||||||
vatAmount: z.number(),
|
vatAmount: z.number(),
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { create } from "zustand"
|
|||||||
import type { BreakfastPackage } from "@/types/components/hotelReservation/breakfast"
|
import type { BreakfastPackage } from "@/types/components/hotelReservation/breakfast"
|
||||||
import type { BedTypeSchema } from "@/types/components/hotelReservation/enterDetails/bedType"
|
import type { BedTypeSchema } from "@/types/components/hotelReservation/enterDetails/bedType"
|
||||||
import type { RoomPrice } from "@/types/components/hotelReservation/enterDetails/details"
|
import type { RoomPrice } from "@/types/components/hotelReservation/enterDetails/details"
|
||||||
|
import type { PriceType } from "@/types/components/hotelReservation/myStay/myStay"
|
||||||
import type { Child } from "@/types/components/hotelReservation/selectRate/selectRate"
|
import type { Child } from "@/types/components/hotelReservation/selectRate/selectRate"
|
||||||
import type { Packages } from "@/types/requests/packages"
|
import type { Packages } from "@/types/requests/packages"
|
||||||
import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation"
|
import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation"
|
||||||
@@ -21,6 +22,8 @@ export type Room = Pick<
|
|||||||
| "confirmationNumber"
|
| "confirmationNumber"
|
||||||
| "cancellationNumber"
|
| "cancellationNumber"
|
||||||
| "bookingCode"
|
| "bookingCode"
|
||||||
|
| "cheques"
|
||||||
|
| "vouchers"
|
||||||
| "isCancelable"
|
| "isCancelable"
|
||||||
| "multiRoom"
|
| "multiRoom"
|
||||||
| "canChangeDate"
|
| "canChangeDate"
|
||||||
@@ -28,6 +31,7 @@ export type Room = Pick<
|
|||||||
| "roomTypeCode"
|
| "roomTypeCode"
|
||||||
| "currencyCode"
|
| "currencyCode"
|
||||||
| "vatPercentage"
|
| "vatPercentage"
|
||||||
|
| "roomPoints"
|
||||||
> & {
|
> & {
|
||||||
roomName: string
|
roomName: string
|
||||||
roomNumber: number | null
|
roomNumber: number | null
|
||||||
@@ -41,6 +45,7 @@ export type Room = Pick<
|
|||||||
breakfast: BreakfastPackage | false
|
breakfast: BreakfastPackage | false
|
||||||
mainRoom: boolean
|
mainRoom: boolean
|
||||||
isPrePaid: boolean
|
isPrePaid: boolean
|
||||||
|
priceType: PriceType
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MyStayRoomDetailsState {
|
interface MyStayRoomDetailsState {
|
||||||
@@ -66,6 +71,8 @@ export const useMyStayRoomDetailsStore = create<MyStayRoomDetailsState>(
|
|||||||
confirmationNumber: "",
|
confirmationNumber: "",
|
||||||
cancellationNumber: null,
|
cancellationNumber: null,
|
||||||
bookingCode: null,
|
bookingCode: null,
|
||||||
|
cheques: 0,
|
||||||
|
vouchers: 0,
|
||||||
currencyCode: "",
|
currencyCode: "",
|
||||||
guest: {
|
guest: {
|
||||||
email: "",
|
email: "",
|
||||||
@@ -85,6 +92,7 @@ export const useMyStayRoomDetailsStore = create<MyStayRoomDetailsState>(
|
|||||||
rateCode: "",
|
rateCode: "",
|
||||||
title: null,
|
title: null,
|
||||||
},
|
},
|
||||||
|
roomPoints: 0,
|
||||||
roomPrice: {
|
roomPrice: {
|
||||||
perNight: {
|
perNight: {
|
||||||
requested: {
|
requested: {
|
||||||
@@ -129,6 +137,7 @@ export const useMyStayRoomDetailsStore = create<MyStayRoomDetailsState>(
|
|||||||
linkedReservations: [],
|
linkedReservations: [],
|
||||||
isCancelable: false,
|
isCancelable: false,
|
||||||
isPrePaid: false,
|
isPrePaid: false,
|
||||||
|
priceType: "money",
|
||||||
},
|
},
|
||||||
linkedReservationRooms: [],
|
linkedReservationRooms: [],
|
||||||
actions: {
|
actions: {
|
||||||
|
|||||||
@@ -5,25 +5,27 @@ interface RoomPrice {
|
|||||||
totalPrice: number
|
totalPrice: number
|
||||||
currencyCode: string
|
currencyCode: string
|
||||||
isMainBooking?: boolean
|
isMainBooking?: boolean
|
||||||
|
roomPoints: number
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MyStayTotalPriceState {
|
interface MyStayTotalPriceState {
|
||||||
rooms: RoomPrice[]
|
rooms: RoomPrice[]
|
||||||
totalPrice: number | null
|
totalPrice: number | null
|
||||||
currencyCode: string
|
currencyCode: string
|
||||||
|
totalPoints: number
|
||||||
actions: {
|
actions: {
|
||||||
// Add a single room price
|
// Add a single room price
|
||||||
addRoomPrice: (room: RoomPrice) => void
|
addRoomPrice: (room: RoomPrice) => void
|
||||||
|
|
||||||
// Get the calculated total
|
|
||||||
getTotalPrice: () => number | null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useMyStayTotalPriceStore = create<MyStayTotalPriceState>(
|
export const useMyStayTotalPriceStore = create<MyStayTotalPriceState>(
|
||||||
(set, get) => ({
|
(set) => ({
|
||||||
rooms: [],
|
rooms: [],
|
||||||
totalPrice: null,
|
totalPrice: null,
|
||||||
|
totalPoints: 0,
|
||||||
|
totalCheques: 0,
|
||||||
|
totalVouchers: 0,
|
||||||
currencyCode: "",
|
currencyCode: "",
|
||||||
actions: {
|
actions: {
|
||||||
addRoomPrice: (room) => {
|
addRoomPrice: (room) => {
|
||||||
@@ -52,17 +54,18 @@ export const useMyStayTotalPriceStore = create<MyStayTotalPriceState>(
|
|||||||
return sum
|
return sum
|
||||||
}, 0)
|
}, 0)
|
||||||
|
|
||||||
|
const totalPoints = newRooms.reduce((sum, r) => {
|
||||||
|
return sum + r.roomPoints
|
||||||
|
}, 0)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
rooms: newRooms,
|
rooms: newRooms,
|
||||||
totalPrice: total,
|
totalPrice: total,
|
||||||
currencyCode,
|
currencyCode,
|
||||||
|
totalPoints,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
getTotalPrice: () => {
|
|
||||||
return get().totalPrice
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,3 +2,5 @@ export enum MODAL_STEPS {
|
|||||||
INITIAL = 1,
|
INITIAL = 1,
|
||||||
CONFIRMATION = 2,
|
CONFIRMATION = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type PriceType = "points" | "money" | "voucher" | "cheque"
|
||||||
|
|||||||
Reference in New Issue
Block a user