feat(SW-190): added hero to static content pages
This commit is contained in:
5
server/routers/contentstack/contentPage/index.ts
Normal file
5
server/routers/contentstack/contentPage/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { mergeRouters } from "@/server/trpc"
|
||||
|
||||
import { contentPageQueryRouter } from "./query"
|
||||
|
||||
export const contentPageRouter = mergeRouters(contentPageQueryRouter)
|
||||
30
server/routers/contentstack/contentPage/output.ts
Normal file
30
server/routers/contentstack/contentPage/output.ts
Normal 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
|
||||
}
|
||||
64
server/routers/contentstack/contentPage/query.ts
Normal file
64
server/routers/contentstack/contentPage/query.ts
Normal 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,
|
||||
}
|
||||
}),
|
||||
})
|
||||
9
server/routers/contentstack/contentPage/utils.ts
Normal file
9
server/routers/contentstack/contentPage/utils.ts
Normal 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
|
||||
}
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
@@ -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[]
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user