feat(BOOK-743): Replaced deprecated Button component

Approved-by: Bianca Widstam
This commit is contained in:
Erik Tiekstra
2026-01-21 09:38:38 +00:00
parent f834433d4d
commit 8e08af718c
77 changed files with 575 additions and 2233 deletions

View File

@@ -11,10 +11,10 @@ import { nullableStringValidator } from "@scandic-hotels/common/utils/zod/string
import { discriminatedUnion } from "../../../utils/discriminatedUnion"
import {
cardBlockRefsSchema,
cardBlockSchema,
transformCardBlock,
infoCardBlockRefsSchema,
infoCardBlockSchema,
transformCardBlockRefs,
transformInfoCardBlock,
} from "../schemas/blocks/cardsGrid"
import { linkConnectionRefsSchema } from "../schemas/blocks/utils/linkConnection"
import {
@@ -300,7 +300,7 @@ const menuItemsRefsSchema = z.intersection(
cardConnection: z.object({
edges: z.array(
z.object({
node: cardBlockRefsSchema,
node: infoCardBlockRefsSchema,
})
),
}),
@@ -457,7 +457,7 @@ export const menuItemSchema = z
cardConnection: z.object({
edges: z.array(
z.object({
node: cardBlockSchema,
node: infoCardBlockSchema,
})
),
}),
@@ -472,7 +472,7 @@ export const menuItemSchema = z
.transform((data) => {
let card = null
if (data.cardConnection.edges.length) {
card = transformCardBlock(data.cardConnection.edges[0].node)
card = transformInfoCardBlock(data.cardConnection.edges[0].node)
}
return {

View File

@@ -4,10 +4,11 @@ import { transformedImageVaultAssetSchema } from "@scandic-hotels/common/utils/i
import { CardsEnum } from "../../../../../types/cardsEnum"
import { systemSchema } from "../../system"
import { getInfoCardThemeFromDeprecatedCardTheme } from "../cardsGrid"
import { buttonSchema } from "../utils/buttonLinkSchema"
import { linkConnectionRefsSchema } from "../utils/linkConnection"
const INFO_CARD_THEMES = [
const INFO_CARD_WITH_IMAGE_THEMES = [
"one",
"two",
"three",
@@ -15,38 +16,55 @@ const INFO_CARD_THEMES = [
"primaryStrong",
] as const
export const infoCardBlockSchema = z.object({
__typename: z.literal(CardsEnum.InfoCard),
export const infoCardWithImageBlockSchema = z.object({
__typename: z.literal(CardsEnum.InfoCardWithImage),
scripted_top_title: z.string().optional(),
heading: z.string().optional().default(""),
body_text: z.string().optional().default(""),
image: transformedImageVaultAssetSchema,
theme: z.enum(INFO_CARD_THEMES).nullable(),
theme: z
.enum(INFO_CARD_WITH_IMAGE_THEMES)
.nullable()
.transform(getInfoCardThemeFromDeprecatedCardTheme),
title: z.string().optional(),
primary_button: buttonSchema.optional().nullable(),
secondary_button: buttonSchema.optional().nullable(),
system: systemSchema,
})
export function transformInfoCardBlock(card: typeof infoCardBlockSchema._type) {
export function transformInfoCardWithImageBlock(
card: typeof infoCardWithImageBlockSchema._type
) {
return {
__typename: card.__typename,
scriptedTopTitle: card.scripted_top_title,
topTitle: card.scripted_top_title,
heading: card.heading,
bodyText: card.body_text,
image: card.image,
theme: card.theme,
title: card.title,
primaryButton: card.primary_button?.href ? card.primary_button : undefined,
primaryButton: card.primary_button?.href
? {
href: card.primary_button.href,
text: card.primary_button.title,
openInNewTab: card.primary_button.openInNewTab,
isExternal: card.primary_button.isExternal,
}
: undefined,
secondaryButton: card.secondary_button?.href
? card.secondary_button
? {
href: card.secondary_button.href,
text: card.secondary_button.title,
openInNewTab: card.secondary_button.openInNewTab,
isExternal: card.secondary_button.isExternal,
}
: undefined,
system: card.system,
}
}
export const infoCardBlockRefsSchema = z.object({
__typename: z.literal(CardsEnum.InfoCard),
export const infoCardWithImageBlockRefsSchema = z.object({
__typename: z.literal(CardsEnum.InfoCardWithImage),
primary_button: linkConnectionRefsSchema,
secondary_button: linkConnectionRefsSchema,
system: systemSchema,

View File

@@ -10,10 +10,10 @@ import {
} from "../../../../types/cardsGridEnum"
import { systemSchema } from "../system"
import {
infoCardBlockRefsSchema,
infoCardBlockSchema,
transformInfoCardBlock,
} from "./cards/infoCard"
infoCardWithImageBlockRefsSchema,
infoCardWithImageBlockSchema,
transformInfoCardWithImageBlock,
} from "./cards/infoCardWithImage"
import {
loyaltyCardBlockRefsSchema,
loyaltyCardBlockSchema,
@@ -26,8 +26,8 @@ import {
import { buttonSchema } from "./utils/buttonLinkSchema"
import { linkConnectionRefsSchema } from "./utils/linkConnection"
export const cardBlockSchema = z.object({
__typename: z.literal(CardsGridEnum.cards.Card),
export const infoCardBlockSchema = z.object({
__typename: z.literal(CardsGridEnum.cards.InfoCard),
// JSON - ImageVault Image
background_image: transformedImageVaultAssetSchema,
body_text: z.string().optional().default(""),
@@ -41,17 +41,36 @@ export const cardBlockSchema = z.object({
title: z.string().optional(),
})
export function transformCardBlock(card: typeof cardBlockSchema._type) {
export function transformInfoCardBlock(card: typeof infoCardBlockSchema._type) {
return {
__typename: card.__typename,
backgroundImage: card.background_image,
body_text: card.body_text,
heading: card.heading,
primaryButton: card.has_primary_button ? card.primary_button : undefined,
scripted_top_title: card.scripted_top_title,
secondaryButton: card.has_secondary_button
? card.secondary_button
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,
}
@@ -68,10 +87,10 @@ export const cardsGridSchema = z.object({
edges: z.array(
z.object({
node: z.discriminatedUnion("__typename", [
cardBlockSchema,
infoCardBlockSchema,
loyaltyCardBlockSchema,
teaserCardBlockSchema,
infoCardBlockSchema,
infoCardWithImageBlockSchema,
]),
})
),
@@ -80,7 +99,10 @@ export const cardsGridSchema = z.object({
layout: z.nativeEnum(CardsGridLayoutEnum),
preamble: z.string().optional().default(""),
theme: z.nativeEnum(scriptedCardThemeEnum).nullable(),
theme: z
.nativeEnum(scriptedCardThemeEnum)
.nullable()
.transform(getInfoCardThemeFromDeprecatedCardTheme),
title: z.string().optional().default(""),
})
.transform((data) => {
@@ -94,12 +116,14 @@ export const cardsGridSchema = z.object({
? { href: data.link.href, text: data.link.title }
: undefined,
cards: data.cardConnection.edges.map((card) => {
if (card.node.__typename === CardsGridEnum.cards.Card) {
return transformCardBlock(card.node)
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.InfoCard) {
return transformInfoCardBlock(card.node)
} else if (
card.node.__typename === CardsGridEnum.cards.InfoCardWithImage
) {
return transformInfoCardWithImageBlock(card.node)
} else {
return {
__typename: card.node.__typename,
@@ -116,8 +140,8 @@ export const cardsGridSchema = z.object({
}),
})
export const cardBlockRefsSchema = z.object({
__typename: z.literal(CardsGridEnum.cards.Card),
export const infoCardBlockRefsSchema = z.object({
__typename: z.literal(CardsGridEnum.cards.InfoCard),
primary_button: linkConnectionRefsSchema,
secondary_button: linkConnectionRefsSchema,
system: systemSchema,
@@ -125,9 +149,9 @@ export const cardBlockRefsSchema = z.object({
export function transformCardBlockRefs(
card:
| typeof cardBlockRefsSchema._type
| typeof teaserCardBlockRefsSchema._type
| typeof infoCardBlockRefsSchema._type
| typeof teaserCardBlockRefsSchema._type
| typeof infoCardWithImageBlockRefsSchema._type
) {
const cards = [card.system]
if (card.primary_button) {
@@ -146,10 +170,10 @@ export const cardGridRefsSchema = z.object({
edges: z.array(
z.object({
node: z.discriminatedUnion("__typename", [
cardBlockRefsSchema,
infoCardBlockRefsSchema,
loyaltyCardBlockRefsSchema,
teaserCardBlockRefsSchema,
infoCardBlockRefsSchema,
infoCardWithImageBlockRefsSchema,
]),
})
),
@@ -160,9 +184,9 @@ export const cardGridRefsSchema = z.object({
return data.cardConnection.edges
.map(({ node }) => {
if (
node.__typename === CardsGridEnum.cards.Card ||
node.__typename === CardsGridEnum.cards.InfoCard ||
node.__typename === CardsGridEnum.cards.TeaserCard ||
node.__typename === CardsGridEnum.cards.InfoCard
node.__typename === CardsGridEnum.cards.InfoCardWithImage
) {
return transformCardBlockRefs(node)
} else {
@@ -176,3 +200,28 @@ export const cardGridRefsSchema = z.object({
.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"
}
}

View File

@@ -3,24 +3,28 @@ import { z } from "zod"
import { scriptedCardThemeEnum } from "../../../../enums/scriptedCard"
import { SidebarEnums } from "../../../../types/sidebar"
import {
cardBlockRefsSchema,
cardBlockSchema,
transformCardBlock,
getInfoCardThemeFromDeprecatedCardTheme,
infoCardBlockRefsSchema,
infoCardBlockSchema,
transformCardBlockRefs,
transformInfoCardBlock,
} from "../blocks/cardsGrid"
export const scriptedCardsSchema = z.object({
typename: z
.literal(SidebarEnums.blocks.ScriptedCard)
.literal(SidebarEnums.blocks.InfoCard)
.optional()
.default(SidebarEnums.blocks.ScriptedCard),
.default(SidebarEnums.blocks.InfoCard),
scripted_card: z
.object({
theme: z.nativeEnum(scriptedCardThemeEnum).nullable(),
theme: z
.nativeEnum(scriptedCardThemeEnum)
.nullable()
.transform(getInfoCardThemeFromDeprecatedCardTheme),
scripted_cardConnection: z.object({
edges: z.array(
z.object({
node: cardBlockSchema,
node: infoCardBlockSchema,
})
),
}),
@@ -33,7 +37,7 @@ export const scriptedCardsSchema = z.object({
return {
theme: data.theme,
...transformCardBlock(data.scripted_cardConnection.edges[0].node),
...transformInfoCardBlock(data.scripted_cardConnection.edges[0].node),
}
}),
})
@@ -44,7 +48,7 @@ export const scriptedCardRefschema = z.object({
scripted_cardConnection: z.object({
edges: z.array(
z.object({
node: cardBlockRefsSchema,
node: infoCardBlockRefsSchema,
})
),
}),

View File

@@ -1,7 +1,7 @@
export const CardsEnum = {
Card: "Card",
InfoCard: "Card", // ContentType is Card, component is InfoCard
TeaserCard: "TeaserCard",
LoyaltyCard: "LoyaltyCard",
InfoCard: "InfoCard",
InfoCardWithImage: "InfoCard", // ContentType is InfoCard, component is InfoCardWithImage
ContentCard: "ContentCard",
} as const

View File

@@ -7,10 +7,10 @@ import { CardsEnum } from "./cardsEnum"
*/
export namespace CardsGridEnum {
export const cards = {
Card: CardsEnum.Card,
InfoCard: CardsEnum.InfoCard,
InfoCardWithImage: CardsEnum.InfoCardWithImage,
LoyaltyCard: CardsEnum.LoyaltyCard,
TeaserCard: CardsEnum.TeaserCard,
InfoCard: CardsEnum.InfoCard,
} as const satisfies Partial<typeof CardsEnum>
}

View File

@@ -3,7 +3,7 @@ export namespace SidebarEnums {
Content = "Content",
DynamicContent = "DynamicContent",
JoinLoyaltyContact = "JoinLoyaltyContact",
ScriptedCard = "ScriptedCard",
InfoCard = "ScriptedCard", // ContentType is ScriptedCard, component is InfoCard
TeaserCard = "TeaserCard",
QuickLinks = "QuickLinks",
}