feat(LOY-64): add ActiveRedeemedBadge UI for on site tier rewards

This commit is contained in:
Chuma McPhoy
2024-12-11 09:32:42 +01:00
parent 2e2b651e15
commit 457f2b942d
15 changed files with 184 additions and 44 deletions

View File

@@ -1,6 +1,6 @@
"use client"
import { motion } from "framer-motion"
import { AnimatePresence, motion } from "framer-motion"
import { useState } from "react"
import {
Dialog,
@@ -11,6 +11,7 @@ import {
import { useIntl } from "react-intl"
import { trpc } from "@/lib/trpc/client"
import { Reward } from "@/server/routers/contentstack/reward/output"
import Countdown from "@/components/Countdown"
import { CheckCircleIcon, CloseLargeIcon } from "@/components/Icons"
@@ -18,6 +19,7 @@ import Button from "@/components/TempDesignSystem/Button"
import Body from "@/components/TempDesignSystem/Text/Body"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import Title from "@/components/TempDesignSystem/Text/Title"
import { isRestaurantOnSiteTierReward } from "@/utils/rewards"
import { RewardIcon } from "../RewardIcon"
@@ -32,7 +34,7 @@ import type {
const MotionOverlay = motion(ModalOverlay)
const MotionModal = motion(Modal)
export default function Redeem({ reward }: RedeemProps) {
export default function Redeem({ reward, memberId }: RedeemProps) {
const [animation, setAnimation] = useState<RedeemModalState>("unmounted")
const intl = useIntl()
const update = trpc.contentstack.rewards.redeem.useMutation()
@@ -100,17 +102,7 @@ export default function Redeem({ reward }: RedeemProps) {
</header>
<div className={styles.modalContent}>
{redeemStep === "redeemed" && (
<div className={styles.badge}>
<div className={styles.redeemed}>
<CheckCircleIcon color="uiSemanticSuccess" />
<Caption>
{intl.formatMessage({
id: "Redeemed & valid through:",
})}
</Caption>
</div>
<Countdown />
</div>
<ConfirmationBadge reward={reward} />
)}
<RewardIcon rewardId={reward.reward_id} />
<Title level="h3" textAlign="center" textTransform="regular">
@@ -127,6 +119,18 @@ export default function Redeem({ reward }: RedeemProps) {
{reward.redeem_description}
</Body>
)}
{redeemStep === "redeemed" &&
isRestaurantOnSiteTierReward(reward) && (
<div className={styles.memberIdBadge}>
<Caption
textTransform="uppercase"
textAlign="center"
color="uiTextHighContrast"
>
{intl.formatMessage({ id: "Member ID:" })} {memberId}
</Caption>
</div>
)}
</div>
{redeemStep === "initial" && (
<footer className={styles.modalFooter}>
@@ -189,3 +193,55 @@ const variants = {
},
},
}
function ConfirmationBadge({ reward }: { reward: Reward }) {
return (
<div className={styles.badge}>
{isRestaurantOnSiteTierReward(reward) ? (
<ActiveRedeemedBadge />
) : (
<TimedRedeemedBadge />
)}
</div>
)
}
function ActiveRedeemedBadge() {
const intl = useIntl()
return (
<div className={styles.redeemed}>
<motion.div
animate={{
opacity: [1, 0.4, 1],
}}
transition={{
duration: 2,
repeat: Infinity,
ease: "easeInOut",
}}
>
<CheckCircleIcon color="uiSemanticSuccess" />
</motion.div>
<Caption>{intl.formatMessage({ id: "Active" })}</Caption>
</div>
)
}
function TimedRedeemedBadge() {
const intl = useIntl()
return (
<>
<div className={styles.redeemed}>
<CheckCircleIcon color="uiSemanticSuccess" />
<Caption>
{intl.formatMessage({
id: "Redeemed & valid through:",
})}
</Caption>
</div>
<Countdown />
</>
)
}