Files
web/packages/trpc/lib/routers/contentstack/reward/output.ts
Anton Gunnarsson 002d093af4 Merged in feat/sw-2863-move-contentstack-router-to-trpc-package (pull request #2389)
feat(SW-2863): Move contentstack router to trpc package

* Add exports to packages and lint rule to prevent relative imports

* Add env to trpc package

* Add eslint to trpc package

* Apply lint rules

* Use direct imports from trpc package

* Add lint-staged config to trpc

* Move lang enum to common

* Restructure trpc package folder structure

* WIP first step

* update internal imports in trpc

* Fix most errors in scandic-web

Just 100 left...

* Move Props type out of trpc

* Fix CategorizedFilters types

* Move more schemas in hotel router

* Fix deps

* fix getNonContentstackUrls

* Fix import error

* Fix entry error handling

* Fix generateMetadata metrics

* Fix alertType enum

* Fix duplicated types

* lint:fix

* Merge branch 'master' into feat/sw-2863-move-contentstack-router-to-trpc-package

* Fix broken imports

* Merge branch 'master' into feat/sw-2863-move-contentstack-router-to-trpc-package


Approved-by: Linus Flood
2025-06-26 07:53:01 +00:00

176 lines
4.5 KiB
TypeScript

import { z } from "zod"
import { MembershipLevelEnum } from "@scandic-hotels/common/constants/membershipLevels"
import {
linkRefsUnionSchema,
linkUnionSchema,
transformPageLink,
} from "../schemas/pageLinks"
import { systemSchema } from "../schemas/system"
export {
BenefitReward,
CouponData,
CouponReward,
REDEEM_LOCATIONS,
REWARD_TYPES,
rewardRefsSchema,
validateApiAllTiersSchema,
validateCategorizedRewardsSchema,
validateCmsRewardsSchema,
}
const validateCmsRewardsSchema = z
.object({
data: z.object({
all_reward: z.object({
items: z.array(
z.object({
taxonomies: z.array(
z.object({
term_uid: z.string().optional().default(""),
})
),
label: z.string().optional(),
reward_id: z.string(),
grouped_label: z.string().optional(),
description: z.string().optional(),
redeem_description: z
.object({
json: z.any(), // JSON
embedded_itemsConnection: z.object({
edges: z.array(
z.object({
node: linkUnionSchema.transform((data) => {
const link = transformPageLink(data)
if (link) {
return link
}
return data
}),
})
),
}),
})
// This is primarily added in order to handle a transition
// switching from string to RTE
.nullable(),
grouped_description: z.string().optional(),
value: z.string().optional(),
})
),
}),
}),
})
.transform((data) => data.data.all_reward.items)
const rewardRefsSchema = z.object({
data: z.object({
all_reward: z.object({
items: z.array(
z.object({
redeem_description: z
.object({
embedded_itemsConnection: z.object({
edges: z.array(
z.object({
node: linkRefsUnionSchema,
})
),
}),
})
// This is primarily added in order to handle a transition
// switching from string to RTE
.nullable(),
system: systemSchema,
})
),
}),
}),
})
const REDEEM_LOCATIONS = ["Non-redeemable", "On-site", "Online"] as const
const REWARD_CATEGORIES = [
"Restaurants",
"Bar",
"Voucher",
"Services and rooms",
"Spa and gym",
] as const
const BaseReward = z.object({
title: z.string().optional(),
id: z.string(),
categories: z
.array(z.enum(REWARD_CATEGORIES).or(z.literal("")))
.optional()
// we sometimes receive empty categories, this filters them out
.transform((categories = []) =>
categories.filter(
(c): c is (typeof REWARD_CATEGORIES)[number] => c !== ""
)
),
rewardId: z.string(),
redeemLocation: z.enum(REDEEM_LOCATIONS),
status: z.enum(["active", "expired"]),
})
const REWARD_TYPES = {
Surprise: "Surprise",
Campaign: "Campaign",
MemberVoucher: "Member-voucher",
Tier: "Tier",
} as const
const BenefitReward = BaseReward.merge(
z.object({
rewardType: z.enum([REWARD_TYPES.Tier]),
rewardTierLevel: z.string().optional(),
})
)
const CouponData = z.object({
couponCode: z.string(),
unwrapped: z.boolean().default(false),
state: z.enum(["claimed", "redeemed", "viewed"]),
expiresAt: z.string().datetime({ offset: true }).optional(),
})
const CouponReward = BaseReward.merge(
z.object({
rewardType: z.enum([
REWARD_TYPES.Surprise,
REWARD_TYPES.Campaign,
REWARD_TYPES.MemberVoucher,
]),
operaRewardId: z.string().default(""),
coupon: z
.array(CouponData)
.optional()
.transform((val) => val || []),
})
)
const validateCategorizedRewardsSchema = z.object({
benefits: z.array(BenefitReward),
coupons: z.array(CouponReward),
})
const TierKeyMapping = {
tier1: MembershipLevelEnum.L1,
tier2: MembershipLevelEnum.L2,
tier3: MembershipLevelEnum.L3,
tier4: MembershipLevelEnum.L4,
tier5: MembershipLevelEnum.L5,
tier6: MembershipLevelEnum.L6,
tier7: MembershipLevelEnum.L7,
} as const
const TierKeys = Object.keys(TierKeyMapping) as [keyof typeof TierKeyMapping]
const validateApiAllTiersSchema = z.record(
z.enum(TierKeys).transform((data) => TierKeyMapping[data]),
z.array(BenefitReward)
)