Files
web/apps/scandic-web/components/HotelReservation/EnterDetails/Payment/MixedRatePaymentBreakdown/index.tsx
Anton Gunnarsson 800dc5c3c1 Merged in feat/sw-3225-move-parking-information-to-booking-flow (pull request #2614)
feat(SW-3225): Move ParkingInformation to design-system

* Inline ParkingInformation types to remove trpc dependency

* Move ParkingInformation to design-system

* Move numberFormatting to common package

* Add deps to external

* Fix imports and i18n script

* Add common as dependency

* Merge branch 'master' into feat/sw-3225-move-parking-information-to-booking-flow


Approved-by: Linus Flood
2025-08-12 12:36:31 +00:00

145 lines
3.7 KiB
TypeScript

import React from "react"
import { useIntl } from "react-intl"
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
import Body from "@scandic-hotels/design-system/Body"
import Caption from "@scandic-hotels/design-system/Caption"
import {
calculateTotalRoomPrice,
hasFlexibleRate,
hasPrepaidRate,
} from "../helpers"
import styles from "./mixedRatePaymentBreakdown.module.css"
import type { RoomState } from "@/types/stores/enter-details"
type PaymentBreakdownState = {
roomsWithPrepaidRate: number[]
roomsWithFlexRate: number[]
payNowPrice: number
payNowComparisonPrice: number
payAtCheckInPrice: number
payAtCheckInComparisonPrice: number
}
interface MixedRatePaymentBreakdownProps {
rooms: RoomState[]
currency: string
}
export default function MixedRatePaymentBreakdown({
rooms,
currency,
}: MixedRatePaymentBreakdownProps) {
const intl = useIntl()
const payNowTitle = intl.formatMessage({
defaultMessage: "Pay now",
})
const payAtCheckInTitle = intl.formatMessage({
defaultMessage: "Pay at check-in",
})
const initialState: PaymentBreakdownState = {
roomsWithPrepaidRate: [],
roomsWithFlexRate: [],
payNowPrice: 0,
payNowComparisonPrice: 0,
payAtCheckInPrice: 0,
payAtCheckInComparisonPrice: 0,
}
const {
roomsWithPrepaidRate,
roomsWithFlexRate,
payNowPrice,
payNowComparisonPrice,
payAtCheckInPrice,
payAtCheckInComparisonPrice,
} = rooms.reduce((acc, room, idx) => {
if (hasPrepaidRate(room)) {
acc.roomsWithPrepaidRate.push(idx)
const { totalPrice, comparisonPrice } = calculateTotalRoomPrice(room)
acc.payNowPrice += totalPrice
acc.payNowComparisonPrice += comparisonPrice
}
if (hasFlexibleRate(room)) {
acc.roomsWithFlexRate.push(idx)
const { totalPrice, comparisonPrice } = calculateTotalRoomPrice(room)
acc.payAtCheckInPrice += totalPrice
acc.payAtCheckInComparisonPrice += comparisonPrice
}
return acc
}, initialState)
return (
<div className={styles.container}>
<PaymentCard
title={payNowTitle}
price={payNowPrice}
comparisonPrice={payNowComparisonPrice}
currency={currency}
roomIndexes={roomsWithPrepaidRate}
/>
<PaymentCard
title={payAtCheckInTitle}
price={payAtCheckInPrice}
comparisonPrice={payAtCheckInComparisonPrice}
currency={currency}
roomIndexes={roomsWithFlexRate}
/>
</div>
)
}
interface PaymentCardProps {
title: string
price: number
comparisonPrice: number
currency: string
roomIndexes: number[]
}
function PaymentCard({
title,
price,
comparisonPrice,
currency,
roomIndexes,
}: PaymentCardProps) {
const intl = useIntl()
const isMemberRateApplied = price < comparisonPrice
return (
<div className={styles.card}>
<Caption
type="bold"
textTransform="uppercase"
className={styles.cardTitle}
>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{title}{" "}
<span>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{"/ "}
{intl.formatMessage(
{
defaultMessage: "Room {roomIndex}",
},
{
roomIndex: roomIndexes.map((idx) => idx + 1).join(" & "),
}
)}
</span>
</Caption>
<Body textTransform="bold" className={styles.priceItem}>
{formatPrice(intl, price, currency)}
{isMemberRateApplied && comparisonPrice ? (
<span>{formatPrice(intl, comparisonPrice, currency)}</span>
) : null}
</Body>
</div>
)
}