feat(SW-190): added hero to static content pages

This commit is contained in:
Erik Tiekstra
2024-08-14 09:29:00 +02:00
parent f1ca9a0704
commit 8220a39a8f
23 changed files with 351 additions and 64 deletions

View File

@@ -0,0 +1,5 @@
import { mergeRouters } from "@/server/trpc"
import { contentPageQueryRouter } from "./query"
export const contentPageRouter = mergeRouters(contentPageQueryRouter)

View File

@@ -0,0 +1,30 @@
import { z } from "zod"
import { Lang } from "@/constants/languages"
import { ImageVaultAsset } from "@/types/components/imageVaultImage"
export const validateContentPageSchema = z.object({
content_page: z.object({
title: z.string(),
header: z.object({
heading: z.string(),
preamble: z.string(),
}),
hero_image: z.any().nullable(),
system: z.object({
uid: z.string(),
locale: z.nativeEnum(Lang),
created_at: z.string(),
updated_at: z.string(),
}),
}),
})
export type ContentPageDataRaw = z.infer<typeof validateContentPageSchema>
type ContentPageRaw = ContentPageDataRaw["content_page"]
export type ContentPage = Omit<ContentPageRaw, "hero_image"> & {
hero_image?: ImageVaultAsset
}

View File

@@ -0,0 +1,64 @@
import { Lang } from "@/constants/languages"
import { GetContentPage } from "@/lib/graphql/Query/ContentPage.graphql"
import { request } from "@/lib/graphql/request"
import { notFound } from "@/server/errors/trpc"
import { contentstackExtendedProcedureUID, router } from "@/server/trpc"
import {
ContentPage,
ContentPageDataRaw,
validateContentPageSchema,
} from "./output"
import { makeImageVaultImage } from "./utils"
import {
TrackingChannelEnum,
TrackingSDKPageData,
} from "@/types/components/tracking"
export const contentPageQueryRouter = router({
get: contentstackExtendedProcedureUID.query(async ({ ctx }) => {
const { lang, uid } = ctx
const response = await request<ContentPageDataRaw>(GetContentPage, {
locale: lang,
uid,
})
if (!response.data) {
throw notFound(response)
}
const validatedContentPage = validateContentPageSchema.safeParse(
response.data
)
if (!validatedContentPage.success) {
console.error(
`Failed to validate Contentpage Data - (lang: ${lang}, uid: ${uid})`
)
console.error(validatedContentPage.error)
return null
}
const contentPageData = validatedContentPage.data.content_page
const contentPage: ContentPage = {
...contentPageData,
hero_image: makeImageVaultImage(contentPageData.hero_image),
}
const tracking: TrackingSDKPageData = {
pageId: contentPageData.system.uid,
lang: contentPageData.system.locale as Lang,
publishedDate: contentPageData.system.updated_at,
createdDate: contentPageData.system.created_at,
channel: TrackingChannelEnum["static-content-page"],
pageType: "staticcontentpage",
}
return {
contentPage,
tracking,
}
}),
})

View File

@@ -0,0 +1,9 @@
import { insertResponseToImageVaultAsset } from "@/utils/imageVault"
import { InsertResponse } from "@/types/components/imageVaultImage"
export function makeImageVaultImage(image: any) {
return image && !!Object.keys(image).length
? insertResponseToImageVaultAsset(image as InsertResponse)
: undefined
}

View File

@@ -3,6 +3,7 @@ import { router } from "@/server/trpc"
import { accountPageRouter } from "./accountPage"
import { baseRouter } from "./base"
import { breadcrumbsRouter } from "./breadcrumbs"
import { contentPageRouter } from "./contentPage"
import { hotelPageRouter } from "./hotelPage"
import { languageSwitcherRouter } from "./languageSwitcher"
import { loyaltyPageRouter } from "./loyaltyPage"
@@ -15,5 +16,6 @@ export const contentstackRouter = router({
hotelPage: hotelPageRouter,
languageSwitcher: languageSwitcherRouter,
loyaltyPage: loyaltyPageRouter,
contentPage: contentPageRouter,
myPages: myPagesRouter,
})

View File

@@ -191,11 +191,8 @@ const loyaltyPageSidebarItem = z.discriminatedUnion("__typename", [
export const validateLoyaltyPageSchema = z.object({
heading: z.string().nullable(),
header: z
.object({
hero_image: z.any(),
})
.nullable(),
preamble: z.string().nullable(),
hero_image: z.any().nullable(),
blocks: z.array(loyaltyPageBlockItem).nullable(),
sidebar: z.array(loyaltyPageSidebarItem).nullable(),
system: z.object({
@@ -263,7 +260,11 @@ export type Sidebar =
| SideBarDynamicContent
type LoyaltyPageDataRaw = z.infer<typeof validateLoyaltyPageSchema>
export type LoyaltyPage = Omit<LoyaltyPageDataRaw, "blocks" | "sidebar"> & {
export type LoyaltyPage = Omit<
LoyaltyPageDataRaw,
"blocks" | "sidebar" | "hero_image"
> & {
hero_image?: ImageVaultAsset
blocks: Block[]
sidebar: Sidebar[]
}

View File

@@ -12,7 +12,6 @@ import {
generateTag,
generateTags,
} from "@/utils/generateTag"
import { insertResponseToImageVaultAsset } from "@/utils/imageVault"
import { removeMultipleSlashes } from "@/utils/url"
import { removeEmptyObjects } from "../../utils"
@@ -22,9 +21,8 @@ import {
validateLoyaltyPageRefsSchema,
validateLoyaltyPageSchema,
} from "./output"
import { getConnections } from "./utils"
import { getConnections, makeButtonObject, makeImageVaultImage } from "./utils"
import { InsertResponse } from "@/types/components/imageVaultImage"
import {
LoyaltyBlocksTypenameEnum,
LoyaltyCardsGridEnum,
@@ -35,35 +33,6 @@ import {
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
@@ -208,17 +177,10 @@ export const loyaltyPageQueryRouter = router({
})
: null
const header = response.data.loyalty_page.header
? {
hero_image: makeImageVaultImage(
response.data.loyalty_page.header.hero_image
),
}
: null
const loyaltyPage = {
heading: response.data.loyalty_page.heading,
header,
preamble: response.data.loyalty_page.preamble,
hero_image: makeImageVaultImage(response.data.loyalty_page.hero_image),
system: response.data.loyalty_page.system,
blocks,
sidebar,

View File

@@ -1,5 +1,9 @@
import { insertResponseToImageVaultAsset } from "@/utils/imageVault"
import { removeMultipleSlashes } from "@/utils/url"
import { LoyaltyPageRefsDataRaw } from "./output"
import { InsertResponse } from "@/types/components/imageVaultImage"
import {
LoyaltyBlocksTypenameEnum,
LoyaltyCardsGridEnum,
@@ -77,3 +81,32 @@ export function getConnections(refs: LoyaltyPageRefsDataRaw) {
return connections
}
export function makeImageVaultImage(image: any) {
return image && !!Object.keys(image).length
? insertResponseToImageVaultAsset(image as InsertResponse)
: undefined
}
export 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,
}
}