refactor(LOY-175): rewrite reward types according to new api endpoints

This commit is contained in:
Christian Andolf
2025-03-11 16:09:15 +01:00
parent 0ae4c5db17
commit b86347b4f4
15 changed files with 196 additions and 246 deletions

View File

@@ -19,10 +19,10 @@ import Redeem from "../Redeem"
import styles from "./current.module.css"
import type { CurrentRewardsClientProps } from "@/types/components/myPages/myPage/accountPage"
import type {
Reward,
RewardWithRedeem,
} from "@/server/routers/contentstack/reward/output"
import {
type Reward,
type RewardWithRedeem,
} from "@/types/components/myPages/rewards"
export default function ClientCurrentRewards({
rewards: initialData,
@@ -70,21 +70,15 @@ export default function ClientCurrentRewards({
<div ref={containerRef} className={styles.container}>
<Grids.Stackable>
{paginatedRewards.map((reward, idx) => {
const earliestExpirationDate =
"coupons" in reward
? getEarliestExpirationDate(reward.coupons)
: null
const earliestExpirationDate = getEarliestExpirationDate(
reward.data.coupon
)
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}
/>
)}
{showRedeem && <ScriptedRewardText reward={reward} />}
<Title
as="h4"
level="h3"

View File

@@ -22,6 +22,12 @@ export default function Campaign() {
return null
}
if (reward.data.rewardType !== "Campaign") {
return null
}
const operaRewardId = reward.data.operaRewardId
return (
<>
<div className={styles.modalContent}>
@@ -35,7 +41,7 @@ export default function Campaign() {
{intl.formatMessage({ id: "Promo code" })}
</Caption>
<Caption textAlign="center" color="uiTextHighContrast">
{reward.operaRewardId}
{operaRewardId}
</Caption>
</div>
</div>
@@ -43,7 +49,7 @@ export default function Campaign() {
<Button
onClick={() => {
try {
navigator.clipboard.writeText(reward.operaRewardId)
navigator.clipboard.writeText(operaRewardId)
toast.success(intl.formatMessage({ id: "Copied to clipboard" }))
} catch {
toast.error(intl.formatMessage({ id: "Failed to copy" }))

View File

@@ -35,7 +35,7 @@ export default function Tier({
<div className={styles.modalContent}>
{redeemStep === "redeemed" && (
<div className={styles.badge}>
{isRestaurantOnSiteTierReward(reward) ? (
{isRestaurantOnSiteTierReward(reward.data) ? (
<ActiveRedeemedBadge />
) : (
<TimedRedeemedBadge />
@@ -47,7 +47,7 @@ export default function Tier({
{reward.label}
</Title>
{reward.redeemLocation !== "Non-redeemable" ? (
{reward.data.redeemLocation !== "Non-redeemable" ? (
<>
{redeemStep === "initial" && (
<Body textAlign="center">{reward.description}</Body>
@@ -63,7 +63,7 @@ export default function Tier({
)}
{redeemStep === "redeemed" &&
isRestaurantOnSiteTierReward(reward) &&
isRestaurantOnSiteTierReward(reward.data) &&
membershipNumber && (
<MembershipNumberBadge membershipNumber={membershipNumber} />
)}
@@ -76,7 +76,7 @@ export default function Tier({
)}
</div>
{reward.redeemLocation !== "Non-redeemable" ? (
{reward.data.redeemLocation !== "Non-redeemable" ? (
<>
{redeemStep === "initial" && (
<footer className={styles.modalFooter}>

View File

@@ -29,7 +29,7 @@ import type {
RedeemProps,
RedeemStep,
} from "@/types/components/myPages/myPage/accountPage"
import type { RewardWithRedeem } from "@/server/routers/contentstack/reward/output"
import type { RewardWithRedeem } from "@/types/components/myPages/rewards"
const MotionOverlay = motion(ModalOverlay)
const MotionModal = motion(Modal)
@@ -70,7 +70,7 @@ export default function Redeem({ reward, membershipNumber }: RedeemProps) {
onOpenChange={(isOpen) => setAnimation(isOpen ? "visible" : "hidden")}
>
<Button intent="primary" fullWidth>
{reward.redeemLocation === "Non-redeemable"
{reward.data.redeemLocation === "Non-redeemable"
? intl.formatMessage({ id: "How to use" })
: intl.formatMessage({ id: "Open" })}
</Button>
@@ -108,7 +108,7 @@ export default function Redeem({ reward, membershipNumber }: RedeemProps) {
onClick={() => {
if (
redeemStep === "redeemed" &&
!isRestaurantOnSiteTierReward(reward)
!isRestaurantOnSiteTierReward(reward.data)
) {
setRedeemStep("confirm-close")
} else {
@@ -165,14 +165,17 @@ const variants = {
}
function getRedeemFlow(reward: RewardWithRedeem, membershipNumber: string) {
switch (reward.rewardType) {
switch (reward.data.rewardType) {
case "Campaign":
return <Campaign />
case "Surprise":
case "Tier":
return <Tier membershipNumber={membershipNumber} />
default:
console.warn("Unsupported reward type for redeem:", reward.rewardType)
console.warn(
"Unsupported reward type for redeem:",
reward.data.rewardType
)
return null
}
}

View File

@@ -4,8 +4,10 @@ import { createContext, useCallback, useContext, useEffect } from "react"
import { trpc } from "@/lib/trpc/client"
import { getFirstRedeemableCoupon } from "@/utils/rewards"
import type { RedeemFlowContext } from "@/types/components/myPages/myPage/accountPage"
import type { RewardWithRedeem } from "@/server/routers/contentstack/reward/output"
import type { RewardWithRedeem } from "@/types/components/myPages/rewards"
export const RedeemContext = createContext<RedeemFlowContext>({
reward: null,
@@ -31,9 +33,10 @@ export default function useRedeemFlow() {
}>()
const onRedeem = useCallback(() => {
if (reward?.id) {
if (reward?.data.id) {
const coupon = getFirstRedeemableCoupon(reward.data)
update.mutate(
{ rewardId: reward.id, couponCode: reward.couponCode },
{ rewardId: reward.data.id, couponCode: coupon.couponCode },
{
onSuccess() {
setRedeemStep("redeemed")

View File

@@ -4,24 +4,22 @@ import { TIER_TO_FRIEND_MAP } from "@/constants/membershipLevels"
import BiroScript from "@/components/TempDesignSystem/Text/BiroScript"
import { isMembershipLevel } from "@/utils/membershipLevels"
import { getRewardType } from "@/utils/rewards"
import type { ScriptedRewardTextProps } from "@/types/components/myPages/myPage/accountPage"
export default function ScriptedRewardText({
rewardType,
rewardTierLevel,
reward,
}: ScriptedRewardTextProps) {
const intl = useIntl()
function getLabel(rewardType?: string, rewardTierLevel?: string) {
const type = getRewardType(rewardType)
switch (type) {
case "Tier":
function getLabel() {
switch (reward.data.rewardType) {
case "Tier": {
const { rewardTierLevel } = reward.data
return rewardTierLevel && isMembershipLevel(rewardTierLevel)
? TIER_TO_FRIEND_MAP[rewardTierLevel]
: null
}
case "Campaign":
return intl.formatMessage({ id: "Campaign" })
case "Surprise":
@@ -33,7 +31,7 @@ export default function ScriptedRewardText({
}
}
const label = getLabel(rewardType, rewardTierLevel)
const label = getLabel()
if (!label) return null

View File

@@ -125,11 +125,11 @@ export default function SurprisesNotification({
async function viewRewards() {
const updates = surprises
.map((surprise) => {
const coupons = surprise.coupons
const coupons = surprise.data.coupon
.map((coupon) => {
if (coupon.couponCode) {
return {
rewardId: surprise.id,
rewardId: surprise.data.id,
couponCode: coupon.couponCode,
}
}