feat(SW-2863): Move contentstack router to trpc package * Add exports to packages and lint rule to prevent relative imports * Add env to trpc package * Add eslint to trpc package * Apply lint rules * Use direct imports from trpc package * Add lint-staged config to trpc * Move lang enum to common * Restructure trpc package folder structure * WIP first step * update internal imports in trpc * Fix most errors in scandic-web Just 100 left... * Move Props type out of trpc * Fix CategorizedFilters types * Move more schemas in hotel router * Fix deps * fix getNonContentstackUrls * Fix import error * Fix entry error handling * Fix generateMetadata metrics * Fix alertType enum * Fix duplicated types * lint:fix * Merge branch 'master' into feat/sw-2863-move-contentstack-router-to-trpc-package * Fix broken imports * Merge branch 'master' into feat/sw-2863-move-contentstack-router-to-trpc-package Approved-by: Linus Flood
243 lines
8.5 KiB
TypeScript
243 lines
8.5 KiB
TypeScript
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 { calculateVat } from "@/components/HotelReservation/utils"
|
||
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>
|
||
)
|
||
}
|