233 lines
7.0 KiB
TypeScript
233 lines
7.0 KiB
TypeScript
"use client"
|
|
import { Fragment } from "react"
|
|
import { useIntl } from "react-intl"
|
|
|
|
import { longDateFormat } from "@scandic-hotels/common/constants/dateFormats"
|
|
import { dt } from "@scandic-hotels/common/dt"
|
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
|
|
|
import useLang from "../../../hooks/useLang"
|
|
import BookingCodeRow from "./Row/BookingCode"
|
|
import HeaderRow from "./Row/Header"
|
|
import LargeRow from "./Row/Large"
|
|
import CorporateChequePrice, {
|
|
type CorporateChequePriceType,
|
|
} from "./Row/Price/CorporateCheque"
|
|
import RedemptionPrice, {
|
|
type RedemptionPriceType,
|
|
} from "./Row/Price/Redemption"
|
|
import RegularPrice, { type RegularPriceType } from "./Row/Price/Regular"
|
|
import VoucherPrice, { type VoucherPriceType } from "./Row/Price/Voucher"
|
|
import VatRow from "./Row/Vat"
|
|
import Breakfast from "./Breakfast"
|
|
import Tbody from "./Tbody"
|
|
|
|
import styles from "./priceDetailsTable.module.css"
|
|
|
|
import type { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
|
import type { BreakfastPackage } from "@scandic-hotels/trpc/routers/hotels/schemas/packages"
|
|
import type { Child } from "@scandic-hotels/trpc/types/child"
|
|
import type { Packages } from "@scandic-hotels/trpc/types/packages"
|
|
import type { RateDefinition } from "@scandic-hotels/trpc/types/roomAvailability"
|
|
|
|
import type { Price } from "../../../types/price"
|
|
|
|
type RoomPrice =
|
|
| CorporateChequePriceType
|
|
| RegularPriceType
|
|
| RedemptionPriceType
|
|
| VoucherPriceType
|
|
|
|
export interface Room {
|
|
adults: number
|
|
bedType:
|
|
| {
|
|
description: string
|
|
type: string
|
|
roomTypeCode: string
|
|
}
|
|
| undefined
|
|
breakfast: Omit<BreakfastPackage, "requestedPrice"> | false | undefined | null
|
|
breakfastChildren?: Omit<BreakfastPackage, "requestedPrice"> | null
|
|
breakfastIncluded: boolean
|
|
childrenInRoom: Child[] | undefined
|
|
packages: Packages | null
|
|
price: RoomPrice
|
|
rateDefinition: Pick<RateDefinition, "isMemberRate">
|
|
roomType: string
|
|
}
|
|
|
|
export interface PriceDetailsTableProps {
|
|
bookingCode?: string
|
|
fromDate: string
|
|
isCampaignRate?: boolean
|
|
rooms: Room[]
|
|
toDate: string
|
|
totalPrice: Price
|
|
vat: number
|
|
defaultCurrency: CurrencyEnum
|
|
}
|
|
|
|
export default function PriceDetailsTable({
|
|
bookingCode,
|
|
fromDate,
|
|
isCampaignRate,
|
|
rooms,
|
|
toDate,
|
|
totalPrice,
|
|
vat,
|
|
defaultCurrency,
|
|
}: PriceDetailsTableProps) {
|
|
const intl = useIntl()
|
|
const lang = useLang()
|
|
|
|
const nights = dt(toDate).diff(fromDate, "days")
|
|
const nightsMsg = intl.formatMessage(
|
|
{ defaultMessage: "{totalNights, plural, one {# night} other {# nights}}" },
|
|
{ totalNights: nights }
|
|
)
|
|
|
|
const arrival = dt(fromDate).locale(lang).format(longDateFormat[lang])
|
|
const departue = dt(toDate).locale(lang).format(longDateFormat[lang])
|
|
const duration = ` ${arrival} - ${departue} (${nightsMsg})`
|
|
|
|
const isAllBreakfastIncluded = rooms.every((room) => room.breakfastIncluded)
|
|
|
|
const allPricesIsDiscounted = rooms.every((room) => {
|
|
if (!("regular" in room.price)) {
|
|
return false
|
|
}
|
|
if (room.rateDefinition.isMemberRate) {
|
|
return true
|
|
}
|
|
if (!room.price.regular) {
|
|
return false
|
|
}
|
|
|
|
return room.price.regular.pricePerStay > room.price.regular.pricePerStay
|
|
})
|
|
|
|
return (
|
|
<table className={styles.priceDetailsTable}>
|
|
{rooms.map((room, idx) => {
|
|
let currency = ""
|
|
let chequePrice: CorporateChequePriceType["corporateCheque"] | undefined
|
|
if ("corporateCheque" in room.price && room.price.corporateCheque) {
|
|
chequePrice = room.price.corporateCheque
|
|
|
|
if (room.price.corporateCheque.currency) {
|
|
currency = room.price.corporateCheque.currency
|
|
}
|
|
}
|
|
|
|
let isMemberRate = false
|
|
let price: RegularPriceType["regular"] | undefined
|
|
if ("regular" in room.price && room.price.regular) {
|
|
price = room.price.regular
|
|
currency = room.price.regular.currency
|
|
isMemberRate = room.rateDefinition.isMemberRate
|
|
}
|
|
|
|
let redemptionPrice: RedemptionPriceType["redemption"] | undefined
|
|
if ("redemption" in room.price && room.price.redemption) {
|
|
redemptionPrice = room.price.redemption
|
|
|
|
if (room.price.redemption.currency) {
|
|
currency = room.price.redemption.currency
|
|
}
|
|
}
|
|
|
|
let voucherPrice: VoucherPriceType["voucher"] | undefined
|
|
if ("voucher" in room.price && room.price.voucher) {
|
|
voucherPrice = room.price.voucher
|
|
}
|
|
|
|
if (!currency) {
|
|
currency = defaultCurrency
|
|
}
|
|
|
|
if (!price && !voucherPrice && !chequePrice && !redemptionPrice) {
|
|
return null
|
|
}
|
|
|
|
return (
|
|
<Fragment key={idx}>
|
|
<Tbody>
|
|
{rooms.length > 1 && (
|
|
<tr>
|
|
<th colSpan={2}>
|
|
<Typography variant="Body/Paragraph/mdBold">
|
|
<span>
|
|
{intl.formatMessage(
|
|
{ defaultMessage: "Room {roomIndex}" },
|
|
{ roomIndex: idx + 1 }
|
|
)}
|
|
</span>
|
|
</Typography>
|
|
</th>
|
|
</tr>
|
|
)}
|
|
<HeaderRow title={room.roomType} subtitle={duration} />
|
|
<RegularPrice
|
|
bedType={room.bedType}
|
|
packages={room.packages}
|
|
isMemberRate={isMemberRate}
|
|
nights={nights}
|
|
price={price}
|
|
/>
|
|
<CorporateChequePrice
|
|
bedType={room.bedType}
|
|
currency={currency}
|
|
nights={nights}
|
|
packages={room.packages}
|
|
price={chequePrice}
|
|
/>
|
|
<RedemptionPrice
|
|
bedType={room.bedType}
|
|
currency={currency}
|
|
nights={nights}
|
|
packages={room.packages}
|
|
price={redemptionPrice}
|
|
/>
|
|
<VoucherPrice
|
|
bedType={room.bedType}
|
|
currency={currency}
|
|
nights={nights}
|
|
packages={room.packages}
|
|
price={voucherPrice}
|
|
/>
|
|
</Tbody>
|
|
|
|
<Breakfast
|
|
adults={room.adults}
|
|
breakfast={room.breakfast}
|
|
breakfastChildren={room.breakfastChildren}
|
|
breakfastIncluded={room.breakfastIncluded}
|
|
childrenInRoom={room.childrenInRoom}
|
|
currency={currency}
|
|
nights={nights}
|
|
/>
|
|
</Fragment>
|
|
)
|
|
})}
|
|
<Tbody>
|
|
<HeaderRow title={intl.formatMessage({ defaultMessage: "Total" })} />
|
|
|
|
<VatRow totalPrice={totalPrice} vat={vat} />
|
|
|
|
<LargeRow
|
|
allPricesIsDiscounted={allPricesIsDiscounted}
|
|
label={intl.formatMessage({ defaultMessage: "Price including VAT" })}
|
|
price={totalPrice}
|
|
/>
|
|
|
|
<BookingCodeRow
|
|
isCampaignRate={isCampaignRate}
|
|
isBreakfastIncluded={isAllBreakfastIncluded}
|
|
bookingCode={bookingCode}
|
|
/>
|
|
</Tbody>
|
|
</table>
|
|
)
|
|
}
|