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
145 lines
3.7 KiB
TypeScript
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>
|
|
)
|
|
}
|