feat(LOY-135): change redeem description to be RTE
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import JsonToHtml from "@/components/JsonToHtml"
|
||||||
import Button from "@/components/TempDesignSystem/Button"
|
import Button from "@/components/TempDesignSystem/Button"
|
||||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||||
import Title from "@/components/TempDesignSystem/Text/Title"
|
import Title from "@/components/TempDesignSystem/Text/Title"
|
||||||
@@ -53,7 +54,12 @@ export default function Tier({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{redeemStep === "confirmation" && (
|
{redeemStep === "confirmation" && (
|
||||||
<Body textAlign="center">{reward.redeem_description}</Body>
|
<JsonToHtml
|
||||||
|
embeds={
|
||||||
|
reward.redeem_description.embedded_itemsConnection.edges
|
||||||
|
}
|
||||||
|
nodes={reward.redeem_description.json.children}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{redeemStep === "redeemed" &&
|
{redeemStep === "redeemed" &&
|
||||||
@@ -63,7 +69,10 @@ export default function Tier({
|
|||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<Body textAlign="center">{reward.redeem_description}</Body>
|
<JsonToHtml
|
||||||
|
embeds={reward.redeem_description.embedded_itemsConnection.edges}
|
||||||
|
nodes={reward.redeem_description.json.children}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -66,9 +66,11 @@ function extractPossibleAttributes(attrs: Attributes | undefined) {
|
|||||||
props.className = attrs["class-name"]
|
props.className = attrs["class-name"]
|
||||||
} else if (attrs.classname) {
|
} else if (attrs.classname) {
|
||||||
props.className = attrs.classname
|
props.className = attrs.classname
|
||||||
} else if (attrs?.style?.["text-align"]) {
|
}
|
||||||
|
|
||||||
|
if (attrs.style?.["text-align"]) {
|
||||||
props.style = {
|
props.style = {
|
||||||
textAlign: attrs?.style?.["text-align"],
|
textAlign: attrs.style["text-align"],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,25 @@
|
|||||||
|
#import "../Fragments/System.graphql"
|
||||||
|
|
||||||
|
#import "../Fragments/PageLink/AccountPageLink.graphql"
|
||||||
|
#import "../Fragments/PageLink/CollectionPageLink.graphql"
|
||||||
|
#import "../Fragments/PageLink/ContentPageLink.graphql"
|
||||||
|
#import "../Fragments/PageLink/DestinationCityPageLink.graphql"
|
||||||
|
#import "../Fragments/PageLink/DestinationCountryPageLink.graphql"
|
||||||
|
#import "../Fragments/PageLink/DestinationOverviewPageLink.graphql"
|
||||||
|
#import "../Fragments/PageLink/HotelPageLink.graphql"
|
||||||
|
#import "../Fragments/PageLink/LoyaltyPageLink.graphql"
|
||||||
|
#import "../Fragments/PageLink/StartPageLink.graphql"
|
||||||
|
|
||||||
|
#import "../Fragments/AccountPage/Ref.graphql"
|
||||||
|
#import "../Fragments/CollectionPage/Ref.graphql"
|
||||||
|
#import "../Fragments/ContentPage/Ref.graphql"
|
||||||
|
#import "../Fragments/DestinationCityPage/Ref.graphql"
|
||||||
|
#import "../Fragments/DestinationCountryPage/Ref.graphql"
|
||||||
|
#import "../Fragments/DestinationOverviewPage/Ref.graphql"
|
||||||
|
#import "../Fragments/HotelPage/Ref.graphql"
|
||||||
|
#import "../Fragments/LoyaltyPage/Ref.graphql"
|
||||||
|
#import "../Fragments/StartPage/Ref.graphql"
|
||||||
|
|
||||||
query GetRewards($locale: String!, $rewardIds: [String!]) {
|
query GetRewards($locale: String!, $rewardIds: [String!]) {
|
||||||
all_reward(locale: $locale, where: { reward_id_in: $rewardIds }) {
|
all_reward(locale: $locale, where: { reward_id_in: $rewardIds }) {
|
||||||
items {
|
items {
|
||||||
@@ -7,10 +29,56 @@ query GetRewards($locale: String!, $rewardIds: [String!]) {
|
|||||||
label
|
label
|
||||||
grouped_label
|
grouped_label
|
||||||
description
|
description
|
||||||
redeem_description
|
redeem_description {
|
||||||
|
json
|
||||||
|
embedded_itemsConnection {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
__typename
|
||||||
|
...AccountPageLink
|
||||||
|
...CollectionPageLink
|
||||||
|
...ContentPageLink
|
||||||
|
...DestinationCityPageLink
|
||||||
|
...DestinationCountryPageLink
|
||||||
|
...DestinationOverviewPageLink
|
||||||
|
...HotelPageLink
|
||||||
|
...LoyaltyPageLink
|
||||||
|
...StartPageLink
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
grouped_description
|
grouped_description
|
||||||
value
|
value
|
||||||
reward_id
|
reward_id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query GetRewardsRef($locale: String!, $rewardIds: [String!]) {
|
||||||
|
all_reward(locale: $locale, where: { reward_id_in: $rewardIds }) {
|
||||||
|
items {
|
||||||
|
redeem_description {
|
||||||
|
embedded_itemsConnection {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
__typename
|
||||||
|
...AccountPageRef
|
||||||
|
...CollectionPageRef
|
||||||
|
...ContentPageRef
|
||||||
|
...DestinationCityPageRef
|
||||||
|
...DestinationCountryPageRef
|
||||||
|
...DestinationOverviewPageRef
|
||||||
|
...HotelPageRef
|
||||||
|
...LoyaltyPageRef
|
||||||
|
...StartPageRef
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
system {
|
||||||
|
...System
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,13 @@ import { z } from "zod"
|
|||||||
|
|
||||||
import { MembershipLevelEnum } from "@/constants/membershipLevels"
|
import { MembershipLevelEnum } from "@/constants/membershipLevels"
|
||||||
|
|
||||||
|
import {
|
||||||
|
linkRefsUnionSchema,
|
||||||
|
linkUnionSchema,
|
||||||
|
transformPageLink,
|
||||||
|
} from "../schemas/pageLinks"
|
||||||
|
import { systemSchema } from "../schemas/system"
|
||||||
|
|
||||||
const Coupon = z.object({
|
const Coupon = z.object({
|
||||||
code: z.string().optional(),
|
code: z.string().optional(),
|
||||||
status: z.string().optional(),
|
status: z.string().optional(),
|
||||||
@@ -133,10 +140,22 @@ export const validateCmsRewardsWithRedeemSchema = z
|
|||||||
reward_id: z.string(),
|
reward_id: z.string(),
|
||||||
grouped_label: z.string().optional(),
|
grouped_label: z.string().optional(),
|
||||||
description: z.string().optional(),
|
description: z.string().optional(),
|
||||||
redeem_description: z
|
redeem_description: z.object({
|
||||||
.string()
|
json: z.any(), // JSON
|
||||||
.nullable()
|
embedded_itemsConnection: z.object({
|
||||||
.transform((val) => val || ""),
|
edges: z.array(
|
||||||
|
z.object({
|
||||||
|
node: linkUnionSchema.transform((data) => {
|
||||||
|
const link = transformPageLink(data)
|
||||||
|
if (link) {
|
||||||
|
return link
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
grouped_description: z.string().optional(),
|
grouped_description: z.string().optional(),
|
||||||
value: z.string().optional(),
|
value: z.string().optional(),
|
||||||
})
|
})
|
||||||
@@ -156,6 +175,30 @@ export type CmsRewardsWithRedeemResponse = z.input<
|
|||||||
typeof validateCmsRewardsWithRedeemSchema
|
typeof validateCmsRewardsWithRedeemSchema
|
||||||
>
|
>
|
||||||
|
|
||||||
|
export const rewardWithRedeemRefsSchema = 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,
|
||||||
|
})
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
system: systemSchema,
|
||||||
|
})
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
export interface GetRewardWithRedeemRefsSchema
|
||||||
|
extends z.input<typeof rewardWithRedeemRefsSchema> {}
|
||||||
|
|
||||||
export type CMSReward = z.output<typeof validateCmsRewardsSchema>[0]
|
export type CMSReward = z.output<typeof validateCmsRewardsSchema>[0]
|
||||||
|
|
||||||
export type CMSRewardWithRedeem = z.output<
|
export type CMSRewardWithRedeem = z.output<
|
||||||
|
|||||||
@@ -4,17 +4,22 @@ import { unstable_cache } from "next/cache"
|
|||||||
import { env } from "@/env/server"
|
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 {
|
||||||
|
GetRewards as GetRewardsWithReedem,
|
||||||
|
GetRewardsRef as GetRewardsWithRedeemRef,
|
||||||
|
} 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"
|
||||||
|
|
||||||
import { generateLoyaltyConfigTag } from "@/utils/generateTag"
|
import { generateLoyaltyConfigTag, generateTag } from "@/utils/generateTag"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
type ApiReward,
|
type ApiReward,
|
||||||
type CategorizedApiReward,
|
type CategorizedApiReward,
|
||||||
type CmsRewardsResponse,
|
type CmsRewardsResponse,
|
||||||
type CmsRewardsWithRedeemResponse,
|
type CmsRewardsWithRedeemResponse,
|
||||||
|
type GetRewardWithRedeemRefsSchema,
|
||||||
|
rewardWithRedeemRefsSchema,
|
||||||
validateApiAllTiersSchema,
|
validateApiAllTiersSchema,
|
||||||
validateApiTierRewardsSchema,
|
validateApiTierRewardsSchema,
|
||||||
validateCmsRewardsSchema,
|
validateCmsRewardsSchema,
|
||||||
@@ -70,6 +75,16 @@ export const getRedeemSuccessCounter = meter.createCounter(
|
|||||||
"trpc.contentstack.reward.redeem-success"
|
"trpc.contentstack.reward.redeem-success"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export const getAllCMSRewardRefsCounter = meter.createCounter(
|
||||||
|
"trpc.contentstack.reward.all"
|
||||||
|
)
|
||||||
|
export const getAllCMSRewardRefsFailCounter = meter.createCounter(
|
||||||
|
"trpc.contentstack.reward.all-fail"
|
||||||
|
)
|
||||||
|
export const getAllCMSRewardRefsSuccessCounter = meter.createCounter(
|
||||||
|
"trpc.contentstack.reward.all-success"
|
||||||
|
)
|
||||||
|
|
||||||
const ONE_HOUR = 60 * 60
|
const ONE_HOUR = 60 * 60
|
||||||
|
|
||||||
export function getUniqueRewardIds(rewardIds: string[]) {
|
export function getUniqueRewardIds(rewardIds: string[]) {
|
||||||
@@ -199,32 +214,100 @@ export const getCachedAllTierRewards = unstable_cache(
|
|||||||
{ revalidate: ONE_HOUR }
|
{ revalidate: ONE_HOUR }
|
||||||
)
|
)
|
||||||
|
|
||||||
export async function getCmsRewards(locale: Lang, rewardIds: string[]) {
|
export async function getCmsRewards(lang: Lang, rewardIds: string[]) {
|
||||||
const tags = rewardIds.map((id) =>
|
const tags = rewardIds.map((id) =>
|
||||||
generateLoyaltyConfigTag(locale, "reward", id)
|
generateLoyaltyConfigTag(lang, "reward", id)
|
||||||
)
|
)
|
||||||
|
|
||||||
const cmsRewardsResponse = env.USE_NEW_REWARD_MODEL
|
let cmsRewardsResponse
|
||||||
? await request<CmsRewardsWithRedeemResponse>(
|
if (env.USE_NEW_REWARD_MODEL) {
|
||||||
GetRewardsWithReedem,
|
getAllCMSRewardRefsCounter.add(1, { lang, rewardIds })
|
||||||
{
|
console.info(
|
||||||
locale: locale,
|
"contentstack.reward.refs start",
|
||||||
rewardIds,
|
JSON.stringify({
|
||||||
|
query: { lang, rewardIds },
|
||||||
|
})
|
||||||
|
)
|
||||||
|
const refsResponse = await request<GetRewardWithRedeemRefsSchema>(
|
||||||
|
GetRewardsWithRedeemRef,
|
||||||
|
{
|
||||||
|
locale: lang,
|
||||||
|
rewardIds,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cache: "force-cache",
|
||||||
|
next: {
|
||||||
|
tags: rewardIds.map((rewardId) => generateTag(lang, rewardId)),
|
||||||
},
|
},
|
||||||
{ next: { tags }, cache: "force-cache" }
|
}
|
||||||
|
)
|
||||||
|
if (!refsResponse.data) {
|
||||||
|
const notFoundError = notFound(refsResponse)
|
||||||
|
getAllCMSRewardRefsFailCounter.add(1, {
|
||||||
|
lang,
|
||||||
|
rewardIds,
|
||||||
|
error_type: "not_found",
|
||||||
|
error: JSON.stringify({ code: notFoundError.code }),
|
||||||
|
})
|
||||||
|
console.error(
|
||||||
|
"contentstack.reward.refs not found error",
|
||||||
|
JSON.stringify({
|
||||||
|
query: { lang, rewardIds },
|
||||||
|
error: { code: notFoundError.code },
|
||||||
|
})
|
||||||
)
|
)
|
||||||
: await request<CmsRewardsResponse>(
|
throw notFoundError
|
||||||
GetRewards,
|
}
|
||||||
{
|
|
||||||
locale: locale,
|
const validatedRefsData = rewardWithRedeemRefsSchema.safeParse(refsResponse)
|
||||||
rewardIds,
|
|
||||||
},
|
if (!validatedRefsData.success) {
|
||||||
{ next: { tags }, cache: "force-cache" }
|
getAllCMSRewardRefsFailCounter.add(1, {
|
||||||
|
lang,
|
||||||
|
rewardIds,
|
||||||
|
error_type: "validation_error",
|
||||||
|
error: JSON.stringify(validatedRefsData.error),
|
||||||
|
})
|
||||||
|
console.error(
|
||||||
|
"contentstack.reward.refs validation error",
|
||||||
|
JSON.stringify({
|
||||||
|
query: { lang, rewardIds },
|
||||||
|
error: validatedRefsData.error,
|
||||||
|
})
|
||||||
)
|
)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
getAllCMSRewardRefsSuccessCounter.add(1, { lang, rewardIds })
|
||||||
|
console.info(
|
||||||
|
"contentstack.startPage.refs success",
|
||||||
|
JSON.stringify({
|
||||||
|
query: { lang, rewardIds },
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
cmsRewardsResponse = await request<CmsRewardsWithRedeemResponse>(
|
||||||
|
GetRewardsWithReedem,
|
||||||
|
{
|
||||||
|
locale: lang,
|
||||||
|
rewardIds,
|
||||||
|
},
|
||||||
|
{ next: { tags }, cache: "force-cache" }
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
cmsRewardsResponse = await request<CmsRewardsResponse>(
|
||||||
|
GetRewards,
|
||||||
|
{
|
||||||
|
locale: lang,
|
||||||
|
rewardIds,
|
||||||
|
},
|
||||||
|
{ next: { tags }, cache: "force-cache" }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (!cmsRewardsResponse.data) {
|
if (!cmsRewardsResponse.data) {
|
||||||
getAllRewardFailCounter.add(1, {
|
getAllRewardFailCounter.add(1, {
|
||||||
lang: locale,
|
lang,
|
||||||
error_type: "validation_error",
|
error_type: "validation_error",
|
||||||
error: JSON.stringify(cmsRewardsResponse.data),
|
error: JSON.stringify(cmsRewardsResponse.data),
|
||||||
})
|
})
|
||||||
@@ -233,7 +316,7 @@ export async function getCmsRewards(locale: Lang, rewardIds: string[]) {
|
|||||||
"contentstack.rewards not found error",
|
"contentstack.rewards not found error",
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
query: {
|
query: {
|
||||||
locale,
|
locale: lang,
|
||||||
rewardIds,
|
rewardIds,
|
||||||
},
|
},
|
||||||
error: { code: notFoundError.code },
|
error: { code: notFoundError.code },
|
||||||
@@ -248,7 +331,7 @@ export async function getCmsRewards(locale: Lang, rewardIds: string[]) {
|
|||||||
|
|
||||||
if (!validatedCmsRewards.success) {
|
if (!validatedCmsRewards.success) {
|
||||||
getAllRewardFailCounter.add(1, {
|
getAllRewardFailCounter.add(1, {
|
||||||
locale,
|
locale: lang,
|
||||||
rewardIds,
|
rewardIds,
|
||||||
error_type: "validation_error",
|
error_type: "validation_error",
|
||||||
error: JSON.stringify(validatedCmsRewards.error),
|
error: JSON.stringify(validatedCmsRewards.error),
|
||||||
@@ -257,7 +340,7 @@ export async function getCmsRewards(locale: Lang, rewardIds: string[]) {
|
|||||||
console.error(
|
console.error(
|
||||||
"contentstack.rewards validation error",
|
"contentstack.rewards validation error",
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
query: { locale, rewardIds },
|
query: { locale: lang, rewardIds },
|
||||||
error: validatedCmsRewards.error,
|
error: validatedCmsRewards.error,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user