diff --git a/lib/graphql/Fragments/Blocks/Card.graphql b/lib/graphql/Fragments/Blocks/Card.graphql index 99ae37916..0fb2e416c 100644 --- a/lib/graphql/Fragments/Blocks/Card.graphql +++ b/lib/graphql/Fragments/Blocks/Card.graphql @@ -4,6 +4,7 @@ fragment CardBlock on Card { background_image scripted_top_title title + has_secondary_button secondary_button { is_contentstack_link cta_text @@ -23,6 +24,7 @@ fragment CardBlock on Card { } } } + has_primary_button primary_button { is_contentstack_link cta_text diff --git a/server/routers/contentstack/loyaltyPage/output.ts b/server/routers/contentstack/loyaltyPage/output.ts index 73dc9e2c1..7fd660663 100644 --- a/server/routers/contentstack/loyaltyPage/output.ts +++ b/server/routers/contentstack/loyaltyPage/output.ts @@ -13,28 +13,6 @@ import { PageLinkEnum } from "@/types/requests/pageLinks" import { EdgesWithTotalCount } from "@/types/requests/utils/edges" import { RTEDocument } from "@/types/rte/node" -const pageLink = z.object({ - edges: z.array( - z.object({ - node: z.object({ - system: z.object({ - uid: z.string(), - locale: z.nativeEnum(Lang), - }), - web: z - .object({ - original_url: z.string().nullable(), - }) - .nullable() - .optional(), - url: z.string(), - title: z.string(), - __typename: z.string().optional(), - }), - }) - ), -}) - const loyaltyPageDynamicContent = z.object({ __typename: z.literal( LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksDynamicContent @@ -43,10 +21,13 @@ const loyaltyPageDynamicContent = z.object({ title: z.string().nullable(), subtitle: z.string().nullable(), component: z.nativeEnum(LoyaltyComponentEnum), - link: z.object({ - text: z.string().nullable(), - pageConnection: pageLink, - }), + link: z + .object({ + text: z.string().nullable(), + href: z.string(), + title: z.string(), + }) + .optional(), }), }) @@ -57,9 +38,10 @@ const loyaltyPageShortcuts = z.object({ preamble: z.string().nullable(), shortcuts: z.array( z.object({ - linkConnection: pageLink, - text: z.string().nullable(), - open_in_new_tab: z.boolean(), + text: z.string().optional(), + openInNewTab: z.boolean(), + url: z.string(), + title: z.string(), }) ), }), @@ -70,31 +52,22 @@ const cardBlock = z.object({ body_text: z.string().nullable(), background_image: z.any(), scripted_top_title: z.string().nullable(), - primary_button: z + primaryButton: z .object({ - is_contentstack_link: z.boolean(), - cta_text: z.string().nullable(), - open_in_new_tab: z.boolean(), - external_link: z.object({ - title: z.string().nullable(), - href: z.string().nullable(), - }), - linkConnection: pageLink, + openInNewTab: z.boolean(), + title: z.string(), + href: z.string(), + isExternal: z.boolean(), }) - .nullable(), - secondary_button: z + .optional(), + secondaryButton: z .object({ - is_contentstack_link: z.boolean(), - cta_text: z.string().nullable(), - open_in_new_tab: z.boolean().nullable(), - external_link: z.object({ - title: z.string().nullable(), - href: z.string().nullable(), - }), - linkConnection: pageLink, + openInNewTab: z.boolean(), + title: z.string(), + href: z.string(), + isExternal: z.boolean(), }) - .nullable(), - + .optional(), system: z.object({ locale: z.nativeEnum(Lang), uid: z.string(), @@ -108,13 +81,7 @@ const loyaltyPageCards = z.object({ preamble: z.string().nullable(), layout: z.enum(["twoColumnGrid", "threeColumnGrid", "twoPlusOne"]), theme: z.enum(["one", "two", "three"]).nullable(), - cardConnection: z.object({ - edges: z.array( - z.object({ - node: cardBlock, - }) - ), - }), + cards: z.array(cardBlock), }), }) @@ -178,31 +145,17 @@ const loyaltyPageSidebarItem = z.discriminatedUnion("__typename", [ ]) export const validateLoyaltyPageSchema = z.object({ - loyalty_page: z.object({ - title: z.string(), - heading: z.string().nullable(), - blocks: z.array(loyaltyPageBlockItem).nullable(), - sidebar: z.array(loyaltyPageSidebarItem).nullable(), - system: z.object({ uid: z.string() }), - }), + heading: z.string().nullable(), + blocks: z.array(loyaltyPageBlockItem).nullable(), + sidebar: z.array(loyaltyPageSidebarItem).nullable(), + system: z.object({ uid: z.string() }), }) // Block types -type DynamicContentRaw = z.infer -export type DynamicContent = Omit & { - dynamic_content: Omit & { - link: - | { - href: string - title: string - text?: string - } - | undefined - } -} +export type DynamicContent = z.infer + type BlockContentRaw = z.infer - export interface RteBlockContent extends BlockContentRaw { content: { content: { @@ -214,44 +167,11 @@ export interface RteBlockContent extends BlockContentRaw { type CardsGridRaw = z.infer -export type CardsRaw = - CardsGridRaw["cards_grid"]["cardConnection"]["edges"][number]["node"] +export type CardsRaw = CardsGridRaw["cards_grid"]["cards"][number] -export type CardsGrid = Omit & { - cards_grid: Omit & { - cards: (Omit & { - primaryButton: - | { - openInNewTab: boolean - title: string - href: string - isExternal: boolean - } - | undefined - secondaryButton: - | { - openInNewTab: boolean - title: string - href: string - isExternal: boolean - } - | undefined - })[] - } -} +export type CardsGrid = z.infer -type ShortcutsRaw = z.infer - -export type Shortcuts = Omit & { - shortcuts: Omit & { - shortcuts: { - text?: string - openInNewTab: boolean - url: string - title: string - }[] - } -} +export type Shortcuts = z.infer export type Block = RteBlockContent | DynamicContent | Shortcuts | CardsGrid @@ -268,12 +188,9 @@ export type RteSidebarContent = Omit & { } export type JoinLoyaltyContact = z.infer export type Sidebar = JoinLoyaltyContact | RteSidebarContent +type LoyaltyPageDataRaw = z.infer -export type LoyaltyPageDataRaw = z.infer - -type LoyaltyPageRaw = LoyaltyPageDataRaw["loyalty_page"] - -export type LoyaltyPage = Omit & { +export type LoyaltyPage = Omit & { blocks: Block[] sidebar: Sidebar[] } diff --git a/server/routers/contentstack/loyaltyPage/query.ts b/server/routers/contentstack/loyaltyPage/query.ts index 9f7e4aafe..565b06bc5 100644 --- a/server/routers/contentstack/loyaltyPage/query.ts +++ b/server/routers/contentstack/loyaltyPage/query.ts @@ -15,27 +15,16 @@ import { import { removeEmptyObjects } from "../../utils" import { - CardsRaw, - type LoyaltyPage, - type LoyaltyPageDataRaw, + LoyaltyPage, type LoyaltyPageRefsDataRaw, validateLoyaltyPageRefsSchema, validateLoyaltyPageSchema, } from "./output" import { getConnections } from "./utils" -import { - LoyaltyBlocksTypenameEnum, - SidebarTypenameEnum, -} from "@/types/components/loyalty/enums" -import { Embeds } from "@/types/requests/embeds" -import { Edges } from "@/types/requests/utils/edges" -import { RTEDocument } from "@/types/rte/node" +import { LoyaltyBlocksTypenameEnum } from "@/types/components/loyalty/enums" -function makeButtonObject( - button: CardsRaw["primary_button" | "secondary_button"] -) { - if (!button) return undefined +function makeButtonObject(button: any) { return { openInNewTab: button.open_in_new_tab, title: @@ -93,7 +82,7 @@ export const loyaltyPageQueryRouter = router({ generateTag(lang, validatedLoyaltyPageRefs.data.loyalty_page.system.uid), ].flat() - const response = await request( + const response = await request( GetLoyaltyPage, { locale: lang, @@ -106,36 +95,8 @@ export const loyaltyPageQueryRouter = router({ throw notFound(response) } - const validatedLoyaltyPage = validateLoyaltyPageSchema.safeParse( - response.data - ) - if (!validatedLoyaltyPage.success) { - throw internalServerError(validatedLoyaltyPage.error) - } - - const sidebar = validatedLoyaltyPage.data.loyalty_page.sidebar - ? validatedLoyaltyPage.data.loyalty_page.sidebar.map((block) => { - if ( - block.__typename == SidebarTypenameEnum.LoyaltyPageSidebarContent - ) { - return { - ...block, - content: { - content: { - json: block.content.content.json as RTEDocument, - embedded_itemsConnection: block.content.content - .embedded_itemsConnection as Edges, - }, - }, - } - } else { - return block - } - }) - : null - - const blocks = validatedLoyaltyPage.data.loyalty_page.blocks - ? validatedLoyaltyPage.data.loyalty_page.blocks.map((block) => { + const blocks = response.data.loyalty_page.blocks + ? response.data.loyalty_page.blocks.map((block: any) => { switch (block.__typename) { case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksDynamicContent: return { @@ -153,23 +114,12 @@ export const loyaltyPageQueryRouter = router({ : undefined, }, } - case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksContent: - return { - ...block, - content: { - content: { - json: block.content.content.json as RTEDocument, - embedded_itemsConnection: block.content.content - .embedded_itemsConnection as Edges, - }, - }, - } case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksShortcuts: return { ...block, shortcuts: { ...block.shortcuts, - shortcuts: block.shortcuts.shortcuts.map((shortcut) => ({ + shortcuts: block.shortcuts.shortcuts.map((shortcut: any) => ({ text: shortcut.text, openInNewTab: shortcut.open_in_new_tab, ...shortcut.linkConnection.edges[0].node, @@ -185,13 +135,15 @@ export const loyaltyPageQueryRouter = router({ cards_grid: { ...block.cards_grid, cards: block.cards_grid.cardConnection.edges.map( - ({ node: card }) => { + ({ node: card }: { node: any }) => { return { ...card, - primaryButton: makeButtonObject(card.primary_button), - secondaryButton: makeButtonObject( - card.secondary_button - ), + primaryButton: card.has_primary_button + ? makeButtonObject(card.primary_button) + : undefined, + secondaryButton: card.has_secondary_button + ? makeButtonObject(card.secondary_button) + : undefined, } } ), @@ -204,11 +156,20 @@ export const loyaltyPageQueryRouter = router({ : null const loyaltyPage = { - ...validatedLoyaltyPage.data.loyalty_page, + heading: response.data.loyalty_page.heading, + system: response.data.loyalty_page.system, blocks, - sidebar, - } as LoyaltyPage + sidebar: response.data.loyalty_page.sidebar, + } - return loyaltyPage + const validatedLoyaltyPage = + validateLoyaltyPageSchema.safeParse(loyaltyPage) + + if (!validatedLoyaltyPage.success) { + throw internalServerError(validatedLoyaltyPage.error) + } + + // Assert LoyaltyPage type to get correct typings for RTE fields + return validatedLoyaltyPage.data as LoyaltyPage }), })