Merged in fix/LOY-400-make-contentstack-data-optional (pull request #3266)

fix(LOY-400): made contentstack data optional so the whole page does not crash if it's empty.

* fix(LOY-400): made contentstack data optional so the whole page does not crash if it's empty.

* Merged in fix/LOY-400-make-contentstack-data-optional-2 (pull request #3269)

Fix/LOY-400 make contentstack data optional 2

* Test

* .

* Correct ref tag

* refactor

* Correct key

* fix(LOY-400): cleaned up


Approved-by: Linus Flood
Approved-by: Matilda Landström
This commit is contained in:
Emma Zettervall
2025-12-02 08:08:12 +00:00
parent 95473927f2
commit 34526bbaf1
5 changed files with 95 additions and 68 deletions

View File

@@ -67,7 +67,11 @@ export function UsePointsModal({
const bookLink = `${pathname}?${searchParams}`
const [items] = contentData.all_usepointsmodal.items
const items = contentData?.all_usepointsmodal?.items?.[0]
if (!items) {
return null
}
const linkListItems = items.link_group.map((link) => ({
text: link.text,

View File

@@ -24,6 +24,7 @@ import { PromoCampaignPageLink } from "../Fragments/PageLink/PromoCampaignPageLi
import { StartPageLink } from "../Fragments/PageLink/StartPageLink.graphql"
import { PromoCampaignPageRef } from "../Fragments/PromoCampaignPage/Ref.graphql"
import { StartPageRef } from "../Fragments/StartPage/Ref.graphql"
import { System } from "../Fragments/System.graphql"
export const GetUsePointsModal = gql`
query GetUsePointsModal($locale: String!) {
@@ -99,6 +100,9 @@ export const GetUsePointsModalRefs = gql`
}
}
}
system {
...System
}
}
}
}
@@ -114,4 +118,5 @@ export const GetUsePointsModalRefs = gql`
${LoyaltyPageRef}
${StartPageRef}
${PromoCampaignPageRef}
${System}
`

View File

@@ -3,82 +3,70 @@ import { z } from "zod"
import { transformedImageVaultAssetSchema } from "@scandic-hotels/common/utils/imageVault"
import { IconName } from "@scandic-hotels/design-system/Icons/iconName"
import { linkConnectionRefs } from "../schemas/linkConnection"
import { linkUnionSchema, transformPageLink } from "../schemas/pageLinks"
import {
linkConnectionRefs,
linkConnectionSchema,
} from "../schemas/linkConnection"
import { systemSchema } from "../schemas/system"
export type UsePointsModalData = z.output<typeof usePointsModalSchema>
export type UsePointsModalRefsData = z.output<typeof usePointsModalRefsSchema>
type LinkGroupItem = z.infer<typeof linkGroupItemSchema>
export const linkConnectionSchema = z
.object({
edges: z.array(
z.object({
node: linkUnionSchema,
const linkGroupItemSchema = z.intersection(
z.object({
link_text: z.string().default(""),
is_contentstack_link: z.boolean(),
illustration: z.nativeEnum(IconName).nullish(),
illustration_size: z
.enum(["small", "medium", "large"])
.nullish()
.default("large"),
external_link: z
.object({
href: z.string().default(""),
})
),
})
.transform((data) => {
if (data.edges.length) {
const linkNode = data.edges[0].node
if (linkNode) {
const link = transformPageLink(linkNode)
if (link && link.url) {
return link.url
}
}
}
return null
})
.optional(),
}),
linkConnectionSchema
)
const usePointsModalItemsSchema = z.object({
image: transformedImageVaultAssetSchema,
link_group: z
.array(
z.object({
link_text: z.string().default(""),
is_contentstack_link: z.boolean(),
illustration: z.nativeEnum(IconName).nullish(),
illustration_size: z
.enum(["small", "medium", "large"])
.nullish()
.default("large"),
external_link: z
.object({
href: z.string().default(""),
})
.optional(),
linkConnection: linkConnectionSchema,
})
)
.transform((links) =>
links.map((link) => ({
text: link.link_text || "",
isExternal: !link.is_contentstack_link,
href: link.is_contentstack_link
? link.linkConnection || ""
: link.external_link?.href || "",
illustration: link.illustration
? {
illustration: link.illustration,
size: link.illustration_size || "large",
}
: undefined,
}))
),
link_group: z.array(linkGroupItemSchema).transform((links: LinkGroupItem[]) =>
links.map((link) => ({
text: link.link_text || "",
isExternal: !link.is_contentstack_link,
href: link.is_contentstack_link
? link.link?.url || ""
: link.external_link?.href || "",
illustration: link.illustration
? {
illustration: link.illustration,
size: link.illustration_size || "large",
}
: undefined,
}))
),
})
export const usePointsModalSchema = z.object({
all_usepointsmodal: z.object({
items: z.array(usePointsModalItemsSchema),
}),
all_usepointsmodal: z
.object({
items: z.array(usePointsModalItemsSchema).optional(),
})
.optional(),
})
export const usePointsModalRefsSchema = z.object({
all_usepointsmodal: z.object({
items: z.array(
z.object({
link_group: z.array(linkConnectionRefs),
})
),
}),
all_usepointsmodal: z
.object({
items: z.array(
z.object({
link_group: z.array(linkConnectionRefs),
system: systemSchema,
})
),
})
.optional(),
})

View File

@@ -8,17 +8,22 @@ import {
} from "../../../graphql/Query/UsePointsModal.graphql"
import { request } from "../../../graphql/request"
import { contentstackBaseProcedure } from "../../../procedures"
import {
generateRefsResponseTag,
generateTag,
generateTagsFromSystem,
} from "../../../utils/generateTag"
import {
type UsePointsModalData,
type UsePointsModalRefsData,
usePointsModalRefsSchema,
usePointsModalSchema,
} from "./output"
import { getConnections } from "./utils"
export const usePointsModalQueryRouter = router({
get: contentstackBaseProcedure.query(async ({ ctx }) => {
const { lang, uid } = ctx
const getRefsCounter = createCounter(
"trpc.contentstack",
"usePointsModal.get.refs"
@@ -29,11 +34,12 @@ export const usePointsModalQueryRouter = router({
})
metricsRefs.start()
const refsTag = generateRefsResponseTag(lang, "usepointsmodal")
const refsResponse = await request<UsePointsModalRefsData>(
GetUsePointsModalRefs,
{ locale: lang },
{
key: `contentstack:usePointsModal:${lang}:refs`,
key: refsTag,
ttl: "max",
}
)
@@ -62,11 +68,18 @@ export const usePointsModalQueryRouter = router({
})
metrics.start()
const connections = getConnections(validatedRefsData.data)
const tags = [
generateTagsFromSystem(lang, connections),
generateTag(lang, "usepointsmodal"),
].flat()
const response = await request<UsePointsModalData>(
GetUsePointsModal,
{ locale: lang },
{
key: `contentstack:usePointsModal:${lang}`,
key: tags,
ttl: "max",
}
)

View File

@@ -0,0 +1,17 @@
import type { System } from "../schemas/system"
import type { UsePointsModalRefsData } from "./output"
export function getConnections({ all_usepointsmodal }: UsePointsModalRefsData) {
const connections: System["system"][] = all_usepointsmodal?.items?.[0]
? [all_usepointsmodal?.items?.[0]?.system]
: []
if (all_usepointsmodal && all_usepointsmodal.items) {
all_usepointsmodal?.items.forEach((item) => {
item.link_group.forEach((link) => {
link.link?.uid && connections.push(link.link)
})
})
}
return connections
}