228 lines
6.7 KiB
TypeScript
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"
|
|
}
|
|
}
|