Files
web/apps/scandic-web/components/Blocks/DynamicContent/RewardNights/index.tsx
Matilda Landström 8764945b2f Merged in fix/LOY-430-filter-old-campaigns (pull request #3317)
fix(LOY-430): don't show inactive campaigns

* fix(LOY-430): don't show inactive campaigns


Approved-by: Chuma Mcphoy (We Ahead)
2025-12-09 10:51:23 +00:00

129 lines
4.0 KiB
TypeScript

import { cx } from "class-variance-authority"
import Table from "@scandic-hotels/design-system/Table"
import { TextLink } from "@scandic-hotels/design-system/TextLink"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { getAllHotelData } from "@/lib/trpc/memoizedRequests"
import { getIntl } from "@/i18n"
import styles from "./rewardNights.module.css"
import type { RewardNight } from "@scandic-hotels/trpc/types/hotel"
export async function RewardNights() {
const intl = await getIntl()
const hotelData = await getAllHotelData()
return (
<Table intent="striped" variant="content" style={{ textWrap: "balance" }}>
<Table.THead>
<Table.TR>
<Table.TH>
{intl.formatMessage({
id: "rewardNights.table.hotel",
defaultMessage: "Hotel",
})}
</Table.TH>
<Table.TH>
{intl.formatMessage({
id: "rewardNights.table.destination",
defaultMessage: "Destination",
})}
</Table.TH>
<Table.TH>
{intl.formatMessage({
id: "common.points",
defaultMessage: "Points",
})}
</Table.TH>
</Table.TR>
</Table.THead>
<Table.TBody>
{hotelData.map((data) => {
const { hotel } = data
const hasCampaign = hasActiveCampaign(hotel.rewardNight.campaign)
return (
<Table.TR key={hotel.id}>
<Table.TD style={{ alignContent: "flex-start" }}>
<TextLink href={data.url ?? ""}>{hotel.name}</TextLink>
</Table.TD>
<Table.TD>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`${hotel.address.city}, ${hotel.address.country}`}
{hasCampaign ? (
<OfferPrice {...hotel.rewardNight.campaign} />
) : null}
</Table.TD>
<Table.TD style={{ alignContent: "flex-start" }}>
<div className={cx({ [styles.grid]: hasCampaign })}>
{formatPoints(hotel.rewardNight.points)}
{hasCampaign ? (
<Typography
variant="Body/Paragraph/mdBold"
className={styles.highlightedText}
>
<span>
{formatPoints(hotel.rewardNight.campaign.points)}
</span>
</Typography>
) : null}
</div>
</Table.TD>
</Table.TR>
)
})}
</Table.TBody>
</Table>
)
}
interface OfferPriceProps {
points: number
start: string
end: string
}
async function OfferPrice(offer: OfferPriceProps) {
const intl = await getIntl()
return (
<div className={styles.offerPrice}>
<Typography variant="Body/Paragraph/mdBold">
<p className={styles.highlightedText}>
{intl.formatMessage({
id: "rewardNights.offerPrice",
defaultMessage: "Offer price",
})}
</p>
</Typography>
<Typography variant="Label/xsBold">
<p>
{intl.formatMessage({
id: "rewardNights.stayBetween:",
defaultMessage: "Stay between:",
})}
</p>
</Typography>
<Typography variant="Label/xsRegular">
<time>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{formatDate(offer.start)} - {formatDate(offer.end)}
</time>
</Typography>
</div>
)
}
function formatPoints(number: number) {
const format = new Intl.NumberFormat("fr-FR")
return format.format(number).replace(/\u202F/g, " ")
}
function formatDate(date?: string) {
return new Date(date ?? Date.now()).toISOString().split("T")[0]
}
function hasActiveCampaign(campaign: RewardNight["campaign"]) {
return campaign.points && formatDate(campaign.end) >= formatDate()
}