Files
web/packages/booking-flow/lib/components/PriceDetailsModal/PriceDetailsTable/index.tsx
Anton Gunnarsson f7ef58eafa Merged in feat/sw-2874-move-select-rate (pull request #2750)
Approved-by: Joakim Jäderberg
2025-09-03 08:30:05 +00:00

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