Merged in feat/LOY-55-Filter-Modal (pull request #1509)

feat(LOY-55): Add FilterRewardsModal

* feat(LOY-55): Add rewards filtering functionality

- Implement dynamic rewards filtering by category and membership level
- Create FilterRewardsModal component for filtering rewards
- Add useFilteredRewards hook to handle filtering logic
- Update rewards schema and constants to support new filtering features
- Remove hardcoded page size and replace with constant

* fix(LOY-55): reuse existing tier to friend map

* refactor(LOY-55): fix checkbox onChange type safety

* refactor(LOY-55): Improve rewards filtering type safety and validation

* refactor(LOY-55): Update filter modal border color using design token


Approved-by: Christian Andolf
This commit is contained in:
Chuma Mcphoy (We Ahead)
2025-03-12 13:29:35 +00:00
parent 2e887aaff8
commit 1ef6fd02c1
12 changed files with 594 additions and 12 deletions

View File

@@ -1,6 +1,7 @@
import { z } from "zod"
import { MembershipLevelEnum } from "@/constants/membershipLevels"
import { COUPON_REWARD_TYPES, REWARD_CATEGORIES } from "@/constants/rewards"
import {
linkRefsUnionSchema,
@@ -9,6 +10,8 @@ import {
} from "../schemas/pageLinks"
import { systemSchema } from "../schemas/system"
import type { RewardCategory } from "@/types/components/myPages/rewards"
const Coupon = z.object({
code: z.string().optional(),
status: z.string().optional(),
@@ -211,6 +214,7 @@ export type Reward = CMSReward & {
redeemLocation: string | undefined
rewardTierLevel: string | undefined
operaRewardId: string
categories: RewardCategory[]
couponCode: string | undefined
coupons: Coupon[]
}
@@ -221,6 +225,7 @@ export type RewardWithRedeem = CMSRewardWithRedeem & {
redeemLocation: string | undefined
rewardTierLevel: string | undefined
operaRewardId: string
categories: RewardCategory[]
couponCode: string | undefined
coupons: Coupon[]
}
@@ -261,8 +266,9 @@ const CouponData = z.object({
const CouponReward = BaseReward.merge(
z.object({
rewardType: z.enum(["Surprise", "Campaign", "Member-voucher"]),
rewardType: z.enum(COUPON_REWARD_TYPES),
operaRewardId: z.string().default(""),
categories: z.array(z.enum(REWARD_CATEGORIES)).optional(),
coupon: z
.array(CouponData)
.optional()

View File

@@ -286,6 +286,10 @@ export const rewardQueryRouter = router({
apiReward && "operaRewardId" in apiReward
? apiReward.operaRewardId
: "",
categories:
apiReward && "categories" in apiReward
? apiReward.categories || []
: [],
couponCode: firstRedeemableCouponToExpire,
coupons:
apiReward && "coupon" in apiReward ? apiReward.coupon || [] : [],
@@ -406,6 +410,8 @@ export const rewardQueryRouter = router({
rewardType: surprise.rewardType,
rewardTierLevel: undefined,
redeemLocation: surprise.redeemLocation,
categories:
"categories" in surprise ? surprise.categories || [] : [],
coupons: "coupon" in surprise ? surprise.coupon || [] : [],
}
})