Files
web/packages/trpc/lib/routers/contentstack/schemas/blocks/cardsGrid.ts
Erik Tiekstra 8e08af718c feat(BOOK-743): Replaced deprecated Button component
Approved-by: Bianca Widstam
2026-01-21 09:38:38 +00:00

228 lines
6.7 KiB
TypeScript

import { z } from "zod"
import { transformedImageVaultAssetSchema } from "@scandic-hotels/common/utils/imageVault"
import { scriptedCardThemeEnum } from "../../../../enums/scriptedCard"
import { BlocksEnums } from "../../../../types/blocksEnum"
import {
CardsGridEnum,
CardsGridLayoutEnum,
} from "../../../../types/cardsGridEnum"
import { systemSchema } from "../system"
import {
infoCardWithImageBlockRefsSchema,
infoCardWithImageBlockSchema,
transformInfoCardWithImageBlock,
} from "./cards/infoCardWithImage"
import {
loyaltyCardBlockRefsSchema,
loyaltyCardBlockSchema,
} from "./cards/loyaltyCard"
import {
teaserCardBlockRefsSchema,
teaserCardBlockSchema,
transformTeaserCardBlock,
} from "./cards/teaserCard"
import { buttonSchema } from "./utils/buttonLinkSchema"
import { linkConnectionRefsSchema } from "./utils/linkConnection"
export const infoCardBlockSchema = z.object({
__typename: z.literal(CardsGridEnum.cards.InfoCard),
// JSON - ImageVault Image
background_image: transformedImageVaultAssetSchema,
body_text: z.string().optional().default(""),
has_primary_button: z.boolean().default(false),
has_secondary_button: z.boolean().default(false),
heading: z.string().optional().default(""),
primary_button: buttonSchema,
scripted_top_title: z.string().optional(),
secondary_button: buttonSchema,
system: systemSchema,
title: z.string().optional(),
})
export function transformInfoCardBlock(card: typeof infoCardBlockSchema._type) {
return {
__typename: card.__typename,
backgroundImage: card.background_image
? {
src: card.background_image.url,
alt: card.background_image.meta.alt ?? undefined,
focalPoint: card.background_image.focalPoint,
dimensions: card.background_image.dimensions,
}
: undefined,
bodyText: card.body_text,
heading: card.heading,
primaryButton:
card.has_primary_button && card.primary_button
? {
href: card.primary_button.href,
text: card.primary_button.title,
openInNewTab: card.primary_button.openInNewTab,
}
: undefined,
topTitle: card.scripted_top_title,
secondaryButton:
card.has_secondary_button && card.secondary_button
? {
href: card.secondary_button.href,
text: card.secondary_button.title,
openInNewTab: card.secondary_button.openInNewTab,
}
: undefined,
system: card.system,
title: card.title,
}
}
export const cardsGridSchema = z.object({
typename: z
.literal(BlocksEnums.block.CardsGrid)
.optional()
.default(BlocksEnums.block.CardsGrid),
cards_grid: z
.object({
cardConnection: z.object({
edges: z.array(
z.object({
node: z.discriminatedUnion("__typename", [
infoCardBlockSchema,
loyaltyCardBlockSchema,
teaserCardBlockSchema,
infoCardWithImageBlockSchema,
]),
})
),
}),
link: buttonSchema.nullish(),
layout: z.nativeEnum(CardsGridLayoutEnum),
preamble: z.string().optional().default(""),
theme: z
.nativeEnum(scriptedCardThemeEnum)
.nullable()
.transform(getInfoCardThemeFromDeprecatedCardTheme),
title: z.string().optional().default(""),
})
.transform((data) => {
return {
layout: data.layout,
preamble: data.preamble,
theme: data.theme,
title: data.title,
link:
data.link?.href && data.link.title
? { href: data.link.href, text: data.link.title }
: undefined,
cards: data.cardConnection.edges.map((card) => {
if (card.node.__typename === CardsGridEnum.cards.InfoCard) {
return transformInfoCardBlock(card.node)
} else if (card.node.__typename === CardsGridEnum.cards.TeaserCard) {
return transformTeaserCardBlock(card.node)
} else if (
card.node.__typename === CardsGridEnum.cards.InfoCardWithImage
) {
return transformInfoCardWithImageBlock(card.node)
} else {
return {
__typename: card.node.__typename,
body_text: card.node.body_text,
heading: card.node.heading,
image: card.node.image,
link: card.node.link,
system: card.node.system,
title: card.node.title,
}
}
}),
}
}),
})
export const infoCardBlockRefsSchema = z.object({
__typename: z.literal(CardsGridEnum.cards.InfoCard),
primary_button: linkConnectionRefsSchema,
secondary_button: linkConnectionRefsSchema,
system: systemSchema,
})
export function transformCardBlockRefs(
card:
| typeof infoCardBlockRefsSchema._type
| typeof teaserCardBlockRefsSchema._type
| typeof infoCardWithImageBlockRefsSchema._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
}
export const cardGridRefsSchema = z.object({
cards_grid: z
.object({
cardConnection: z.object({
edges: z.array(
z.object({
node: z.discriminatedUnion("__typename", [
infoCardBlockRefsSchema,
loyaltyCardBlockRefsSchema,
teaserCardBlockRefsSchema,
infoCardWithImageBlockRefsSchema,
]),
})
),
}),
link: linkConnectionRefsSchema.nullish(),
})
.transform((data) => {
return data.cardConnection.edges
.map(({ node }) => {
if (
node.__typename === CardsGridEnum.cards.InfoCard ||
node.__typename === CardsGridEnum.cards.TeaserCard ||
node.__typename === CardsGridEnum.cards.InfoCardWithImage
) {
return transformCardBlockRefs(node)
} else {
const loyaltyCards = [node.system]
if (node.link) {
loyaltyCards.push(node.link)
}
return loyaltyCards
}
})
.flat()
}),
})
export function getInfoCardThemeFromDeprecatedCardTheme(theme?: string | null) {
if (!theme) {
return null
}
switch (theme) {
case "one":
return "Primary 1"
case "primaryDark":
return "Primary 3"
case "primaryDim":
return "Accent"
case "primaryInverted":
return "White"
case "primaryStrong":
return "Primary 2"
case "image":
return "Image"
case "two": // Doesn't exist anymore, map to Primary 1
case "three": // Doesn't exist anymore, map to Primary 1
default:
return "Primary 1"
}
}