Files
web/packages/trpc/lib/routers/contentstack/schemas/blocks/cardsGrid.ts
Linus Flood 5fc93472f4 Merged in feat/rework-contentstack (pull request #3493)
Feat(SW-3708): refactor contentstack fetching (removing all refs) and cache invalidation

* Remove all REFS

* Revalidate correct language

* PR fixes

* PR fixes

* Throw when errors from contentstack api


Approved-by: Joakim Jäderberg
2026-01-27 12:38:36 +00:00

161 lines
4.9 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 {
infoCardWithImageBlockSchema,
transformInfoCardWithImageBlock,
} from "./cards/infoCardWithImage"
import { loyaltyCardBlockSchema } from "./cards/loyaltyCard"
import {
teaserCardBlockSchema,
transformTeaserCardBlock,
} from "./cards/teaserCard"
import { buttonSchema } from "./utils/buttonLinkSchema"
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 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"
}
}