+ {header.data.topLink.link ? (
+
- {headerData.topLink.title}
+ {header.data.topLink.title}
) : null}
diff --git a/components/Header/index.tsx b/components/Header/index.tsx
index cb24d890e..c04f35607 100644
--- a/components/Header/index.tsx
+++ b/components/Header/index.tsx
@@ -1,11 +1,15 @@
import { Suspense } from "react"
+import { getHeader, getLanguageSwitcher } from "@/lib/trpc/memoizedRequests"
+
import MainMenu from "./MainMenu"
import TopMenu from "./TopMenu"
import styles from "./header.module.css"
export default function Header() {
+ void getHeader()
+ void getLanguageSwitcher()
return (
diff --git a/lib/graphql/Fragments/Blocks/Refs/Card.graphql b/lib/graphql/Fragments/Blocks/Refs/Card.graphql
index 3b3c33a9a..8bbf74c32 100644
--- a/lib/graphql/Fragments/Blocks/Refs/Card.graphql
+++ b/lib/graphql/Fragments/Blocks/Refs/Card.graphql
@@ -1,12 +1,16 @@
+#import "../../AccountPage/Ref.graphql"
+#import "../../ContentPage/Ref.graphql"
+#import "../../LoyaltyPage/Ref.graphql"
+
fragment CardBlockRef on Card {
secondary_button {
linkConnection {
edges {
node {
__typename
- ...LoyaltyPageRef
- ...ContentPageRef
...AccountPageRef
+ ...ContentPageRef
+ ...LoyaltyPageRef
}
}
}
@@ -16,9 +20,9 @@ fragment CardBlockRef on Card {
edges {
node {
__typename
- ...LoyaltyPageRef
- ...ContentPageRef
...AccountPageRef
+ ...ContentPageRef
+ ...LoyaltyPageRef
}
}
}
diff --git a/lib/graphql/Query/Header.graphql b/lib/graphql/Query/Header.graphql
index ec6be3b72..cd893f135 100644
--- a/lib/graphql/Query/Header.graphql
+++ b/lib/graphql/Query/Header.graphql
@@ -1,13 +1,11 @@
#import "../Fragments/System.graphql"
-#import "../Fragments/PageLink/AccountPageLink.graphql"
#import "../Fragments/PageLink/ContentPageLink.graphql"
#import "../Fragments/PageLink/HotelPageLink.graphql"
#import "../Fragments/PageLink/LoyaltyPageLink.graphql"
#import "../Fragments/Blocks/Card.graphql"
#import "../Fragments/Blocks/Refs/Card.graphql"
-#import "../Fragments/AccountPage/Ref.graphql"
#import "../Fragments/ContentPage/Ref.graphql"
#import "../Fragments/HotelPage/Ref.graphql"
#import "../Fragments/LoyaltyPage/Ref.graphql"
@@ -20,6 +18,7 @@ query GetHeader($locale: String!) {
linkConnection {
edges {
node {
+ __typename
...ContentPageLink
...HotelPageLink
...LoyaltyPageLink
@@ -32,6 +31,7 @@ query GetHeader($locale: String!) {
linkConnection {
edges {
node {
+ __typename
...ContentPageLink
...HotelPageLink
...LoyaltyPageLink
@@ -43,6 +43,7 @@ query GetHeader($locale: String!) {
linkConnection {
edges {
node {
+ __typename
...ContentPageLink
...HotelPageLink
...LoyaltyPageLink
@@ -57,6 +58,7 @@ query GetHeader($locale: String!) {
linkConnection {
edges {
node {
+ __typename
...ContentPageLink
...HotelPageLink
...LoyaltyPageLink
@@ -68,6 +70,7 @@ query GetHeader($locale: String!) {
cardConnection {
edges {
node {
+ __typename
...CardBlock
}
}
@@ -84,6 +87,7 @@ query GetHeaderRef($locale: String!) {
linkConnection {
edges {
node {
+ __typename
...ContentPageRef
...HotelPageRef
...LoyaltyPageRef
@@ -95,6 +99,7 @@ query GetHeaderRef($locale: String!) {
linkConnection {
edges {
node {
+ __typename
...ContentPageRef
...HotelPageRef
...LoyaltyPageRef
@@ -105,6 +110,7 @@ query GetHeaderRef($locale: String!) {
linkConnection {
edges {
node {
+ __typename
...ContentPageRef
...HotelPageRef
...LoyaltyPageRef
@@ -117,6 +123,7 @@ query GetHeaderRef($locale: String!) {
linkConnection {
edges {
node {
+ __typename
...ContentPageRef
...HotelPageRef
...LoyaltyPageRef
@@ -128,6 +135,7 @@ query GetHeaderRef($locale: String!) {
cardConnection {
edges {
node {
+ __typename
...CardBlockRef
}
}
diff --git a/lib/trpc/memoizedRequests/index.ts b/lib/trpc/memoizedRequests/index.ts
index 43c1959f9..6130a8556 100644
--- a/lib/trpc/memoizedRequests/index.ts
+++ b/lib/trpc/memoizedRequests/index.ts
@@ -9,3 +9,17 @@ export const getLocations = cache(async function getMemoizedLocations() {
export const getProfile = cache(async function getMemoizedProfile() {
return serverClient().user.get()
})
+
+export const getFooter = cache(async function getMemoizedFooter() {
+ return serverClient().contentstack.base.footer()
+})
+
+export const getHeader = cache(async function getMemoizedHeader() {
+ return serverClient().contentstack.base.header()
+})
+
+export const getLanguageSwitcher = cache(
+ async function getMemoizedLanguageSwitcher() {
+ return serverClient().contentstack.languageSwitcher.get()
+ }
+)
diff --git a/server/routers/contentstack/base/output.ts b/server/routers/contentstack/base/output.ts
index f098392c8..ddca32139 100644
--- a/server/routers/contentstack/base/output.ts
+++ b/server/routers/contentstack/base/output.ts
@@ -1,10 +1,17 @@
-import { z } from "zod"
+import { z, ZodError, ZodIssueCode } from "zod"
import { Lang } from "@/constants/languages"
+import { discriminatedUnion } from "@/lib/discriminatedUnion"
+import {
+ cardBlockRefsSchema,
+ cardBlockSchema,
+ transformCardBlock,
+ transformCardBlockRefs,
+} from "@/server/routers/contentstack/schemas/blocks/cardsGrid"
+import * as pageLinks from "@/server/routers/contentstack/schemas/pageLinks"
import { removeMultipleSlashes } from "@/utils/url"
-import { imageVaultAssetTransformedSchema } from "../schemas/imageVault"
import { systemSchema } from "../schemas/system"
import { Image } from "@/types/image"
@@ -430,228 +437,219 @@ export const validateFooterRefConfigSchema = z.object({
}),
})
-const linkConnectionNodeSchema = z
+/**
+ * New Header Validation
+ */
+
+const linkRefsUnionSchema = z.discriminatedUnion("__typename", [
+ pageLinks.contentPageRefSchema,
+ pageLinks.hotelPageRefSchema,
+ pageLinks.loyaltyPageRefSchema,
+])
+
+const linkRefsSchema = z
.object({
- edges: z
- .array(
+ linkConnection: z.object({
+ edges: z.array(
z.object({
- node: z.object({
- system: systemSchema,
- url: z.string(),
- title: z.string(),
- web: z.object({
- original_url: z.string(),
- }),
- }),
+ node: linkRefsUnionSchema,
})
- )
- .max(1),
- })
- .transform((data) => {
- const node = data.edges[0]?.node
- if (!node) {
- return null
- }
- const url = node.url
- const originalUrl = node.web?.original_url
- const lang = node.system.locale
-
- return {
- href: originalUrl || removeMultipleSlashes(`/${lang}/${url}`),
- isExternal: !!originalUrl,
- }
- })
-
-const linkWithTitleSchema = z
- .object({
- title: z.string(),
- linkConnection: linkConnectionNodeSchema,
- })
- .transform((rawData) => {
- return rawData.linkConnection && rawData.title
- ? {
- ...rawData.linkConnection,
- title: rawData.title,
- }
- : null
- })
-
-const cardButtonSchema = z
- .object({
- cta_text: z.string(),
- external_link: z.object({
- href: z.string(),
- title: z.string(),
+ ),
}),
- is_contentstack_link: z.boolean(),
- linkConnection: linkConnectionNodeSchema,
- open_in_new_tab: z.boolean(),
})
.transform((data) => {
- const linkConnectionData = data.linkConnection
- const isContentstackLink = data.is_contentstack_link
- const externalLink = data.external_link
- const href =
- isContentstackLink && externalLink.href
- ? externalLink.href
- : linkConnectionData?.href ?? ""
-
- return {
- openInNewTab: data.open_in_new_tab,
- title: data.cta_text,
- href,
- isExternal: !isContentstackLink || linkConnectionData?.isExternal,
+ if (data.linkConnection.edges.length) {
+ const link = pageLinks.transformRef(data.linkConnection.edges[0].node)
+ if (link) {
+ return {
+ link,
+ }
+ }
}
+ return { link: null }
})
-const cardConnectionSchema = z
- .object({
- edges: z
- .array(
+const menuItemsRefsSchema = z.intersection(
+ linkRefsSchema,
+ z
+ .object({
+ cardConnection: z.object({
+ edges: z.array(
+ z.object({
+ node: cardBlockRefsSchema,
+ })
+ ),
+ }),
+ see_all_link: linkRefsSchema,
+ submenu: z.array(
z.object({
- node: z.object({
- heading: z.string(),
- body_text: z.string(),
- background_image: imageVaultAssetTransformedSchema,
- has_primary_button: z.boolean(),
- has_secondary_button: z.boolean(),
- scripted_top_title: z.string(),
- primary_button: cardButtonSchema.nullable(),
- secondary_button: cardButtonSchema.nullable(),
- }),
+ links: z.array(linkRefsSchema),
})
- )
- .max(1),
- })
- .transform((data) => {
- const node = data.edges[0]?.node
- if (!node) {
- return null
- }
+ ),
+ })
+ .transform((data) => {
+ let card = null
+ if (data.cardConnection.edges.length) {
+ card = transformCardBlockRefs(data.cardConnection.edges[0].node)
+ }
- return {
- scriptedTopTitle: node.scripted_top_title,
- heading: node.heading,
- bodyText: node.body_text,
- backgroundImage: node.background_image,
- primaryButton: node.has_primary_button ? node.primary_button : null,
- secondaryButton: node.has_secondary_button ? node.secondary_button : null,
- }
- })
+ return {
+ card,
+ see_all_link: data.see_all_link,
+ submenu: data.submenu,
+ }
+ })
+)
-export const menuItemSchema = z
- .object({
- title: z.string(),
- linkConnection: linkConnectionNodeSchema,
- submenu: z.array(
- z.object({
- title: z.string(),
- links: z.array(linkWithTitleSchema),
- })
- ),
- see_all_link: linkWithTitleSchema,
- cardConnection: cardConnectionSchema,
- })
- .transform((data) => {
- const { submenu, linkConnection, cardConnection, see_all_link, title } =
- data
- return {
- title,
- link: submenu.length ? null : linkConnection,
- seeAllLink: submenu.length ? see_all_link : null,
- submenu,
- card: cardConnection,
- }
- })
-
-export const getHeaderSchema = z
+export const headerRefsSchema = z
.object({
all_header: z.object({
items: z
.array(
z.object({
- top_link: linkWithTitleSchema,
- menu_items: z.array(menuItemSchema),
+ menu_items: z.array(menuItemsRefsSchema),
+ system: systemSchema,
+ top_link: linkRefsSchema,
})
)
- .length(1),
+ .max(1),
}),
})
.transform((data) => {
- const { top_link, menu_items } = data.all_header.items[0]
+ if (!data.all_header.items.length) {
+ console.info(`Zod Error - No header returned in refs request`)
+ throw new ZodError([
+ {
+ code: ZodIssueCode.custom,
+ fatal: true,
+ message: "No header returned (Refs)",
+ path: ["all_header.items"],
+ },
+ ])
+ }
return {
- topLink: top_link,
- menuItems: menu_items,
+ header: data.all_header.items[0],
}
})
-const linkConnectionRefs = z.object({
- edges: z
- .array(
- z.object({
- node: z.object({
- system: systemSchema,
- }),
- })
- )
- .max(1),
-})
+const linkUnionSchema = z.discriminatedUnion("__typename", [
+ pageLinks.contentPageSchema,
+ pageLinks.hotelPageSchema,
+ pageLinks.loyaltyPageSchema,
+])
-const cardConnectionRefs = z.object({
- primary_button: z
- .object({
- linkConnection: linkConnectionRefs,
- })
- .nullable(),
- secondary_button: z
- .object({
- linkConnection: linkConnectionRefs,
- })
- .nullable(),
- system: z.object({
- content_type_uid: z.string(),
- uid: z.string(),
- }),
-})
-
-export const getHeaderRefSchema = z.object({
- all_header: z.object({
- items: z
- .array(
+const linkSchema = z
+ .object({
+ linkConnection: z.object({
+ edges: z.array(
z.object({
- top_link: z
- .object({
- linkConnection: linkConnectionRefs,
- })
- .nullable(),
- menu_items: z.array(
+ node: discriminatedUnion(linkUnionSchema.options),
+ })
+ ),
+ }),
+ })
+ .transform((data) => {
+ if (data.linkConnection.edges.length) {
+ const link = pageLinks.transform(data.linkConnection.edges[0].node)
+ if (link) {
+ return {
+ link,
+ }
+ }
+ }
+
+ return {
+ link: null,
+ }
+ })
+
+const titleSchema = z.object({
+ title: z.string().optional().default(""),
+})
+
+/**
+ * Intersection has to be used since you are not
+ * allowed to merge two schemas where one uses
+ * transform
+ */
+const linkAndTitleSchema = z.intersection(linkSchema, titleSchema)
+
+/**
+ * Same as above 👆
+ */
+export const menuItemSchema = z
+ .intersection(
+ linkAndTitleSchema,
+ z
+ .object({
+ cardConnection: z.object({
+ edges: z.array(
z.object({
- linkConnection: linkConnectionRefs,
- see_all_link: z.object({
- linkConnection: linkConnectionRefs,
- }),
- cardConnection: z.object({
- edges: z
- .array(
- z.object({
- node: cardConnectionRefs,
- })
- )
- .max(1),
- }),
- submenu: z.array(
- z.object({
- links: z.array(
- z.object({ linkConnection: linkConnectionRefs })
- ),
- })
- ),
+ node: cardBlockSchema,
})
),
- system: systemSchema,
- })
- )
- .length(1),
- }),
-})
+ }),
+ see_all_link: linkAndTitleSchema,
+ submenu: z.array(
+ z.object({
+ links: z.array(linkAndTitleSchema),
+ title: z.string().optional().default(""),
+ })
+ ),
+ })
+ .transform((data) => {
+ let card = null
+ if (data.cardConnection.edges.length) {
+ card = transformCardBlock(data.cardConnection.edges[0].node)
+ }
+
+ return {
+ card,
+ seeAllLink: data.see_all_link,
+ submenu: data.submenu,
+ }
+ })
+ )
+ .transform((data) => {
+ return {
+ ...data,
+ link: data.submenu.length ? null : data.link,
+ seeAllLink: data.submenu.length ? data.seeAllLink : null,
+ }
+ })
+
+export const headerSchema = z
+ .object({
+ all_header: z.object({
+ items: z
+ .array(
+ z.object({
+ menu_items: z.array(menuItemSchema),
+ top_link: linkAndTitleSchema,
+ })
+ )
+ .max(1),
+ }),
+ })
+ .transform((data) => {
+ if (!data.all_header.items.length) {
+ console.info(`Zod Error - No header returned in request`)
+ throw new ZodError([
+ {
+ code: ZodIssueCode.custom,
+ fatal: true,
+ message: "No header returned",
+ path: ["all_header.items"],
+ },
+ ])
+ }
+
+ const header = data.all_header.items[0]
+ return {
+ header: {
+ menuItems: header.menu_items,
+ topLink: header.top_link,
+ },
+ }
+ })
diff --git a/server/routers/contentstack/base/query.ts b/server/routers/contentstack/base/query.ts
index a78043f22..74b511123 100644
--- a/server/routers/contentstack/base/query.ts
+++ b/server/routers/contentstack/base/query.ts
@@ -9,14 +9,8 @@ import {
GetCurrentHeader,
GetCurrentHeaderRef,
} from "@/lib/graphql/Query/Current/Header.graphql"
-import {
- GetFooter,
- GetFooterRef,
-} from "@/lib/graphql/Query/Footer.graphql"
-import {
- GetHeader,
- GetHeaderRef,
-} from "@/lib/graphql/Query/Header.graphql"
+import { GetFooter, GetFooterRef } from "@/lib/graphql/Query/Footer.graphql"
+import { GetHeader, GetHeaderRef } from "@/lib/graphql/Query/Header.graphql"
import { request } from "@/lib/graphql/request"
import { notFound } from "@/server/errors/trpc"
import { contentstackBaseProcedure, router } from "@/server/trpc"
@@ -25,22 +19,23 @@ import {
generateRefsResponseTag,
generateTag,
generateTags,
+ generateTagsFromSystem,
} from "@/utils/generateTag"
import { langInput } from "./input"
import {
- type GetCurrentHeaderData,
type ContactConfigData,
CurrentFooterDataRaw,
CurrentFooterRefDataRaw,
CurrentHeaderRefDataRaw,
- getHeaderRefSchema,
- getHeaderSchema,
+ type GetCurrentHeaderData,
+ headerRefsSchema,
+ headerSchema,
validateContactConfigSchema,
validateCurrentFooterConfigSchema,
+ validateCurrentHeaderConfigSchema,
validateFooterConfigSchema,
validateFooterRefConfigSchema,
- validateCurrentHeaderConfigSchema,
} from "./output"
import { getConnections, getFooterConnections } from "./utils"
@@ -48,7 +43,10 @@ import type {
FooterDataRaw,
FooterRefDataRaw,
} from "@/types/components/footer/footer"
-import type { HeaderRefResponse, HeaderResponse } from "@/types/header"
+import type {
+ GetHeader as GetHeaderData,
+ GetHeaderRefs,
+} from "@/types/trpc/routers/contentstack/header"
const meter = metrics.getMeter("trpc.contentstack.base")
// OpenTelemetry metrics: ContactConfig
@@ -209,7 +207,7 @@ export const baseQueryRouter = router({
JSON.stringify({ query: { lang } })
)
- const responseRef = await request(
+ const responseRef = await request(
GetHeaderRef,
{
locale: lang,
@@ -241,7 +239,7 @@ export const baseQueryRouter = router({
throw notFoundError
}
- const validatedHeaderRefs = getHeaderRefSchema.safeParse(responseRef.data)
+ const validatedHeaderRefs = headerRefsSchema.safeParse(responseRef.data)
if (!validatedHeaderRefs.success) {
getHeaderRefsFailCounter.add(1, {
@@ -276,14 +274,11 @@ export const baseQueryRouter = router({
)
const tags = [
- generateTags(lang, connections),
- generateTag(
- lang,
- validatedHeaderRefs.data.all_header.items[0].system.uid
- ),
+ generateTagsFromSystem(lang, connections),
+ generateTag(lang, validatedHeaderRefs.data.header.system.uid),
].flat()
- const response = await request(
+ const response = await request(
GetHeader,
{ locale: lang },
{ cache: "force-cache", next: { tags } }
@@ -306,7 +301,7 @@ export const baseQueryRouter = router({
throw notFoundError
}
- const validatedHeaderConfig = getHeaderSchema.safeParse(response.data)
+ const validatedHeaderConfig = headerSchema.safeParse(response.data)
if (!validatedHeaderConfig.success) {
getHeaderFailCounter.add(1, {
@@ -329,7 +324,9 @@ export const baseQueryRouter = router({
JSON.stringify({ query: { lang } })
)
- return validatedHeaderConfig.data
+ return {
+ data: validatedHeaderConfig.data.header,
+ }
}),
currentHeader: contentstackBaseProcedure
.input(langInput)
diff --git a/server/routers/contentstack/base/utils.ts b/server/routers/contentstack/base/utils.ts
index 6125eec92..cd61dea0c 100644
--- a/server/routers/contentstack/base/utils.ts
+++ b/server/routers/contentstack/base/utils.ts
@@ -2,43 +2,42 @@ import type {
FooterLinkItem,
FooterRefDataRaw,
} from "@/types/components/footer/footer"
-import type { HeaderRefResponse } from "@/types/header"
+import { System } from "@/types/requests/system"
import { Edges } from "@/types/requests/utils/edges"
import { NodeRefs } from "@/types/requests/utils/refs"
+import type { HeaderRefs } from "@/types/trpc/routers/contentstack/header"
-export function getConnections(refs: HeaderRefResponse) {
- const connections: Edges[] = []
- const headerData = refs.all_header.items[0]
- const topLink = headerData.top_link
- if (topLink) {
- connections.push(topLink.linkConnection)
+export function getConnections({ header }: HeaderRefs) {
+ const connections: System["system"][] = [header.system]
+
+ if (header.top_link?.link) {
+ connections.push(header.top_link.link)
}
- headerData.menu_items.forEach(
- ({ linkConnection, see_all_link, cardConnection, submenu }) => {
- const card = cardConnection.edges[0]?.node
- connections.push(linkConnection)
-
- if (see_all_link) {
- connections.push(see_all_link.linkConnection)
+ if (header.menu_items.length) {
+ header.menu_items.forEach((menuItem) => {
+ if (menuItem.card) {
+ connections.push(...menuItem.card)
}
-
- if (card) {
- if (card.primary_button) {
- connections.push(card.primary_button.linkConnection)
- }
- if (card.secondary_button) {
- connections.push(card.secondary_button.linkConnection)
- }
+ if (menuItem.link) {
+ connections.push(menuItem.link)
}
-
- submenu.forEach(({ links }) => {
- links.forEach(({ linkConnection }) => {
- connections.push(linkConnection)
+ if (menuItem.see_all_link?.link) {
+ connections.push(menuItem.see_all_link.link)
+ }
+ if (menuItem.submenu.length) {
+ menuItem.submenu.forEach((subMenuItem) => {
+ if (subMenuItem.links.length) {
+ subMenuItem.links.forEach((link) => {
+ if (link?.link) {
+ connections.push(link.link)
+ }
+ })
+ }
})
- })
- }
- )
+ }
+ })
+ }
return connections
}
diff --git a/server/routers/contentstack/schemas/blocks/cardsGrid.ts b/server/routers/contentstack/schemas/blocks/cardsGrid.ts
index a37a70724..d9c39bcc5 100644
--- a/server/routers/contentstack/schemas/blocks/cardsGrid.ts
+++ b/server/routers/contentstack/schemas/blocks/cardsGrid.ts
@@ -8,7 +8,7 @@ import { linkConnectionRefsSchema } from "./utils/linkConnection"
import { BlocksEnums } from "@/types/enums/blocks"
import { CardsGridEnum } from "@/types/enums/cardsGrid"
-const cardBlockSchema = z.object({
+export const cardBlockSchema = z.object({
__typename: z.literal(CardsGridEnum.cards.Card),
// JSON - ImageVault Image
background_image: tempImageVaultAssetSchema,
@@ -30,6 +30,29 @@ const cardBlockSchema = z.object({
title: z.string().optional(),
})
+export function transformCardBlock(card: typeof cardBlockSchema._type) {
+ return {
+ __typename: card.__typename,
+ backgroundImage: card.background_image,
+ body_text: card.body_text,
+ heading: card.heading,
+ isContentCard: card.is_content_card,
+ primaryButton: card.has_primary_button ? card.primary_button : undefined,
+ scripted_top_title: card.scripted_top_title,
+ secondaryButton: card.has_secondary_button
+ ? card.secondary_button
+ : undefined,
+ sidePeekButton:
+ card.has_sidepeek_button && card.sidepeek_button?.call_to_action_text
+ ? {
+ title: card.sidepeek_button.call_to_action_text,
+ }
+ : undefined,
+ system: card.system,
+ title: card.title,
+ }
+}
+
const loyaltyCardBlockSchema = z.object({
__typename: z.literal(CardsGridEnum.cards.LoyaltyCard),
body_text: z.string().optional(),
@@ -71,29 +94,7 @@ export const cardsGridSchema = z.object({
title: data.title,
cards: data.cardConnection.edges.map((card) => {
if (card.node.__typename === CardsGridEnum.cards.Card) {
- return {
- __typename: card.node.__typename,
- backgroundImage: card.node.background_image,
- body_text: card.node.body_text,
- heading: card.node.heading,
- isContentCard: card.node.is_content_card,
- primaryButton: card.node.has_primary_button
- ? card.node.primary_button
- : undefined,
- scripted_top_title: card.node.scripted_top_title,
- secondaryButton: card.node.has_secondary_button
- ? card.node.secondary_button
- : undefined,
- sidePeekButton:
- card.node.has_sidepeek_button &&
- card.node.sidepeek_button?.call_to_action_text
- ? {
- title: card.node.sidepeek_button.call_to_action_text,
- }
- : undefined,
- system: card.node.system,
- title: card.node.title,
- }
+ return transformCardBlock(card.node)
} else {
return {
__typename: card.node.__typename,
@@ -110,13 +111,24 @@ export const cardsGridSchema = z.object({
}),
})
-const cardBlockRefsSchema = z.object({
+export const cardBlockRefsSchema = z.object({
__typename: z.literal(CardsGridEnum.cards.Card),
primary_button: linkConnectionRefsSchema,
secondary_button: linkConnectionRefsSchema,
system: systemSchema,
})
+export function transformCardBlockRefs(card: typeof cardBlockRefsSchema._type) {
+ const cards = [card.system]
+ if (card.primary_button) {
+ cards.push(card.primary_button)
+ }
+ if (card.secondary_button) {
+ cards.push(card.secondary_button)
+ }
+ return cards
+}
+
const loyaltyCardBlockRefsSchema = z.object({
__typename: z.literal(CardsGridEnum.cards.LoyaltyCard),
link: linkConnectionRefsSchema,
@@ -141,14 +153,7 @@ export const cardGridRefsSchema = z.object({
return data.cardConnection.edges
.map(({ node }) => {
if (node.__typename === CardsGridEnum.cards.Card) {
- const cards = [node.system]
- if (node.primary_button) {
- cards.push(node.primary_button)
- }
- if (node.secondary_button) {
- cards.push(node.secondary_button)
- }
- return cards
+ return transformCardBlockRefs(node)
} else {
const loyaltyCards = [node.system]
if (node.link) {
diff --git a/server/routers/contentstack/schemas/pageLinks.ts b/server/routers/contentstack/schemas/pageLinks.ts
index d7e7d493b..95b1b5fc5 100644
--- a/server/routers/contentstack/schemas/pageLinks.ts
+++ b/server/routers/contentstack/schemas/pageLinks.ts
@@ -46,7 +46,7 @@ export const hotelPageSchema = z
.object({
__typename: z.literal(ContentEnum.blocks.HotelPage),
})
- .merge(extendedPageLinkSchema)
+ .merge(pageLinkSchema)
export const hotelPageRefSchema = z.object({
__typename: z.literal(ContentEnum.blocks.HotelPage),
diff --git a/types/components/footer/navigation.ts b/types/components/footer/navigation.ts
index e17c7d65b..700bf5e5f 100644
--- a/types/components/footer/navigation.ts
+++ b/types/components/footer/navigation.ts
@@ -1,41 +1,19 @@
-import { z } from "zod"
-
-import {
- validateLinkItem,
- validateLinksWithType,
- validateSecondaryLinks,
-} from "@/server/routers/contentstack/base/output"
-
-import type { LanguageSwitcherData } from "@/types/requests/languageSwitcher"
-
-export type FooterLink = z.output
+import type {
+ FooterLink,
+ FooterLinkWithType,
+ FooterSecondaryNavGroup,
+} from "@/types/trpc/routers/contentstack/footer"
export type FooterMainNavProps = {
mainLinks: FooterLink[]
}
-type FooterSecondaryNavGroup = z.output
-
-type FooterLinkWithType = z.output
-
type FooterAppDownloads = {
title: string
links: FooterLinkWithType
}
-type FooterSocialMedia = {
- links: FooterLinkWithType
-}
-
export type FooterSecondaryNavProps = {
secondaryLinks: FooterSecondaryNavGroup
appDownloads: FooterAppDownloads
}
-
-export type FooterDetailsProps = {
- socialMedia?: FooterSocialMedia
- tertiaryLinks?: FooterLink[]
- languageUrls?: LanguageSwitcherData
-}
-
-export type FooterNavigationProps = FooterMainNavProps & FooterSecondaryNavProps
diff --git a/types/components/header/header.ts b/types/components/header/header.ts
deleted file mode 100644
index e69de29bb..000000000
diff --git a/types/components/header/mobileMenu.ts b/types/components/header/mobileMenu.ts
index 398bb725e..d773b397b 100644
--- a/types/components/header/mobileMenu.ts
+++ b/types/components/header/mobileMenu.ts
@@ -1,7 +1,7 @@
-import type { Header, MenuItem } from "@/types/header"
import type { LanguageSwitcherData } from "@/types/requests/languageSwitcher"
+import type { Header } from "@/types/trpc/routers/contentstack/header"
export interface MobileMenuProps {
languageUrls: LanguageSwitcherData
- topLink: Header["topLink"]
+ topLink: Header["header"]["topLink"]
}
diff --git a/types/components/header/navigationMenuItem.ts b/types/components/header/navigationMenuItem.ts
index d89fd447c..6cfe3cb60 100644
--- a/types/components/header/navigationMenuItem.ts
+++ b/types/components/header/navigationMenuItem.ts
@@ -1,4 +1,4 @@
-import type { MenuItem } from "@/types/header"
+import type { MenuItem } from "@/types/trpc/routers/contentstack/header"
export interface NavigationMenuItemProps {
item: MenuItem
diff --git a/types/components/header/navigationMenuList.ts b/types/components/header/navigationMenuList.ts
index 56fa579e9..363ecbb59 100644
--- a/types/components/header/navigationMenuList.ts
+++ b/types/components/header/navigationMenuList.ts
@@ -1,4 +1,4 @@
-import type { MenuItem } from "@/types/header"
+import type { MenuItem } from "@/types/trpc/routers/contentstack/header"
export interface NavigationMenuListProps {
isMobile: boolean
diff --git a/types/header.ts b/types/header.ts
deleted file mode 100644
index cc425f618..000000000
--- a/types/header.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { z } from "zod"
-
-import {
- getHeaderRefSchema,
- getHeaderSchema,
- menuItemSchema,
-} from "@/server/routers/contentstack/base/output"
-
-export type HeaderRefResponse = z.input
-export type HeaderResponse = z.input
-export type Header = z.output
-export type MenuItem = z.output
diff --git a/types/trpc/routers/contentstack/footer.ts b/types/trpc/routers/contentstack/footer.ts
new file mode 100644
index 000000000..23c3b7084
--- /dev/null
+++ b/types/trpc/routers/contentstack/footer.ts
@@ -0,0 +1,11 @@
+import { z } from "zod"
+
+import {
+ validateLinkItem,
+ validateLinksWithType,
+ validateSecondaryLinks,
+} from "@/server/routers/contentstack/base/output"
+
+export type FooterLink = z.output
+export type FooterSecondaryNavGroup = z.output
+export type FooterLinkWithType = z.output
diff --git a/types/trpc/routers/contentstack/header.ts b/types/trpc/routers/contentstack/header.ts
new file mode 100644
index 000000000..a28c3114e
--- /dev/null
+++ b/types/trpc/routers/contentstack/header.ts
@@ -0,0 +1,15 @@
+import { z } from "zod"
+
+import {
+ headerRefsSchema,
+ headerSchema,
+ menuItemSchema,
+} from "@/server/routers/contentstack/base/output"
+
+export type GetHeaderRefs = z.input
+export type HeaderRefs = NonNullable>
+
+export type GetHeader = z.input
+export type Header = z.output
+
+export type MenuItem = z.output