Feat/lokalise rebuild * chore(lokalise): update translation ids * chore(lokalise): easier to switch between projects * chore(lokalise): update translation ids * . * . * . * . * . * . * chore(lokalise): update translation ids * chore(lokalise): update translation ids * . * . * . * chore(lokalise): update translation ids * chore(lokalise): update translation ids * . * . * chore(lokalise): update translation ids * chore(lokalise): update translation ids * chore(lokalise): new translations * merge * switch to errors for missing id's * merge * sync translations Approved-by: Linus Flood
260 lines
9.3 KiB
TypeScript
260 lines
9.3 KiB
TypeScript
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
|
||
? intl.formatMessage(
|
||
{
|
||
id: "common.numberOfPoints",
|
||
defaultMessage: "{points, plural, one {# point} other {# points}}",
|
||
},
|
||
{ points: breakfastTotalPriceInPoints }
|
||
)
|
||
: ""
|
||
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({
|
||
id: "myStay.receipt.accommodation",
|
||
defaultMessage: "Accommodation",
|
||
})}
|
||
{!booking.rateDefinition.mustBeGuaranteed && (
|
||
<>
|
||
{" - "}
|
||
{intl.formatMessage({
|
||
id: "myStay.receipt.prepaidRoom",
|
||
defaultMessage: "Room is prepaid",
|
||
})}
|
||
</>
|
||
)}
|
||
</span>
|
||
</Typography>
|
||
<dl className={styles.dl}>
|
||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||
<dt>
|
||
{intl.formatMessage({
|
||
id: "booking.priceIncludingVat",
|
||
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({
|
||
id: "myStay.receipt.prepaid",
|
||
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({
|
||
id: "myStay.receipt.petRoomChargeIncludingVat",
|
||
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({
|
||
id: "booking.priceExcludingVat",
|
||
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({
|
||
id: "common.vat",
|
||
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({
|
||
id: "myStay.receipt.unknownItem",
|
||
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({
|
||
id: "booking.priceIncludingVat",
|
||
defaultMessage: "Price including VAT",
|
||
})
|
||
: intl.formatMessage({
|
||
id: "common.price",
|
||
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({
|
||
id: "common.breakfast",
|
||
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({
|
||
id: "booking.priceIncludingVat",
|
||
defaultMessage: "Price including VAT",
|
||
})
|
||
: intl.formatMessage({
|
||
id: "common.price",
|
||
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>
|
||
)
|
||
}
|