Merged in fix/hide-cs-rewards-flag (pull request #1065)
fix: hide new cs rewards model behind feature flag Approved-by: Michael Zetterberg Approved-by: Chuma Mcphoy (We Ahead)
This commit is contained in:
@@ -61,3 +61,5 @@ ENABLE_BOOKING_WIDGET_HOTELRESERVATION_PATH="false"
|
|||||||
SHOW_SITE_WIDE_ALERT="false"
|
SHOW_SITE_WIDE_ALERT="false"
|
||||||
SHOW_SIGNUP_FLOW="true"
|
SHOW_SIGNUP_FLOW="true"
|
||||||
USE_NEW_REWARDS_ENDPOINT="true"
|
USE_NEW_REWARDS_ENDPOINT="true"
|
||||||
|
|
||||||
|
USE_NEW_REWARD_MODEL="true"
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ GOOGLE_DYNAMIC_MAP_ID="test"
|
|||||||
HIDE_FOR_NEXT_RELEASE="true"
|
HIDE_FOR_NEXT_RELEASE="true"
|
||||||
SALESFORCE_PREFERENCE_BASE_URL="test"
|
SALESFORCE_PREFERENCE_BASE_URL="test"
|
||||||
USE_NEW_REWARDS_ENDPOINT="true"
|
USE_NEW_REWARDS_ENDPOINT="true"
|
||||||
|
USE_NEW_REWARD_MODEL="true"
|
||||||
|
|
||||||
TZ=UTC
|
TZ=UTC
|
||||||
ENABLE_BOOKING_FLOW="false"
|
ENABLE_BOOKING_FLOW="false"
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export default function ClientCurrentRewards({
|
|||||||
{reward.label}
|
{reward.label}
|
||||||
</Title>
|
</Title>
|
||||||
</div>
|
</div>
|
||||||
{showRedeem && (
|
{showRedeem && "redeem_description" in reward && (
|
||||||
<div className={styles.btnContainer}>
|
<div className={styles.btnContainer}>
|
||||||
<Redeem reward={reward} />
|
<Redeem reward={reward} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -24,15 +24,15 @@ import { RewardIcon } from "../RewardIcon"
|
|||||||
import styles from "./current.module.css"
|
import styles from "./current.module.css"
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
Redeem,
|
|
||||||
RedeemModalState,
|
RedeemModalState,
|
||||||
|
RedeemProps,
|
||||||
RedeemStep,
|
RedeemStep,
|
||||||
} from "@/types/components/myPages/myPage/accountPage"
|
} from "@/types/components/myPages/myPage/accountPage"
|
||||||
|
|
||||||
const MotionOverlay = motion(ModalOverlay)
|
const MotionOverlay = motion(ModalOverlay)
|
||||||
const MotionModal = motion(Modal)
|
const MotionModal = motion(Modal)
|
||||||
|
|
||||||
export default function Redeem({ reward }: Redeem) {
|
export default function Redeem({ reward }: RedeemProps) {
|
||||||
const [animation, setAnimation] = useState<RedeemModalState>("unmounted")
|
const [animation, setAnimation] = useState<RedeemModalState>("unmounted")
|
||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
const update = trpc.contentstack.rewards.redeem.useMutation()
|
const update = trpc.contentstack.rewards.redeem.useMutation()
|
||||||
@@ -121,9 +121,12 @@ export default function Redeem({ reward }: Redeem) {
|
|||||||
<Body textAlign="center">{reward.description}</Body>
|
<Body textAlign="center">{reward.description}</Body>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{redeemStep === "confirmation" && (
|
{redeemStep === "confirmation" &&
|
||||||
<Body textAlign="center">{reward.redeem_description}</Body>
|
"redeem_description" in reward && (
|
||||||
)}
|
<Body textAlign="center">
|
||||||
|
{reward.redeem_description}
|
||||||
|
</Body>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{redeemStep === "initial" && (
|
{redeemStep === "initial" && (
|
||||||
<footer className={styles.modalFooter}>
|
<footer className={styles.modalFooter}>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export default async function CurrentRewardsBlock({
|
|||||||
<ClientCurrentRewards
|
<ClientCurrentRewards
|
||||||
rewards={rewardsResponse.rewards}
|
rewards={rewardsResponse.rewards}
|
||||||
pageSize={6}
|
pageSize={6}
|
||||||
showRedeem={env.USE_NEW_REWARDS_ENDPOINT}
|
showRedeem={env.USE_NEW_REWARDS_ENDPOINT && env.USE_NEW_REWARD_MODEL}
|
||||||
/>
|
/>
|
||||||
<SectionLink link={link} variant="mobile" />
|
<SectionLink link={link} variant="mobile" />
|
||||||
</SectionContainer>
|
</SectionContainer>
|
||||||
|
|||||||
8
env/server.ts
vendored
8
env/server.ts
vendored
@@ -115,6 +115,13 @@ export const env = createEnv({
|
|||||||
// transform to boolean
|
// transform to boolean
|
||||||
.transform((s) => s === "true")
|
.transform((s) => s === "true")
|
||||||
.default("false"),
|
.default("false"),
|
||||||
|
USE_NEW_REWARD_MODEL: z
|
||||||
|
.string()
|
||||||
|
// only allow "true" or "false"
|
||||||
|
.refine((s) => s === "true" || s === "false")
|
||||||
|
// transform to boolean
|
||||||
|
.transform((s) => s === "true")
|
||||||
|
.default("false"),
|
||||||
},
|
},
|
||||||
emptyStringAsUndefined: true,
|
emptyStringAsUndefined: true,
|
||||||
runtimeEnv: {
|
runtimeEnv: {
|
||||||
@@ -172,6 +179,7 @@ export const env = createEnv({
|
|||||||
GOOGLE_DYNAMIC_MAP_ID: process.env.GOOGLE_DYNAMIC_MAP_ID,
|
GOOGLE_DYNAMIC_MAP_ID: process.env.GOOGLE_DYNAMIC_MAP_ID,
|
||||||
HIDE_FOR_NEXT_RELEASE: process.env.HIDE_FOR_NEXT_RELEASE,
|
HIDE_FOR_NEXT_RELEASE: process.env.HIDE_FOR_NEXT_RELEASE,
|
||||||
USE_NEW_REWARDS_ENDPOINT: process.env.USE_NEW_REWARDS_ENDPOINT,
|
USE_NEW_REWARDS_ENDPOINT: process.env.USE_NEW_REWARDS_ENDPOINT,
|
||||||
|
USE_NEW_REWARD_MODEL: process.env.USE_NEW_REWARD_MODEL,
|
||||||
ENABLE_BOOKING_FLOW: process.env.ENABLE_BOOKING_FLOW,
|
ENABLE_BOOKING_FLOW: process.env.ENABLE_BOOKING_FLOW,
|
||||||
ENABLE_BOOKING_WIDGET: process.env.ENABLE_BOOKING_WIDGET,
|
ENABLE_BOOKING_WIDGET: process.env.ENABLE_BOOKING_WIDGET,
|
||||||
ENABLE_BOOKING_WIDGET_HOTELRESERVATION_PATH:
|
ENABLE_BOOKING_WIDGET_HOTELRESERVATION_PATH:
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ query GetRewards($locale: String!, $rewardIds: [String!]) {
|
|||||||
label
|
label
|
||||||
grouped_label
|
grouped_label
|
||||||
description
|
description
|
||||||
redeem_description
|
|
||||||
grouped_description
|
grouped_description
|
||||||
value
|
value
|
||||||
reward_id
|
reward_id
|
||||||
|
|||||||
16
lib/graphql/Query/RewardsWithRedeem.graphql
Normal file
16
lib/graphql/Query/RewardsWithRedeem.graphql
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
query GetRewards($locale: String!, $rewardIds: [String!]) {
|
||||||
|
all_reward(locale: $locale, where: { reward_id_in: $rewardIds }) {
|
||||||
|
items {
|
||||||
|
taxonomies {
|
||||||
|
term_uid
|
||||||
|
}
|
||||||
|
label
|
||||||
|
grouped_label
|
||||||
|
description
|
||||||
|
redeem_description
|
||||||
|
grouped_description
|
||||||
|
value
|
||||||
|
reward_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -92,6 +92,30 @@ export const validateApiTierRewardsSchema = z.record(
|
|||||||
)
|
)
|
||||||
|
|
||||||
export const validateCmsRewardsSchema = z
|
export 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(),
|
||||||
|
})
|
||||||
|
),
|
||||||
|
label: z.string().optional(),
|
||||||
|
reward_id: z.string(),
|
||||||
|
grouped_label: z.string().optional(),
|
||||||
|
description: z.string().optional(),
|
||||||
|
grouped_description: z.string().optional(),
|
||||||
|
value: z.string().optional(),
|
||||||
|
})
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.transform((data) => data.data.all_reward.items)
|
||||||
|
|
||||||
|
export const validateCmsRewardsWithRedeemSchema = z
|
||||||
.object({
|
.object({
|
||||||
data: z.object({
|
data: z.object({
|
||||||
all_reward: z.object({
|
all_reward: z.object({
|
||||||
@@ -125,12 +149,24 @@ export type SurpriseReward = z.output<typeof SurpriseReward>
|
|||||||
|
|
||||||
export type CmsRewardsResponse = z.input<typeof validateCmsRewardsSchema>
|
export type CmsRewardsResponse = z.input<typeof validateCmsRewardsSchema>
|
||||||
|
|
||||||
|
export type CmsRewardsWithRedeemResponse = z.input<
|
||||||
|
typeof validateCmsRewardsWithRedeemSchema
|
||||||
|
>
|
||||||
|
|
||||||
export type CMSReward = z.output<typeof validateCmsRewardsSchema>[0]
|
export type CMSReward = z.output<typeof validateCmsRewardsSchema>[0]
|
||||||
|
|
||||||
|
export type CMSRewardWithRedeem = z.output<
|
||||||
|
typeof validateCmsRewardsWithRedeemSchema
|
||||||
|
>[0]
|
||||||
|
|
||||||
export type Reward = CMSReward & {
|
export type Reward = CMSReward & {
|
||||||
id: string | undefined
|
id: string | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type RewardWithRedeem = CMSRewardWithRedeem & {
|
||||||
|
id: string | undefined
|
||||||
|
}
|
||||||
|
|
||||||
// New endpoint related types and schemas.
|
// New endpoint related types and schemas.
|
||||||
|
|
||||||
const BenefitReward = z.object({
|
const BenefitReward = z.object({
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ import { metrics } from "@opentelemetry/api"
|
|||||||
import { unstable_cache } from "next/cache"
|
import { unstable_cache } from "next/cache"
|
||||||
|
|
||||||
import { Lang } from "@/constants/languages"
|
import { Lang } from "@/constants/languages"
|
||||||
|
import { env } from "@/env/server"
|
||||||
import * as api from "@/lib/api"
|
import * as api from "@/lib/api"
|
||||||
import { GetRewards } from "@/lib/graphql/Query/Rewards.graphql"
|
import { GetRewards } from "@/lib/graphql/Query/Rewards.graphql"
|
||||||
|
import { GetRewards as GetRewardsWithReedem } from "@/lib/graphql/Query/RewardsWithRedeem.graphql"
|
||||||
import { request } from "@/lib/graphql/request"
|
import { request } from "@/lib/graphql/request"
|
||||||
import { notFound } from "@/server/errors/trpc"
|
import { notFound } from "@/server/errors/trpc"
|
||||||
|
|
||||||
@@ -11,9 +13,11 @@ import { generateLoyaltyConfigTag } from "@/utils/generateTag"
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
CmsRewardsResponse,
|
CmsRewardsResponse,
|
||||||
|
CmsRewardsWithRedeemResponse,
|
||||||
validateApiAllTiersSchema,
|
validateApiAllTiersSchema,
|
||||||
validateApiTierRewardsSchema,
|
validateApiTierRewardsSchema,
|
||||||
validateCmsRewardsSchema,
|
validateCmsRewardsSchema,
|
||||||
|
validateCmsRewardsWithRedeemSchema,
|
||||||
} from "./output"
|
} from "./output"
|
||||||
|
|
||||||
const meter = metrics.getMeter("trpc.reward")
|
const meter = metrics.getMeter("trpc.reward")
|
||||||
@@ -196,14 +200,24 @@ export async function getCmsRewards(locale: Lang, rewardIds: string[]) {
|
|||||||
const tags = rewardIds.map((id) =>
|
const tags = rewardIds.map((id) =>
|
||||||
generateLoyaltyConfigTag(locale, "reward", id)
|
generateLoyaltyConfigTag(locale, "reward", id)
|
||||||
)
|
)
|
||||||
const cmsRewardsResponse = await request<CmsRewardsResponse>(
|
|
||||||
GetRewards,
|
const cmsRewardsResponse = env.USE_NEW_REWARD_MODEL
|
||||||
{
|
? await request<CmsRewardsWithRedeemResponse>(
|
||||||
locale: locale,
|
GetRewardsWithReedem,
|
||||||
rewardIds,
|
{
|
||||||
},
|
locale: locale,
|
||||||
{ next: { tags }, cache: "force-cache" }
|
rewardIds,
|
||||||
)
|
},
|
||||||
|
{ next: { tags }, cache: "force-cache" }
|
||||||
|
)
|
||||||
|
: await request<CmsRewardsResponse>(
|
||||||
|
GetRewards,
|
||||||
|
{
|
||||||
|
locale: locale,
|
||||||
|
rewardIds,
|
||||||
|
},
|
||||||
|
{ next: { tags }, cache: "force-cache" }
|
||||||
|
)
|
||||||
|
|
||||||
if (!cmsRewardsResponse.data) {
|
if (!cmsRewardsResponse.data) {
|
||||||
getAllRewardFailCounter.add(1, {
|
getAllRewardFailCounter.add(1, {
|
||||||
@@ -225,8 +239,9 @@ export async function getCmsRewards(locale: Lang, rewardIds: string[]) {
|
|||||||
throw notFoundError
|
throw notFoundError
|
||||||
}
|
}
|
||||||
|
|
||||||
const validatedCmsRewards =
|
const validatedCmsRewards = env.USE_NEW_REWARD_MODEL
|
||||||
validateCmsRewardsSchema.safeParse(cmsRewardsResponse)
|
? validateCmsRewardsWithRedeemSchema.safeParse(cmsRewardsResponse)
|
||||||
|
: validateCmsRewardsSchema.safeParse(cmsRewardsResponse)
|
||||||
|
|
||||||
if (!validatedCmsRewards.success) {
|
if (!validatedCmsRewards.success) {
|
||||||
getAllRewardFailCounter.add(1, {
|
getAllRewardFailCounter.add(1, {
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
import { blocksSchema } from "@/server/routers/contentstack/accountPage/output"
|
import { blocksSchema } from "@/server/routers/contentstack/accountPage/output"
|
||||||
import { Reward } from "@/server/routers/contentstack/reward/output"
|
import {
|
||||||
|
Reward,
|
||||||
|
RewardWithRedeem,
|
||||||
|
} from "@/server/routers/contentstack/reward/output"
|
||||||
|
|
||||||
import { DynamicContent } from "@/types/trpc/routers/contentstack/blocks"
|
import { DynamicContent } from "@/types/trpc/routers/contentstack/blocks"
|
||||||
|
|
||||||
@@ -21,13 +24,13 @@ export type ContentProps = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface CurrentRewardsClientProps {
|
export interface CurrentRewardsClientProps {
|
||||||
rewards: Reward[]
|
rewards: (Reward | RewardWithRedeem)[]
|
||||||
pageSize: number
|
pageSize: number
|
||||||
showRedeem: boolean
|
showRedeem: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Redeem {
|
export interface RedeemProps {
|
||||||
reward: Reward
|
reward: RewardWithRedeem
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RedeemModalState = "unmounted" | "hidden" | "visible"
|
export type RedeemModalState = "unmounted" | "hidden" | "visible"
|
||||||
|
|||||||
Reference in New Issue
Block a user