feat(LOY-154): add expiration date to rewards

This commit is contained in:
Christian Andolf
2025-03-10 13:18:54 +01:00
parent 7563db9dbc
commit b45157818f
8 changed files with 139 additions and 86 deletions

View File

@@ -7,9 +7,11 @@ import { trpc } from "@/lib/trpc/client"
import { RewardIcon } from "@/components/Blocks/DynamicContent/Rewards/RewardIcon"
import ScriptedRewardText from "@/components/Blocks/DynamicContent/Rewards/ScriptedRewardText"
import Pagination from "@/components/MyPages/Pagination"
import ExpirationDate from "@/components/Rewards/ExpirationDate"
import Grids from "@/components/TempDesignSystem/Grids"
import Title from "@/components/TempDesignSystem/Text/Title"
import useLang from "@/hooks/useLang"
import { getEarliestExpirationDate } from "@/utils/rewards"
import Redeem from "../Redeem"
@@ -67,32 +69,44 @@ export default function ClientCurrentRewards({
return (
<div ref={containerRef} className={styles.container}>
<Grids.Stackable>
{currentRewards.map((reward, idx) => (
<article className={styles.card} key={`${reward.reward_id}-${idx}`}>
<div className={styles.content}>
<RewardIcon rewardId={reward.reward_id} />
{showRedeem && (
<ScriptedRewardText
rewardType={reward.rewardType}
rewardTierLevel={reward.rewardTierLevel}
/>
)}
<Title
as="h4"
level="h3"
textAlign="center"
textTransform="regular"
>
{reward.label}
</Title>
</div>
{showRedeem && "redeem_description" in reward && (
<div className={styles.btnContainer}>
<Redeem reward={reward} membershipNumber={membershipNumber} />
{currentRewards.map((reward, idx) => {
const earliestExpirationDate =
"coupons" in reward
? getEarliestExpirationDate(reward.coupons)
: null
return (
<article className={styles.card} key={`${reward.reward_id}-${idx}`}>
<div className={styles.content}>
<RewardIcon rewardId={reward.reward_id} />
{showRedeem && (
<ScriptedRewardText
rewardType={reward.rewardType}
rewardTierLevel={reward.rewardTierLevel}
/>
)}
<Title
as="h4"
level="h3"
textAlign="center"
textTransform="regular"
>
{reward.label}
</Title>
{earliestExpirationDate ? (
<ExpirationDate expirationDate={earliestExpirationDate} />
) : null}
</div>
)}
</article>
))}
{showRedeem && "redeem_description" in reward && (
<div className={styles.btnContainer}>
<Redeem reward={reward} membershipNumber={membershipNumber} />
</div>
)}
</article>
)
})}
</Grids.Stackable>
{totalPages > 1 && (
<Pagination

View File

@@ -1,51 +1,19 @@
import { useIntl } from "react-intl"
import { dt } from "@/lib/dt"
import ExpirationDate from "@/components/Rewards/ExpirationDate"
import Body from "@/components/TempDesignSystem/Text/Body"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import useLang from "@/hooks/useLang"
import { getEarliestExpirationDate } from "@/utils/rewards"
import Card from "./Card"
import styles from "./surprises.module.css"
import type { Dayjs } from "dayjs"
import type { SlideProps } from "@/types/components/blocks/surprises"
export default function Slide({ surprise }: SlideProps) {
const lang = useLang()
const intl = useIntl()
const earliestExpirationDate = surprise.coupons
.map(({ expiresAt }) => expiresAt)
.filter((expiresAt): expiresAt is string => !!expiresAt)
.reduce((earliestDate: Dayjs | null, expiresAt) => {
const expiresAtDate = dt(expiresAt)
if (!earliestDate) {
return expiresAtDate
}
return earliestDate.isBefore(expiresAtDate) ? earliestDate : expiresAtDate
}, null)
const earliestExpirationDate = getEarliestExpirationDate(surprise.coupons)
return (
<Card title={surprise.label}>
<Body textAlign="center">{surprise.description}</Body>
{earliestExpirationDate ? (
<div className={styles.badge}>
<Caption>
{intl.formatMessage(
{ id: "Valid through {expirationDate}" },
{
expirationDate: dt(earliestExpirationDate)
.locale(lang)
.format("D MMM YYYY"),
}
)}
</Caption>
</div>
<ExpirationDate expirationDate={earliestExpirationDate} />
) : null}
</Card>
)

View File

@@ -125,16 +125,6 @@
transform: rotate(180deg);
}
.badge {
padding: var(--Spacing-x1) var(--Spacing-x-one-and-half);
display: flex;
flex-direction: column;
align-items: center;
gap: var(--Spacing-x-half);
background-color: var(--Base-Surface-Secondary-light-Normal);
border-radius: var(--Corner-radius-Small);
}
.close {
background: none;
border: none;

View File

@@ -0,0 +1,9 @@
.badge {
padding: var(--Spacing-x1) var(--Spacing-x-one-and-half);
display: flex;
flex-direction: column;
align-items: center;
gap: var(--Spacing-x-half);
background-color: var(--Base-Surface-Secondary-light-Normal);
border-radius: var(--Corner-radius-Small);
}

View File

@@ -0,0 +1,36 @@
"use client"
import { useIntl } from "react-intl"
import { dt } from "@/lib/dt"
import Body from "@/components/TempDesignSystem/Text/Body"
import useLang from "@/hooks/useLang"
import styles from "./expirationDate.module.css"
import type { Dayjs } from "dayjs"
export default function ExpirationDate({
expirationDate,
}: {
expirationDate: Dayjs | string
}) {
const intl = useIntl()
const lang = useLang()
return (
<div className={styles.badge}>
<Body textTransform="bold">
{intl.formatMessage(
{ id: "Valid through {expirationDate}" },
{
expirationDate: dt(expirationDate)
.locale(lang)
.format("D MMM YYYY"),
}
)}
</Body>
</div>
)
}