Files
web/apps/scandic-web/components/HotelReservation/MyStay/Receipt/Specification/index.tsx
Hrishikesh Vaipurkar 0a4bf40a15 Merged in chore/SW-3321-move-selectratecontext-to- (pull request #2729)
chore(SW-3321): Moved Select rate context to booking-flow package

* chore(SW-3321): Moved Select rate context to booking-flow package

* chore(SW-3321): Optimised code


Approved-by: Joakim Jäderberg
2025-09-02 07:40:01 +00:00

243 lines
8.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { calculateVat } from "@scandic-hotels/booking-flow/utils/SelectRate"
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
import { Divider } from "@scandic-hotels/design-system/Divider"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
import { getIntl } from "@/i18n"
import styles from "./specification.module.css"
import type { SpecificationProps } from "@/types/components/hotelReservation/myStay/receipt"
export default async function Specification({
ancillaryPackages,
booking,
currency,
}: SpecificationProps) {
const intl = await getIntl()
const breakfastPackages = booking.packages.filter(
(p) => p.type === "Breakfast"
)
const breakfastTotalPriceInMoney = breakfastPackages
.filter((p) => p.currency !== CurrencyEnum.POINTS)
.reduce((acc, curr) => acc + curr.totalPrice, 0)
const breakfastTotalPriceInPoints = breakfastPackages
.filter((p) => p.currency === CurrencyEnum.POINTS)
.reduce((acc, curr) => acc + curr.totalPrice, 0)
const breakfastCount = breakfastPackages.reduce(
(acc, curr) => acc + curr.unit,
0
)
const displayBreakfastPrice =
breakfastCount > 0 && !booking.rateDefinition.breakfastIncluded
const breakfastMoneyString =
breakfastTotalPriceInMoney > 0
? `${breakfastTotalPriceInMoney} ${currency}`
: ""
const breakfastPointsString =
breakfastTotalPriceInPoints > 0
? `${breakfastTotalPriceInPoints} ${intl.formatMessage({
defaultMessage: "Points",
})}`
: ""
const breakfastPlusString =
breakfastMoneyString && breakfastPointsString ? " + " : ""
const petRoomPackage = booking.packages.find(
(p) => p.code === RoomPackageCodeEnum.PET_ROOM
)
const { vatAmount, priceExclVat } = calculateVat(
booking.roomPrice,
booking.vatPercentage
)
return (
<div className={styles.container}>
<div>
{/****** The room ********/}
<Typography variant="Body/Supporting text (caption)/smBold">
<span>
{intl.formatMessage({
defaultMessage: "Accommodation",
})}
{!booking.rateDefinition.mustBeGuaranteed && (
<>
{" - "}
{intl.formatMessage({
defaultMessage: "Room is prepaid",
})}
</>
)}
</span>
</Typography>
<dl className={styles.dl}>
<Typography variant="Body/Supporting text (caption)/smRegular">
<dt>
{intl.formatMessage({
defaultMessage: "Price including VAT",
})}
</dt>
</Typography>
<Typography variant="Body/Supporting text (caption)/smRegular">
<dd>
{!booking.rateDefinition.mustBeGuaranteed
? // eslint-disable-next-line formatjs/no-literal-string-in-jsx
`(${intl.formatMessage({
defaultMessage: "PREPAID",
})}) `
: null}
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`${booking.roomPrice} ${currency}`}
</dd>
</Typography>
{petRoomPackage && (
<>
<Typography variant="Body/Supporting text (caption)/smRegular">
<dt>
{intl.formatMessage({
defaultMessage: "Pet room charge including VAT",
})}
</dt>
</Typography>
<Typography variant="Body/Supporting text (caption)/smRegular">
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
<dd>{`${petRoomPackage.totalPrice} ${petRoomPackage.currency}`}</dd>
</Typography>
</>
)}
<Typography variant="Body/Supporting text (caption)/smRegular">
<dt className={styles.tertiary}>
{intl.formatMessage({
defaultMessage: "Price excluding VAT",
})}
</dt>
</Typography>
<Typography variant="Body/Supporting text (caption)/smRegular">
<dd className={styles.tertiary}>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`${priceExclVat.toFixed(2)} ${currency}`}
</dd>
</Typography>
<Typography variant="Body/Supporting text (caption)/smRegular">
<dt className={styles.tertiary}>
{intl.formatMessage({
defaultMessage: "VAT",
})}
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{` ${booking.vatPercentage} %`}
</dt>
</Typography>
<Typography variant="Body/Supporting text (caption)/smRegular">
<dd className={styles.tertiary}>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`${vatAmount.toFixed(2)} ${currency}`}
</dd>
</Typography>
</dl>
</div>
{/****** Ancillaries ********/}
{booking.ancillaries.map((ancillary) => (
<>
<Divider />
<div>
<div className={styles.quantifyingHeader}>
<Typography variant="Body/Supporting text (caption)/smBold">
<span>
{ancillaryPackages?.flatMap((a) =>
a.ancillaryContent.filter(
(aa) =>
aa.id === ancillary.code ||
aa.loyaltyCode === ancillary.code
)
)[0]?.title ??
intl.formatMessage({
defaultMessage: "Unknown item",
})}
</span>
</Typography>
<Typography variant="Body/Supporting text (caption)/smBold">
<span>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`× ${ancillary.unit}`}
</span>
</Typography>
</div>
<dl className={styles.dl}>
<Typography variant="Body/Supporting text (caption)/smRegular">
<dt>
{ancillary.currency !== CurrencyEnum.POINTS
? intl.formatMessage({
defaultMessage: "Price including VAT",
})
: intl.formatMessage({
defaultMessage: "Price",
})}
</dt>
</Typography>
<Typography variant="Body/Supporting text (caption)/smRegular">
<dd>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`${ancillary.totalPrice} ${ancillary.currency}`}
</dd>
</Typography>
</dl>
</div>
</>
))}
{/****** Breakfast ********/}
{displayBreakfastPrice && (
<>
<Divider />
<div>
<div className={styles.quantifyingHeader}>
<Typography variant="Body/Supporting text (caption)/smBold">
<span>
{intl.formatMessage({
defaultMessage: "Breakfast",
})}
</span>
</Typography>
<Typography variant="Body/Supporting text (caption)/smBold">
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
<span>{`× ${breakfastCount}`}</span>
</Typography>
</div>
<dl className={styles.dl}>
<Typography variant="Body/Supporting text (caption)/smRegular">
<dt>
{breakfastTotalPriceInMoney > 0
? intl.formatMessage({
defaultMessage: "Price including VAT",
})
: intl.formatMessage({
defaultMessage: "Price",
})}
</dt>
</Typography>
<Typography variant="Body/Supporting text (caption)/smRegular">
<dd>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`${breakfastMoneyString}${breakfastPlusString}${breakfastPointsString}`}
</dd>
</Typography>
</dl>
</div>
</>
)}
</div>
)
}