import { Lang } from "@/constants/languages" import { GetLoyaltyPage, GetLoyaltyPageRefs, } from "@/lib/graphql/Query/LoyaltyPage.graphql" import { request } from "@/lib/graphql/request" import { notFound } from "@/server/errors/trpc" import { contentstackExtendedProcedureUID, router } from "@/server/trpc" import { generateRefsResponseTag, generateTag, generateTags, } from "@/utils/generateTag" import { insertResponseToImageVaultAsset } from "@/utils/imageVault" import { removeMultipleSlashes } from "@/utils/url" import { removeEmptyObjects } from "../../utils" import { LoyaltyPage, type LoyaltyPageRefsDataRaw, validateLoyaltyPageRefsSchema, validateLoyaltyPageSchema, } from "./output" import { getConnections } from "./utils" import { InsertResponse } from "@/types/components/imageVaultImage" import { LoyaltyBlocksTypenameEnum, LoyaltyCardsGridEnum, SidebarTypenameEnum, } from "@/types/components/loyalty/enums" import { TrackingChannelEnum, TrackingSDKPageData, } from "@/types/components/tracking" function makeImageVaultImage(image: any) { return image && !!Object.keys(image).length ? insertResponseToImageVaultAsset(image as InsertResponse) : undefined } function makeButtonObject(button: any) { if (!button) return null const isContenstackLink = button?.is_contentstack_link || button.linkConnection?.edges?.length return { openInNewTab: button?.open_in_new_tab, title: button.cta_text || (isContenstackLink ? button.linkConnection.edges[0].node.title : button.external_link.title), href: isContenstackLink ? button.linkConnection.edges[0].node.web?.original_url || removeMultipleSlashes( `/${button.linkConnection.edges[0].node.system.locale}/${button.linkConnection.edges[0].node.url}` ) : button.external_link.href, isExternal: !isContenstackLink, } } export const loyaltyPageQueryRouter = router({ get: contentstackExtendedProcedureUID.query(async ({ ctx }) => { const { lang, uid } = ctx const refsResponse = await request( GetLoyaltyPageRefs, { locale: lang, uid, }, { tags: [generateRefsResponseTag(lang, uid)], } ) if (!refsResponse.data) { throw notFound(refsResponse) } const cleanedData = removeEmptyObjects(refsResponse.data) const validatedLoyaltyPageRefs = validateLoyaltyPageRefsSchema.safeParse(cleanedData) if (!validatedLoyaltyPageRefs.success) { console.error( `Failed to validate Loyaltypage Refs - (lang: ${lang}, uid: ${uid})` ) console.error(validatedLoyaltyPageRefs.error) return null } const connections = getConnections(validatedLoyaltyPageRefs.data) const tags = [ generateTags(lang, connections), generateTag(lang, validatedLoyaltyPageRefs.data.loyalty_page.system.uid), ].flat() const response = await request( GetLoyaltyPage, { locale: lang, uid, }, { tags } ) if (!response.data) { throw notFound(response) } const blocks = response.data.loyalty_page.blocks ? response.data.loyalty_page.blocks.map((block: any) => { switch (block.__typename) { case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksDynamicContent: return { ...block, dynamic_content: { ...block.dynamic_content, link: block.dynamic_content.link.pageConnection.edges.length ? { text: block.dynamic_content.link.text, href: removeMultipleSlashes( `/${block.dynamic_content.link.pageConnection.edges[0].node.system.locale}/${block.dynamic_content.link.pageConnection.edges[0].node.url}` ), title: block.dynamic_content.link.pageConnection.edges[0] .node.title, } : undefined, }, } case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksShortcuts: return { ...block, shortcuts: { ...block.shortcuts, shortcuts: block.shortcuts.shortcuts.map((shortcut: any) => ({ text: shortcut.text, openInNewTab: shortcut.open_in_new_tab, ...shortcut.linkConnection.edges[0].node, url: shortcut.linkConnection.edges[0].node.web?.original_url || removeMultipleSlashes( `/${shortcut.linkConnection.edges[0].node.system.locale}/${shortcut.linkConnection.edges[0].node.url}` ), })), }, } case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardsGrid: return { ...block, cards_grid: { ...block.cards_grid, cards: block.cards_grid.cardConnection.edges.map( ({ node: card }: { node: any }) => { switch (card.__typename) { case LoyaltyCardsGridEnum.LoyaltyCard: return { ...card, image: makeImageVaultImage(card.image), link: makeButtonObject(card.link), } case LoyaltyCardsGridEnum.Card: return { ...card, backgroundImage: makeImageVaultImage( card.background_image ), primaryButton: card.has_primary_button ? makeButtonObject(card.primary_button) : undefined, secondaryButton: card.has_secondary_button ? makeButtonObject(card.secondary_button) : undefined, } } } ), }, } default: return block } }) : null const sidebar = response.data.loyalty_page.sidebar ? response.data.loyalty_page.sidebar.map((item: any) => { switch (item.__typename) { case SidebarTypenameEnum.LoyaltyPageSidebarJoinLoyaltyContact: return { ...item, join_loyalty_contact: { ...item.join_loyalty_contact, button: makeButtonObject(item.join_loyalty_contact.button), }, } default: return item } }) : null const loyaltyPage = { heading: response.data.loyalty_page.heading, system: response.data.loyalty_page.system, blocks, sidebar, } const validatedLoyaltyPage = validateLoyaltyPageSchema.safeParse(loyaltyPage) if (!validatedLoyaltyPage.success) { console.error( `Failed to validate Loyaltypage Data - (lang: ${lang}, uid: ${uid})` ) console.error(validatedLoyaltyPage.error) return null } const loyaltyTrackingData: TrackingSDKPageData = { pageId: response.data.loyalty_page.system.uid, lang: response.data.loyalty_page.system.locale as Lang, publishedDate: response.data.loyalty_page.system.updated_at, createdDate: response.data.loyalty_page.system.created_at, channel: TrackingChannelEnum["scandic-friends"], pageType: "loyaltycontentpage", } // Assert LoyaltyPage type to get correct typings for RTE fields return { loyaltyPage: validatedLoyaltyPage.data as LoyaltyPage, tracking: loyaltyTrackingData, } }), })