Merged in feat/sw-2863-move-contentstack-router-to-trpc-package (pull request #2389)
feat(SW-2863): Move contentstack router to trpc package * Add exports to packages and lint rule to prevent relative imports * Add env to trpc package * Add eslint to trpc package * Apply lint rules * Use direct imports from trpc package * Add lint-staged config to trpc * Move lang enum to common * Restructure trpc package folder structure * WIP first step * update internal imports in trpc * Fix most errors in scandic-web Just 100 left... * Move Props type out of trpc * Fix CategorizedFilters types * Move more schemas in hotel router * Fix deps * fix getNonContentstackUrls * Fix import error * Fix entry error handling * Fix generateMetadata metrics * Fix alertType enum * Fix duplicated types * lint:fix * Merge branch 'master' into feat/sw-2863-move-contentstack-router-to-trpc-package * Fix broken imports * Merge branch 'master' into feat/sw-2863-move-contentstack-router-to-trpc-package Approved-by: Linus Flood
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { BlocksEnums } from "../../../../types/blocks"
|
||||
import {
|
||||
linkRefsUnionSchema,
|
||||
linkUnionSchema,
|
||||
transformPageLink,
|
||||
} from "../pageLinks"
|
||||
import { sysAssetSchema } from "./sysAsset"
|
||||
|
||||
export const embeddedContentSchema = z.union([linkUnionSchema, sysAssetSchema])
|
||||
|
||||
export const accordionItemsSchema = z.array(
|
||||
z.object({
|
||||
question: z.string(),
|
||||
answer: z.object({
|
||||
json: z.any(), // JSON
|
||||
embedded_itemsConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: embeddedContentSchema.transform((data) => {
|
||||
const link = transformPageLink(data)
|
||||
if (link) {
|
||||
return link
|
||||
}
|
||||
return data
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
)
|
||||
|
||||
export type Accordion = z.infer<typeof accordionSchema>
|
||||
|
||||
enum AccordionEnum {
|
||||
CampaignPageBlocksAccordionBlockAccordionsGlobalAccordion = "CampaignPageBlocksAccordionBlockAccordionsGlobalAccordion",
|
||||
CampaignPageBlocksAccordionBlockAccordionsSpecificAccordion = "CampaignPageBlocksAccordionBlockAccordionsSpecificAccordion",
|
||||
ContentPageBlocksAccordionBlockAccordionsGlobalAccordion = "ContentPageBlocksAccordionBlockAccordionsGlobalAccordion",
|
||||
ContentPageBlocksAccordionBlockAccordionsSpecificAccordion = "ContentPageBlocksAccordionBlockAccordionsSpecificAccordion",
|
||||
DestinationCityPageBlocksAccordionBlockAccordionsGlobalAccordion = "DestinationCityPageBlocksAccordionBlockAccordionsGlobalAccordion",
|
||||
DestinationCityPageBlocksAccordionBlockAccordionsSpecificAccordion = "DestinationCityPageBlocksAccordionBlockAccordionsSpecificAccordion",
|
||||
DestinationCountryPageBlocksAccordionBlockAccordionsGlobalAccordion = "DestinationCountryPageBlocksAccordionBlockAccordionsGlobalAccordion",
|
||||
DestinationCountryPageBlocksAccordionBlockAccordionsSpecificAccordion = "DestinationCountryPageBlocksAccordionBlockAccordionsSpecificAccordion",
|
||||
}
|
||||
|
||||
export const accordionSchema = z.object({
|
||||
typename: z
|
||||
.literal(BlocksEnums.block.Accordion)
|
||||
.optional()
|
||||
.default(BlocksEnums.block.Accordion),
|
||||
accordion: z
|
||||
.object({
|
||||
title: z.string().optional().default(""),
|
||||
accordions: z.array(
|
||||
z.object({
|
||||
__typename: z.nativeEnum(AccordionEnum),
|
||||
global_accordion: z
|
||||
.object({
|
||||
global_accordionConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z.object({
|
||||
questions: accordionItemsSchema,
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
.optional(),
|
||||
specific_accordion: z
|
||||
.object({
|
||||
questions: accordionItemsSchema,
|
||||
})
|
||||
.optional(),
|
||||
})
|
||||
),
|
||||
})
|
||||
.transform((data) => {
|
||||
return {
|
||||
...data,
|
||||
accordions: data.accordions.flatMap((acc) => {
|
||||
switch (acc.__typename) {
|
||||
case AccordionEnum.CampaignPageBlocksAccordionBlockAccordionsGlobalAccordion:
|
||||
case AccordionEnum.ContentPageBlocksAccordionBlockAccordionsGlobalAccordion:
|
||||
case AccordionEnum.DestinationCityPageBlocksAccordionBlockAccordionsGlobalAccordion:
|
||||
case AccordionEnum.DestinationCountryPageBlocksAccordionBlockAccordionsGlobalAccordion:
|
||||
return (
|
||||
acc.global_accordion?.global_accordionConnection.edges.flatMap(
|
||||
({ node: accordionConnection }) => {
|
||||
return accordionConnection.questions
|
||||
}
|
||||
) || []
|
||||
)
|
||||
case AccordionEnum.CampaignPageBlocksAccordionBlockAccordionsSpecificAccordion:
|
||||
case AccordionEnum.ContentPageBlocksAccordionBlockAccordionsSpecificAccordion:
|
||||
case AccordionEnum.DestinationCityPageBlocksAccordionBlockAccordionsSpecificAccordion:
|
||||
case AccordionEnum.DestinationCountryPageBlocksAccordionBlockAccordionsSpecificAccordion:
|
||||
return acc.specific_accordion?.questions || []
|
||||
}
|
||||
}),
|
||||
}
|
||||
}),
|
||||
})
|
||||
|
||||
export const globalAccordionConnectionRefs = z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z.object({
|
||||
questions: z.array(
|
||||
z.object({
|
||||
answer: z.object({
|
||||
embedded_itemsConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: linkRefsUnionSchema,
|
||||
})
|
||||
),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
),
|
||||
})
|
||||
|
||||
export const specificAccordionConnectionRefs = z.object({
|
||||
questions: z.array(
|
||||
z.object({
|
||||
answer: z.object({
|
||||
embedded_itemsConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: linkRefsUnionSchema,
|
||||
})
|
||||
),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
),
|
||||
})
|
||||
|
||||
export const accordionRefsSchema = z.object({
|
||||
accordion: z
|
||||
.object({
|
||||
accordions: z.array(
|
||||
z.object({
|
||||
__typename: z.nativeEnum(AccordionEnum),
|
||||
global_accordion: z
|
||||
.object({
|
||||
global_accordionConnection: globalAccordionConnectionRefs,
|
||||
})
|
||||
.optional(),
|
||||
specific_accordion: specificAccordionConnectionRefs.optional(),
|
||||
})
|
||||
),
|
||||
})
|
||||
.transform((data) => {
|
||||
return data.accordions.flatMap((accordion) => {
|
||||
switch (accordion.__typename) {
|
||||
case AccordionEnum.CampaignPageBlocksAccordionBlockAccordionsGlobalAccordion:
|
||||
case AccordionEnum.ContentPageBlocksAccordionBlockAccordionsGlobalAccordion:
|
||||
case AccordionEnum.DestinationCityPageBlocksAccordionBlockAccordionsGlobalAccordion:
|
||||
case AccordionEnum.DestinationCountryPageBlocksAccordionBlockAccordionsGlobalAccordion:
|
||||
return (
|
||||
accordion.global_accordion?.global_accordionConnection.edges.flatMap(
|
||||
({ node: accordionConnection }) => {
|
||||
return accordionConnection.questions.flatMap((question) =>
|
||||
question.answer.embedded_itemsConnection.edges.flatMap(
|
||||
({ node }) => node.system
|
||||
)
|
||||
)
|
||||
}
|
||||
) || []
|
||||
)
|
||||
case AccordionEnum.CampaignPageBlocksAccordionBlockAccordionsSpecificAccordion:
|
||||
case AccordionEnum.DestinationCityPageBlocksAccordionBlockAccordionsSpecificAccordion:
|
||||
case AccordionEnum.DestinationCountryPageBlocksAccordionBlockAccordionsSpecificAccordion:
|
||||
return (
|
||||
accordion.specific_accordion?.questions.flatMap((question) =>
|
||||
question.answer.embedded_itemsConnection.edges.flatMap(
|
||||
({ node }) => node.system
|
||||
)
|
||||
) || []
|
||||
)
|
||||
default:
|
||||
return []
|
||||
}
|
||||
})
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,82 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { removeMultipleSlashes } from "@scandic-hotels/common/utils/url"
|
||||
|
||||
import { HotelPageEnum } from "../../../../types/hotelPageEnum"
|
||||
import { tempImageVaultAssetSchema } from "../imageVault"
|
||||
import { contentPageRefSchema, contentPageSchema } from "../pageLinks"
|
||||
|
||||
export const activitiesCardSchema = z.object({
|
||||
typename: z
|
||||
.literal(HotelPageEnum.ContentStack.blocks.ActivitiesCard)
|
||||
.optional()
|
||||
.default(HotelPageEnum.ContentStack.blocks.ActivitiesCard),
|
||||
upcoming_activities_card: z
|
||||
.object({
|
||||
background_image: tempImageVaultAssetSchema,
|
||||
body_text: z.string(),
|
||||
cta_text: z.string(),
|
||||
sidepeek_cta_text: z.string(),
|
||||
heading: z.string(),
|
||||
scripted_title: z.string().optional(),
|
||||
sidepeek_slug: z.string(),
|
||||
hotel_page_activities_content_pageConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z.discriminatedUnion("__typename", [
|
||||
contentPageSchema.extend({
|
||||
header: z.object({
|
||||
preamble: z.string(),
|
||||
}),
|
||||
}),
|
||||
]),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
let contentPage = { href: "", preamble: "" }
|
||||
if (data.hotel_page_activities_content_pageConnection.edges.length) {
|
||||
const page =
|
||||
data.hotel_page_activities_content_pageConnection.edges[0].node
|
||||
contentPage.preamble = page.header.preamble
|
||||
if (page.web.original_url) {
|
||||
contentPage.href = page.web.original_url
|
||||
} else {
|
||||
contentPage.href = removeMultipleSlashes(
|
||||
`/${page.system.locale}/${page.url}`
|
||||
)
|
||||
}
|
||||
}
|
||||
return {
|
||||
backgroundImage: data.background_image,
|
||||
bodyText: data.body_text,
|
||||
contentPage,
|
||||
ctaText: data.cta_text,
|
||||
sidepeekCtaText: data.sidepeek_cta_text,
|
||||
sidepeekSlug: data.sidepeek_slug,
|
||||
heading: data.heading,
|
||||
scriptedTopTitle: data.scripted_title,
|
||||
}
|
||||
}),
|
||||
})
|
||||
|
||||
export const activitiesCardRefSchema = z.object({
|
||||
upcoming_activities_card: z
|
||||
.object({
|
||||
hotel_page_activities_content_pageConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z.discriminatedUnion("__typename", [contentPageRefSchema]),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
return (
|
||||
data.hotel_page_activities_content_pageConnection.edges.flatMap(
|
||||
({ node }) => node.system
|
||||
) || []
|
||||
)
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,100 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { BlocksEnums } from "../../../../types/blocks"
|
||||
import {
|
||||
contentCardRefSchema,
|
||||
contentCardSchema,
|
||||
transformContentCard,
|
||||
} from "./cards/contentCard"
|
||||
import { buttonSchema } from "./utils/buttonLinkSchema"
|
||||
import { linkConnectionRefsSchema } from "./utils/linkConnection"
|
||||
|
||||
export const cardGallerySchema = z.object({
|
||||
typename: z
|
||||
.literal(BlocksEnums.block.CardGallery)
|
||||
.optional()
|
||||
.default(BlocksEnums.block.CardGallery),
|
||||
card_gallery: z
|
||||
.object({
|
||||
heading: z.string().optional(),
|
||||
link: buttonSchema.optional(),
|
||||
card_groups: z
|
||||
.array(
|
||||
z
|
||||
.object({
|
||||
filter_identifier: z.string().nullish(),
|
||||
filter_label: z.string().nullish(),
|
||||
cardsConnection: z.object({
|
||||
edges: z.array(z.object({ node: contentCardSchema })),
|
||||
}),
|
||||
})
|
||||
.transform((group) => {
|
||||
if (!group.filter_label || !group.cardsConnection.edges.length) {
|
||||
return null
|
||||
}
|
||||
|
||||
const iconIdentifier = group.filter_identifier ?? "favorite"
|
||||
const identifier = `${group.filter_label.toLowerCase()}-${iconIdentifier}`
|
||||
const cards = group.cardsConnection.edges
|
||||
.map((edge) => transformContentCard(edge.node))
|
||||
.filter(
|
||||
(card): card is NonNullable<typeof card> => card !== null
|
||||
)
|
||||
.map((card) => ({
|
||||
...card,
|
||||
filterId: identifier,
|
||||
}))
|
||||
return {
|
||||
label: group.filter_label,
|
||||
iconIdentifier,
|
||||
identifier,
|
||||
cards,
|
||||
}
|
||||
})
|
||||
)
|
||||
.transform((groups) =>
|
||||
groups.filter(
|
||||
(group): group is NonNullable<typeof group> => group !== null
|
||||
)
|
||||
),
|
||||
})
|
||||
.transform((data) => {
|
||||
const filterCategories = data.card_groups.map((group) => ({
|
||||
identifier: group.identifier,
|
||||
iconIdentifier: group.iconIdentifier,
|
||||
label: group.label,
|
||||
}))
|
||||
|
||||
return {
|
||||
heading: data.heading,
|
||||
filterCategories,
|
||||
cards: data.card_groups.map((group) => group.cards).flat(),
|
||||
defaultFilter: filterCategories[0]?.identifier,
|
||||
link:
|
||||
data.link?.href && data.link.title
|
||||
? { href: data.link.href, text: data.link.title }
|
||||
: undefined,
|
||||
}
|
||||
}),
|
||||
})
|
||||
|
||||
export const cardGalleryRefsSchema = z.object({
|
||||
typename: z
|
||||
.literal(BlocksEnums.block.CardGallery)
|
||||
.optional()
|
||||
.default(BlocksEnums.block.CardGallery),
|
||||
card_gallery: z.object({
|
||||
card_groups: z.array(
|
||||
z.object({
|
||||
cardsConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: contentCardRefSchema,
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
),
|
||||
link: linkConnectionRefsSchema.optional(),
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,46 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { CardsEnum } from "../../../../../types/cardsEnum"
|
||||
import { tempImageVaultAssetSchema } from "../../imageVault"
|
||||
import { systemSchema } from "../../system"
|
||||
import { buttonSchema } from "../utils/buttonLinkSchema"
|
||||
import { linkConnectionRefsSchema } from "../utils/linkConnection"
|
||||
|
||||
export const contentCardSchema = z.object({
|
||||
__typename: z.literal(CardsEnum.ContentCard),
|
||||
title: z.string(),
|
||||
heading: z.string(),
|
||||
image: tempImageVaultAssetSchema,
|
||||
body_text: z.string(),
|
||||
promo_text: z.string().optional(),
|
||||
has_card_link: z.boolean(),
|
||||
card_link: buttonSchema,
|
||||
system: systemSchema,
|
||||
})
|
||||
|
||||
export const contentCardRefSchema = z.object({
|
||||
__typename: z.literal(CardsEnum.ContentCard),
|
||||
card_link: linkConnectionRefsSchema,
|
||||
system: systemSchema,
|
||||
})
|
||||
|
||||
export function transformContentCard(card: typeof contentCardSchema._type) {
|
||||
// Return null if image or image URL is missing
|
||||
if (!card.image?.url) return null
|
||||
|
||||
return {
|
||||
__typename: card.__typename,
|
||||
title: card.title,
|
||||
heading: card.heading,
|
||||
image: card.image,
|
||||
bodyText: card.body_text,
|
||||
promoText: card.promo_text,
|
||||
link: card.has_card_link
|
||||
? {
|
||||
href: card.card_link.href,
|
||||
openInNewTab: card.card_link.openInNewTab,
|
||||
isExternal: card.card_link.isExternal,
|
||||
}
|
||||
: undefined,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { CardsEnum } from "../../../../../types/cardsEnum"
|
||||
import { tempImageVaultAssetSchema } from "../../imageVault"
|
||||
import { systemSchema } from "../../system"
|
||||
import { buttonSchema } from "../utils/buttonLinkSchema"
|
||||
import { linkConnectionRefsSchema } from "../utils/linkConnection"
|
||||
|
||||
const INFO_CARD_THEMES = [
|
||||
"one",
|
||||
"two",
|
||||
"three",
|
||||
"primaryInverted",
|
||||
"primaryStrong",
|
||||
] as const
|
||||
|
||||
export const infoCardBlockSchema = z.object({
|
||||
__typename: z.literal(CardsEnum.InfoCard),
|
||||
scripted_top_title: z.string().optional(),
|
||||
heading: z.string().optional().default(""),
|
||||
body_text: z.string().optional().default(""),
|
||||
image: tempImageVaultAssetSchema,
|
||||
theme: z.enum(INFO_CARD_THEMES).nullable(),
|
||||
title: z.string().optional(),
|
||||
primary_button: buttonSchema.optional().nullable(),
|
||||
secondary_button: buttonSchema.optional().nullable(),
|
||||
system: systemSchema,
|
||||
})
|
||||
|
||||
export function transformInfoCardBlock(card: typeof infoCardBlockSchema._type) {
|
||||
return {
|
||||
__typename: card.__typename,
|
||||
scriptedTopTitle: 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,
|
||||
secondaryButton: card.secondary_button?.href
|
||||
? card.secondary_button
|
||||
: undefined,
|
||||
system: card.system,
|
||||
}
|
||||
}
|
||||
|
||||
export const infoCardBlockRefsSchema = z.object({
|
||||
__typename: z.literal(CardsEnum.InfoCard),
|
||||
primary_button: linkConnectionRefsSchema,
|
||||
secondary_button: linkConnectionRefsSchema,
|
||||
system: systemSchema,
|
||||
})
|
||||
@@ -0,0 +1,24 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { CardsEnum } from "../../../../../types/cardsEnum"
|
||||
import { tempImageVaultAssetSchema } from "../../imageVault"
|
||||
import { systemSchema } from "../../system"
|
||||
import { buttonSchema } from "../utils/buttonLinkSchema"
|
||||
import { linkConnectionRefsSchema } from "../utils/linkConnection"
|
||||
|
||||
export const loyaltyCardBlockSchema = z.object({
|
||||
__typename: z.literal(CardsEnum.LoyaltyCard),
|
||||
body_text: z.string().optional(),
|
||||
heading: z.string().optional().default(""),
|
||||
// JSON - ImageVault Image
|
||||
image: tempImageVaultAssetSchema,
|
||||
link: buttonSchema,
|
||||
system: systemSchema,
|
||||
title: z.string().optional(),
|
||||
})
|
||||
|
||||
export const loyaltyCardBlockRefsSchema = z.object({
|
||||
__typename: z.literal(CardsEnum.LoyaltyCard),
|
||||
link: linkConnectionRefsSchema,
|
||||
system: systemSchema,
|
||||
})
|
||||
@@ -0,0 +1,120 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { CardsEnum } from "../../../../../types/cardsEnum"
|
||||
import { tempImageVaultAssetSchema } from "../../imageVault"
|
||||
import {
|
||||
accountPageSchema,
|
||||
collectionPageSchema,
|
||||
contentPageSchema,
|
||||
destinationCityPageSchema,
|
||||
destinationCountryPageSchema,
|
||||
destinationOverviewPageSchema,
|
||||
hotelPageSchema,
|
||||
loyaltyPageSchema,
|
||||
startPageSchema,
|
||||
transformPageLink,
|
||||
} from "../../pageLinks"
|
||||
import { systemSchema } from "../../system"
|
||||
import { imageContainerSchema } from "../imageContainer"
|
||||
import { sysAssetSchema } from "../sysAsset"
|
||||
import { buttonSchema } from "../utils/buttonLinkSchema"
|
||||
import { linkConnectionRefsSchema } from "../utils/linkConnection"
|
||||
|
||||
export const teaserCardBlockSchema = z.object({
|
||||
__typename: z.literal(CardsEnum.TeaserCard),
|
||||
heading: z.string().default(""),
|
||||
body_text: z.string().default(""),
|
||||
image: tempImageVaultAssetSchema,
|
||||
primary_button: buttonSchema,
|
||||
secondary_button: buttonSchema,
|
||||
has_primary_button: z.boolean().default(false),
|
||||
has_secondary_button: z.boolean().default(false),
|
||||
has_sidepeek_button: z.boolean().default(false),
|
||||
sidepeek_button: z
|
||||
.object({
|
||||
call_to_action_text: z.string().optional().default(""),
|
||||
})
|
||||
.optional(),
|
||||
sidepeek_content: z
|
||||
.object({
|
||||
heading: z.string(),
|
||||
content: z.object({
|
||||
json: z.any(),
|
||||
embedded_itemsConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z
|
||||
.discriminatedUnion("__typename", [
|
||||
imageContainerSchema,
|
||||
sysAssetSchema,
|
||||
accountPageSchema,
|
||||
collectionPageSchema,
|
||||
contentPageSchema,
|
||||
destinationCityPageSchema,
|
||||
destinationCountryPageSchema,
|
||||
destinationOverviewPageSchema,
|
||||
hotelPageSchema,
|
||||
loyaltyPageSchema,
|
||||
startPageSchema,
|
||||
])
|
||||
.transform((data) => {
|
||||
const link = transformPageLink(data)
|
||||
if (link) {
|
||||
return link
|
||||
}
|
||||
return data
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
}),
|
||||
has_primary_button: z.boolean().default(false),
|
||||
primary_button: buttonSchema,
|
||||
has_secondary_button: z.boolean().default(false),
|
||||
secondary_button: buttonSchema,
|
||||
})
|
||||
.optional()
|
||||
.transform((data) => {
|
||||
if (!data) {
|
||||
return
|
||||
}
|
||||
|
||||
return {
|
||||
...data,
|
||||
primary_button: data.has_primary_button
|
||||
? data.primary_button
|
||||
: undefined,
|
||||
secondary_button: data.has_secondary_button
|
||||
? data.secondary_button
|
||||
: undefined,
|
||||
}
|
||||
}),
|
||||
system: systemSchema,
|
||||
})
|
||||
|
||||
export function transformTeaserCardBlock(
|
||||
card: typeof teaserCardBlockSchema._type
|
||||
) {
|
||||
return {
|
||||
__typename: card.__typename,
|
||||
body_text: card.body_text,
|
||||
heading: card.heading,
|
||||
primaryButton: card.has_primary_button ? card.primary_button : undefined,
|
||||
secondaryButton: card.has_secondary_button
|
||||
? card.secondary_button
|
||||
: undefined,
|
||||
sidePeekButton: card.has_sidepeek_button ? card.sidepeek_button : undefined,
|
||||
sidePeekContent: card.has_sidepeek_button
|
||||
? card.sidepeek_content
|
||||
: undefined,
|
||||
image: card.image,
|
||||
system: card.system,
|
||||
}
|
||||
}
|
||||
|
||||
export const teaserCardBlockRefsSchema = z.object({
|
||||
__typename: z.literal(CardsEnum.TeaserCard),
|
||||
primary_button: linkConnectionRefsSchema,
|
||||
secondary_button: linkConnectionRefsSchema,
|
||||
system: systemSchema,
|
||||
})
|
||||
@@ -0,0 +1,170 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { scriptedCardThemeEnum } from "../../../../enums/scriptedCard"
|
||||
import { BlocksEnums } from "../../../../types/blocks"
|
||||
import {
|
||||
CardsGridEnum,
|
||||
CardsGridLayoutEnum,
|
||||
} from "../../../../types/cardsGridEnum"
|
||||
import { tempImageVaultAssetSchema } from "../imageVault"
|
||||
import { systemSchema } from "../system"
|
||||
import {
|
||||
infoCardBlockRefsSchema,
|
||||
infoCardBlockSchema,
|
||||
transformInfoCardBlock,
|
||||
} from "./cards/infoCard"
|
||||
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 cardBlockSchema = z.object({
|
||||
__typename: z.literal(CardsGridEnum.cards.Card),
|
||||
// JSON - ImageVault Image
|
||||
background_image: tempImageVaultAssetSchema,
|
||||
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 transformCardBlock(card: typeof cardBlockSchema._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
|
||||
: 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", [
|
||||
cardBlockSchema,
|
||||
loyaltyCardBlockSchema,
|
||||
teaserCardBlockSchema,
|
||||
infoCardBlockSchema,
|
||||
]),
|
||||
})
|
||||
),
|
||||
}),
|
||||
layout: z.nativeEnum(CardsGridLayoutEnum),
|
||||
preamble: z.string().optional().default(""),
|
||||
theme: z.nativeEnum(scriptedCardThemeEnum).nullable(),
|
||||
title: z.string().optional().default(""),
|
||||
})
|
||||
.transform((data) => {
|
||||
return {
|
||||
layout: data.layout,
|
||||
preamble: data.preamble,
|
||||
theme: data.theme,
|
||||
title: data.title,
|
||||
cards: data.cardConnection.edges.map((card) => {
|
||||
if (card.node.__typename === CardsGridEnum.cards.Card) {
|
||||
return transformCardBlock(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 {
|
||||
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 cardBlockRefsSchema = z.object({
|
||||
__typename: z.literal(CardsGridEnum.cards.Card),
|
||||
primary_button: linkConnectionRefsSchema,
|
||||
secondary_button: linkConnectionRefsSchema,
|
||||
system: systemSchema,
|
||||
})
|
||||
|
||||
export function transformCardBlockRefs(
|
||||
card:
|
||||
| typeof cardBlockRefsSchema._type
|
||||
| typeof teaserCardBlockRefsSchema._type
|
||||
| typeof infoCardBlockRefsSchema._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", [
|
||||
cardBlockRefsSchema,
|
||||
loyaltyCardBlockRefsSchema,
|
||||
teaserCardBlockRefsSchema,
|
||||
infoCardBlockRefsSchema,
|
||||
]),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
return data.cardConnection.edges
|
||||
.map(({ node }) => {
|
||||
if (
|
||||
node.__typename === CardsGridEnum.cards.Card ||
|
||||
node.__typename === CardsGridEnum.cards.TeaserCard ||
|
||||
node.__typename === CardsGridEnum.cards.InfoCard
|
||||
) {
|
||||
return transformCardBlockRefs(node)
|
||||
} else {
|
||||
const loyaltyCards = [node.system]
|
||||
if (node.link) {
|
||||
loyaltyCards.push(node.link)
|
||||
}
|
||||
return loyaltyCards
|
||||
}
|
||||
})
|
||||
.flat()
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,154 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { BlocksEnums } from "../../../../types/blocks"
|
||||
import {
|
||||
contentCardRefSchema,
|
||||
contentCardSchema,
|
||||
transformContentCard,
|
||||
} from "./cards/contentCard"
|
||||
import { buttonSchema } from "./utils/buttonLinkSchema"
|
||||
import { linkConnectionRefsSchema } from "./utils/linkConnection"
|
||||
|
||||
const commonFields = {
|
||||
heading: z.string().optional(),
|
||||
link: buttonSchema.nullish(),
|
||||
} as const
|
||||
|
||||
const carouselCardGroupsFilteredSchema = z
|
||||
.array(
|
||||
z
|
||||
.object({
|
||||
filter_identifier: z.string().nullish(),
|
||||
filter_label: z.string().nullish(),
|
||||
cardConnection: z.object({
|
||||
edges: z.array(z.object({ node: contentCardSchema })),
|
||||
}),
|
||||
})
|
||||
.transform((group) => {
|
||||
if (!group.filter_label || !group.cardConnection.edges.length) {
|
||||
return null
|
||||
}
|
||||
const iconIdentifier = group.filter_identifier ?? "favorite"
|
||||
const identifier = `${group.filter_label.toLowerCase()}-${iconIdentifier}`
|
||||
const cards = group.cardConnection.edges
|
||||
.map((edge) => transformContentCard(edge.node))
|
||||
.filter((card): card is NonNullable<typeof card> => card !== null)
|
||||
.map((card) => ({
|
||||
...card,
|
||||
filterId: identifier,
|
||||
}))
|
||||
return {
|
||||
label: group.filter_label,
|
||||
iconIdentifier,
|
||||
identifier,
|
||||
cards,
|
||||
}
|
||||
})
|
||||
)
|
||||
.transform((groups) =>
|
||||
groups.filter((group): group is NonNullable<typeof group> => group !== null)
|
||||
)
|
||||
|
||||
const carouselCardGroupsNoFilterSchema = z
|
||||
.array(
|
||||
z
|
||||
.object({
|
||||
cardConnection: z.object({
|
||||
edges: z.array(z.object({ node: contentCardSchema })),
|
||||
}),
|
||||
})
|
||||
.transform((group) => {
|
||||
if (!group.cardConnection.edges.length) {
|
||||
return null
|
||||
}
|
||||
const cards = group.cardConnection.edges
|
||||
.map((edge) => transformContentCard(edge.node))
|
||||
.filter((card): card is NonNullable<typeof card> => card !== null)
|
||||
.map((card) => ({
|
||||
...card,
|
||||
}))
|
||||
return {
|
||||
cards,
|
||||
}
|
||||
})
|
||||
)
|
||||
.transform((groups) =>
|
||||
groups.filter((group): group is NonNullable<typeof group> => group !== null)
|
||||
)
|
||||
|
||||
const carouselCardsWithFilters = z.object({
|
||||
...commonFields,
|
||||
enable_filters: z.literal(true),
|
||||
card_groups: carouselCardGroupsFilteredSchema,
|
||||
})
|
||||
|
||||
const carouselCardsWithoutFilters = z.object({
|
||||
...commonFields,
|
||||
enable_filters: z.literal(false),
|
||||
card_groups: carouselCardGroupsNoFilterSchema,
|
||||
})
|
||||
|
||||
export const carouselCardsSchema = z.object({
|
||||
typename: z
|
||||
.literal(BlocksEnums.block.CarouselCards)
|
||||
.optional()
|
||||
.default(BlocksEnums.block.CarouselCards),
|
||||
carousel_cards: z
|
||||
.discriminatedUnion("enable_filters", [
|
||||
carouselCardsWithFilters,
|
||||
carouselCardsWithoutFilters,
|
||||
])
|
||||
.transform((data) => {
|
||||
if (!data.enable_filters) {
|
||||
return {
|
||||
heading: data.heading,
|
||||
enableFilters: false,
|
||||
filterCategories: [],
|
||||
cards: data.card_groups.map((group) => group.cards).flat(),
|
||||
link:
|
||||
data.link?.href && data.link.title
|
||||
? { href: data.link.href, text: data.link.title }
|
||||
: undefined,
|
||||
}
|
||||
}
|
||||
|
||||
const filterCategories = data.card_groups.map((group) => ({
|
||||
identifier: group.identifier,
|
||||
iconIdentifier: group.iconIdentifier,
|
||||
label: group.label,
|
||||
}))
|
||||
|
||||
return {
|
||||
heading: data.heading,
|
||||
enableFilters: true,
|
||||
filterCategories,
|
||||
cards: data.card_groups.map((group) => group.cards).flat(),
|
||||
defaultFilter: filterCategories[0]?.identifier,
|
||||
link:
|
||||
data.link?.href && data.link.title
|
||||
? { href: data.link.href, text: data.link.title }
|
||||
: undefined,
|
||||
}
|
||||
}),
|
||||
})
|
||||
|
||||
export const carouselCardsRefsSchema = z.object({
|
||||
typename: z
|
||||
.literal(BlocksEnums.block.CarouselCards)
|
||||
.optional()
|
||||
.default(BlocksEnums.block.CarouselCards),
|
||||
carousel_cards: z.object({
|
||||
card_groups: z.array(
|
||||
z.object({
|
||||
cardConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: contentCardRefSchema,
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
),
|
||||
link: linkConnectionRefsSchema.nullish(),
|
||||
}),
|
||||
})
|
||||
102
packages/trpc/lib/routers/contentstack/schemas/blocks/content.ts
Normal file
102
packages/trpc/lib/routers/contentstack/schemas/blocks/content.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { BlocksEnums } from "../../../../types/blocks"
|
||||
import { ContentEnum } from "../../../../types/content"
|
||||
import {
|
||||
accountPageSchema,
|
||||
collectionPageSchema,
|
||||
contentPageSchema,
|
||||
destinationCityPageSchema,
|
||||
destinationCountryPageSchema,
|
||||
destinationOverviewPageSchema,
|
||||
hotelPageSchema,
|
||||
loyaltyPageSchema,
|
||||
startPageSchema,
|
||||
transformPageLink,
|
||||
} from "../pageLinks"
|
||||
import {
|
||||
imageContainerRefsSchema,
|
||||
imageContainerSchema,
|
||||
} from "./imageContainer"
|
||||
import { sysAssetRefsSchema, sysAssetSchema } from "./sysAsset"
|
||||
|
||||
export const contentSchema = z.object({
|
||||
typename: z
|
||||
.literal(BlocksEnums.block.Content)
|
||||
.optional()
|
||||
.default(BlocksEnums.block.Content),
|
||||
content: z
|
||||
.object({
|
||||
content: z.object({
|
||||
json: z.any(), // JSON
|
||||
embedded_itemsConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z
|
||||
.discriminatedUnion("__typename", [
|
||||
imageContainerSchema,
|
||||
sysAssetSchema,
|
||||
accountPageSchema,
|
||||
collectionPageSchema,
|
||||
contentPageSchema,
|
||||
destinationCityPageSchema,
|
||||
destinationCountryPageSchema,
|
||||
destinationOverviewPageSchema,
|
||||
hotelPageSchema,
|
||||
loyaltyPageSchema,
|
||||
startPageSchema,
|
||||
])
|
||||
.transform((data) => {
|
||||
const link = transformPageLink(data)
|
||||
if (link) {
|
||||
return link
|
||||
}
|
||||
return data
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
return data.content
|
||||
}),
|
||||
})
|
||||
|
||||
export const contentRefsSchema = z.object({
|
||||
content: z
|
||||
.object({
|
||||
content: z.object({
|
||||
embedded_itemsConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z.discriminatedUnion("__typename", [
|
||||
sysAssetRefsSchema,
|
||||
imageContainerRefsSchema,
|
||||
accountPageSchema,
|
||||
collectionPageSchema,
|
||||
contentPageSchema,
|
||||
destinationCityPageSchema,
|
||||
destinationCountryPageSchema,
|
||||
destinationOverviewPageSchema,
|
||||
hotelPageSchema,
|
||||
loyaltyPageSchema,
|
||||
startPageSchema,
|
||||
]),
|
||||
})
|
||||
),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
return data.content.embedded_itemsConnection.edges
|
||||
.filter(({ node }) => node.__typename !== ContentEnum.blocks.SysAsset)
|
||||
.map(({ node }) => {
|
||||
if ("system" in node) {
|
||||
return node.system
|
||||
}
|
||||
return null
|
||||
})
|
||||
.filter((node) => !!node)
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,42 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import {
|
||||
accountPageSchema,
|
||||
campaignOverviewPageSchema,
|
||||
campaignPageSchema,
|
||||
collectionPageSchema,
|
||||
contentPageSchema,
|
||||
destinationCityPageSchema,
|
||||
destinationCountryPageSchema,
|
||||
destinationOverviewPageSchema,
|
||||
hotelPageSchema,
|
||||
loyaltyPageSchema,
|
||||
startPageSchema,
|
||||
transformPageLink,
|
||||
} from "../pageLinks"
|
||||
import { imageContainerSchema } from "./imageContainer"
|
||||
import { sysAssetSchema } from "./sysAsset"
|
||||
|
||||
export const contentEmbedsSchema = z
|
||||
.discriminatedUnion("__typename", [
|
||||
imageContainerSchema,
|
||||
sysAssetSchema,
|
||||
accountPageSchema,
|
||||
campaignOverviewPageSchema,
|
||||
campaignPageSchema,
|
||||
collectionPageSchema,
|
||||
contentPageSchema,
|
||||
destinationCityPageSchema,
|
||||
destinationCountryPageSchema,
|
||||
destinationOverviewPageSchema,
|
||||
hotelPageSchema,
|
||||
loyaltyPageSchema,
|
||||
startPageSchema,
|
||||
])
|
||||
.transform((data) => {
|
||||
const link = transformPageLink(data)
|
||||
if (link) {
|
||||
return link
|
||||
}
|
||||
return data
|
||||
})
|
||||
@@ -0,0 +1,70 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { BlocksEnums } from "../../../../types/blocks"
|
||||
import { DynamicContentEnum } from "../../../../types/dynamicContent"
|
||||
import {
|
||||
linkRefsUnionSchema,
|
||||
linkUnionSchema,
|
||||
transformPageLink,
|
||||
} from "../pageLinks"
|
||||
|
||||
export const dynamicContentSchema = z.object({
|
||||
typename: z
|
||||
.literal(BlocksEnums.block.DynamicContent)
|
||||
.optional()
|
||||
.default(BlocksEnums.block.DynamicContent),
|
||||
dynamic_content: z.object({
|
||||
component: z.enum(DynamicContentEnum.Blocks.enums),
|
||||
subtitle: z.string().optional().default(""),
|
||||
title: z.string().optional().default(""),
|
||||
link: z
|
||||
.object({
|
||||
text: z.string().optional().default(""),
|
||||
linkConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: linkUnionSchema.transform((data) => {
|
||||
const link = transformPageLink(data)
|
||||
if (link) {
|
||||
return link
|
||||
}
|
||||
return data
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
if (data.linkConnection?.edges.length) {
|
||||
const link = data.linkConnection.edges?.[0]?.node
|
||||
return {
|
||||
href: link.url,
|
||||
text: data.text,
|
||||
title: link.title,
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}),
|
||||
}),
|
||||
})
|
||||
|
||||
export const dynamicContentRefsSchema = z.object({
|
||||
dynamic_content: z.object({
|
||||
link: z
|
||||
.object({
|
||||
linkConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: linkRefsUnionSchema,
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
if (data.linkConnection?.edges.length) {
|
||||
return data.linkConnection.edges[0].node.system
|
||||
}
|
||||
return null
|
||||
}),
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,26 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { BlocksEnums } from "../../../../types/blocks"
|
||||
|
||||
export const essentialsSchema = z.object({
|
||||
essentials: z.object({
|
||||
title: z.string(),
|
||||
preamble: z.string().nullish(),
|
||||
items: z.array(
|
||||
z.object({
|
||||
label: z.string(),
|
||||
icon_identifier: z.string(),
|
||||
description: z.string().nullish(),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
|
||||
export const essentialsBlockSchema = z
|
||||
.object({
|
||||
typename: z
|
||||
.literal(BlocksEnums.block.Essentials)
|
||||
.optional()
|
||||
.default(BlocksEnums.block.Essentials),
|
||||
})
|
||||
.merge(essentialsSchema)
|
||||
@@ -0,0 +1,63 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import * as pageLinks from "../../../../routers/contentstack/schemas/pageLinks"
|
||||
import { BlocksEnums } from "../../../../types/blocks"
|
||||
import { tempImageVaultAssetSchema } from "../imageVault"
|
||||
import { systemSchema } from "../system"
|
||||
import { buttonSchema } from "./utils/buttonLinkSchema"
|
||||
|
||||
export const fullWidthCampaignSchema = z.object({
|
||||
full_width_campaign: z
|
||||
.object({
|
||||
full_width_campaignConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z.object({
|
||||
background_image: tempImageVaultAssetSchema,
|
||||
heading: z.string().optional(),
|
||||
body_text: z.string().optional(),
|
||||
scripted_top_title: z.string().optional(),
|
||||
has_primary_button: z.boolean().default(false),
|
||||
primary_button: buttonSchema,
|
||||
has_secondary_button: z.boolean().default(false),
|
||||
secondary_button: buttonSchema,
|
||||
system: systemSchema,
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
return data.full_width_campaignConnection.edges[0]?.node || null
|
||||
}),
|
||||
})
|
||||
|
||||
export const fullWidthCampaignBlockSchema = z
|
||||
.object({
|
||||
typename: z
|
||||
.literal(BlocksEnums.block.FullWidthCampaign)
|
||||
.optional()
|
||||
.default(BlocksEnums.block.FullWidthCampaign),
|
||||
})
|
||||
.merge(fullWidthCampaignSchema)
|
||||
|
||||
export const fullWidthCampaignBlockRefsSchema = z.object({
|
||||
full_width_campaign: z.object({
|
||||
full_width_campaignConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z.discriminatedUnion("__typename", [
|
||||
pageLinks.accountPageRefSchema,
|
||||
pageLinks.contentPageRefSchema,
|
||||
pageLinks.loyaltyPageRefSchema,
|
||||
pageLinks.collectionPageRefSchema,
|
||||
pageLinks.hotelPageRefSchema,
|
||||
pageLinks.destinationCityPageRefSchema,
|
||||
pageLinks.destinationCountryPageRefSchema,
|
||||
pageLinks.destinationOverviewPageRefSchema,
|
||||
]),
|
||||
})
|
||||
),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,75 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { BlocksEnums } from "../../../../types/blocks"
|
||||
import { HotelPageEnum } from "../../../../types/hotelPageEnum"
|
||||
import {
|
||||
accordionItemsSchema,
|
||||
globalAccordionConnectionRefs,
|
||||
specificAccordionConnectionRefs,
|
||||
} from "./accordion"
|
||||
|
||||
export const hotelFaqSchema = z
|
||||
.object({
|
||||
typename: z
|
||||
.literal(BlocksEnums.block.Accordion)
|
||||
.optional()
|
||||
.default(BlocksEnums.block.Accordion),
|
||||
title: z.string().optional().default(""),
|
||||
global_faqConnection: z
|
||||
.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z.object({
|
||||
questions: accordionItemsSchema,
|
||||
}),
|
||||
})
|
||||
),
|
||||
})
|
||||
.optional(),
|
||||
specific_faq: z
|
||||
.object({
|
||||
questions: accordionItemsSchema,
|
||||
})
|
||||
.optional()
|
||||
.nullable(),
|
||||
})
|
||||
.transform((data) => {
|
||||
const array = []
|
||||
array.push(
|
||||
data.global_faqConnection?.edges.flatMap(({ node: faqConnection }) => {
|
||||
return faqConnection.questions
|
||||
}) || []
|
||||
)
|
||||
array.push(data.specific_faq?.questions || [])
|
||||
return { ...data, accordions: array.flat(2) }
|
||||
})
|
||||
|
||||
export const hotelFaqRefsSchema = z
|
||||
.object({
|
||||
__typename: z
|
||||
.literal(HotelPageEnum.ContentStack.blocks.Faq)
|
||||
.optional()
|
||||
.default(HotelPageEnum.ContentStack.blocks.Faq),
|
||||
global_faqConnection: globalAccordionConnectionRefs.optional(),
|
||||
specific_faq: specificAccordionConnectionRefs.optional().nullable(),
|
||||
})
|
||||
.transform((data) => {
|
||||
const array = []
|
||||
array.push(
|
||||
data.global_faqConnection?.edges.flatMap(({ node: faqConnection }) => {
|
||||
return faqConnection.questions.flatMap((question) =>
|
||||
question.answer.embedded_itemsConnection.edges.flatMap(
|
||||
({ node }) => node.system
|
||||
)
|
||||
)
|
||||
}) || []
|
||||
)
|
||||
array.push(
|
||||
data.specific_faq?.questions.flatMap((question) =>
|
||||
question.answer.embedded_itemsConnection.edges.flatMap(
|
||||
({ node }) => node.system
|
||||
)
|
||||
) || []
|
||||
)
|
||||
return array.flat(2)
|
||||
})
|
||||
@@ -0,0 +1,71 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { BlocksEnums } from "../../../../types/blocks"
|
||||
import { Country } from "../../../../types/country"
|
||||
|
||||
export const locationFilterSchema = z
|
||||
.object({
|
||||
country: z.nativeEnum(Country).nullable(),
|
||||
city_denmark: z.string().optional().nullable(),
|
||||
city_finland: z.string().optional().nullable(),
|
||||
city_germany: z.string().optional().nullable(),
|
||||
city_poland: z.string().optional().nullable(),
|
||||
city_norway: z.string().optional().nullable(),
|
||||
city_sweden: z.string().optional().nullable(),
|
||||
excluded: z.array(z.string()),
|
||||
})
|
||||
.transform((data) => {
|
||||
const cities = [
|
||||
data.city_denmark,
|
||||
data.city_finland,
|
||||
data.city_germany,
|
||||
data.city_poland,
|
||||
data.city_norway,
|
||||
data.city_sweden,
|
||||
].filter((city): city is string => Boolean(city))
|
||||
|
||||
// When there are multiple city values, we return null as the filter is invalid.
|
||||
if (cities.length > 1) {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
country: cities.length ? null : data.country,
|
||||
city: cities.length ? cities[0] : null,
|
||||
excluded: data.excluded,
|
||||
}
|
||||
})
|
||||
|
||||
export const contentPageHotelListingSchema = z.object({
|
||||
typename: z
|
||||
.literal(BlocksEnums.block.ContentPageHotelListing)
|
||||
.default(BlocksEnums.block.ContentPageHotelListing),
|
||||
hotel_listing: z
|
||||
.object({
|
||||
heading: z.string().optional(),
|
||||
location_filter: locationFilterSchema,
|
||||
manual_filter: z
|
||||
.object({
|
||||
hotels: z.array(z.string()),
|
||||
})
|
||||
.transform((data) => ({ hotels: data.hotels.filter(Boolean) })),
|
||||
content_type: z.enum(["hotel", "restaurant", "meeting"]),
|
||||
})
|
||||
.transform(({ heading, location_filter, manual_filter, content_type }) => {
|
||||
return {
|
||||
heading,
|
||||
locationFilter: location_filter,
|
||||
hotelsToInclude: manual_filter.hotels,
|
||||
contentType: content_type,
|
||||
}
|
||||
}),
|
||||
})
|
||||
|
||||
export const campaignPageHotelListingSchema = z.object({
|
||||
typename: z
|
||||
.literal(BlocksEnums.block.CampaignPageHotelListing)
|
||||
.default(BlocksEnums.block.CampaignPageHotelListing),
|
||||
hotel_listing: z.object({
|
||||
heading: z.string(),
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,20 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { ContentEnum } from "../../../../types/content"
|
||||
import { tempImageVaultAssetSchema } from "../imageVault"
|
||||
import { systemSchema } from "../system"
|
||||
|
||||
export const imageContainerSchema = z.object({
|
||||
__typename: z.literal(ContentEnum.blocks.ImageContainer),
|
||||
// JSON - ImageVault Image
|
||||
image_left: tempImageVaultAssetSchema,
|
||||
// JSON - ImageVault Image
|
||||
image_right: tempImageVaultAssetSchema,
|
||||
system: systemSchema,
|
||||
title: z.string().optional(),
|
||||
})
|
||||
|
||||
export const imageContainerRefsSchema = z.object({
|
||||
__typename: z.literal(ContentEnum.blocks.ImageContainer),
|
||||
system: systemSchema,
|
||||
})
|
||||
@@ -0,0 +1,35 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { BlocksEnums } from "../../../../types/blocks"
|
||||
import { tempImageVaultAssetSchema } from "../imageVault"
|
||||
import { buttonSchema } from "./utils/buttonLinkSchema"
|
||||
import { linkConnectionRefsSchema } from "./utils/linkConnection"
|
||||
|
||||
export const joinScandicFriendsSchema = z.object({
|
||||
join_scandic_friends: z.object({
|
||||
show_header: z.boolean().default(false),
|
||||
scripted_top_title: z.string(),
|
||||
title: z.string(),
|
||||
preamble: z.string(),
|
||||
image: tempImageVaultAssetSchema,
|
||||
show_usp: z.boolean().default(false),
|
||||
usp: z.array(z.string()),
|
||||
has_primary_button: z.boolean().default(false),
|
||||
primary_button: buttonSchema,
|
||||
}),
|
||||
})
|
||||
|
||||
export const joinScandicFriendsBlockSchema = z
|
||||
.object({
|
||||
typename: z
|
||||
.literal(BlocksEnums.block.JoinScandicFriends)
|
||||
.optional()
|
||||
.default(BlocksEnums.block.JoinScandicFriends),
|
||||
})
|
||||
.merge(joinScandicFriendsSchema)
|
||||
|
||||
export const joinScandicFriendsBlockRefsSchema = z.object({
|
||||
join_scandic_friends: z.object({
|
||||
primary_button: linkConnectionRefsSchema,
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,89 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { BlocksEnums } from "../../../../types/blocks"
|
||||
import {
|
||||
linkRefsUnionSchema,
|
||||
linkUnionSchema,
|
||||
transformPageLink,
|
||||
} from "../pageLinks"
|
||||
|
||||
export const shortcutsBlockSchema = z.object({
|
||||
shortcuts: z
|
||||
.object({
|
||||
subtitle: z.string().nullable(),
|
||||
title: z.string().nullable(),
|
||||
two_column_list: z.boolean().nullable().default(false),
|
||||
shortcuts: z
|
||||
.array(
|
||||
z.object({
|
||||
open_in_new_tab: z.boolean(),
|
||||
text: z.string().optional().default(""),
|
||||
linkConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: linkUnionSchema.transform((data) => {
|
||||
const link = transformPageLink(data)
|
||||
if (link) {
|
||||
return link
|
||||
}
|
||||
return data
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
)
|
||||
.transform((data) => {
|
||||
return data
|
||||
.filter((node) => node.linkConnection.edges.length)
|
||||
.map((node) => {
|
||||
const link = node.linkConnection.edges[0].node
|
||||
return {
|
||||
openInNewTab: node.open_in_new_tab,
|
||||
text: node.text,
|
||||
title: link.title,
|
||||
url: link.url,
|
||||
}
|
||||
})
|
||||
}),
|
||||
})
|
||||
.transform(({ two_column_list, ...rest }) => {
|
||||
return {
|
||||
...rest,
|
||||
hasTwoColumns: !!two_column_list,
|
||||
}
|
||||
}),
|
||||
})
|
||||
|
||||
export const shortcutsSchema = z
|
||||
.object({
|
||||
typename: z
|
||||
.literal(BlocksEnums.block.Shortcuts)
|
||||
.optional()
|
||||
.default(BlocksEnums.block.Shortcuts),
|
||||
})
|
||||
.merge(shortcutsBlockSchema)
|
||||
|
||||
export const shortcutsRefsSchema = z.object({
|
||||
shortcuts: z.object({
|
||||
shortcuts: z
|
||||
.array(
|
||||
z.object({
|
||||
linkConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: linkRefsUnionSchema,
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
)
|
||||
.transform((data) =>
|
||||
data
|
||||
.map((shortcut) => {
|
||||
return shortcut.linkConnection.edges.map(({ node }) => node.system)
|
||||
})
|
||||
.flat()
|
||||
),
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,67 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { removeMultipleSlashes } from "@scandic-hotels/common/utils/url"
|
||||
|
||||
import { HotelPageEnum } from "../../../../types/hotelPageEnum"
|
||||
import { collectionPageRefSchema, contentPageRefSchema } from "../pageLinks"
|
||||
|
||||
export const spaPageSchema = z.object({
|
||||
typename: z
|
||||
.literal(HotelPageEnum.ContentStack.blocks.SpaPage)
|
||||
.optional()
|
||||
.default(HotelPageEnum.ContentStack.blocks.SpaPage),
|
||||
spa_page: z
|
||||
.object({
|
||||
button_cta: z.string(),
|
||||
pageConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z.object({
|
||||
title: z.string(),
|
||||
url: z.string(),
|
||||
system: z.object({
|
||||
content_type_uid: z.string(),
|
||||
locale: z.string(),
|
||||
uid: z.string(),
|
||||
}),
|
||||
web: z.object({ original_url: z.string() }),
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
let url = ""
|
||||
if (data.pageConnection.edges.length) {
|
||||
const page = data.pageConnection.edges[0].node
|
||||
if (page.web.original_url) {
|
||||
url = page.web.original_url
|
||||
} else {
|
||||
url = removeMultipleSlashes(`/${page.system.locale}/${page.url}`)
|
||||
}
|
||||
}
|
||||
return {
|
||||
buttonCTA: data.button_cta,
|
||||
url: url,
|
||||
}
|
||||
}),
|
||||
})
|
||||
|
||||
export const spaPageRefSchema = z.object({
|
||||
spa_page: z
|
||||
.object({
|
||||
pageConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z.discriminatedUnion("__typename", [
|
||||
contentPageRefSchema,
|
||||
collectionPageRefSchema,
|
||||
]),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
return data.pageConnection.edges.flatMap(({ node }) => node.system) || []
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,36 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { ContentEnum } from "../../../../types/content"
|
||||
|
||||
// SysAsset is used for several different assets in ContentStack, such as images, pdf-files, etc.
|
||||
// It is a generic asset type that can represent any file type.
|
||||
// A lot of the fields are optional/nullable, hence the use of `.nullish()`.
|
||||
// The properties of this schema should be handled inside the components that use it, fe. web/apps/scandic-web/components/JsonToHtml/renderOptions.tsx.
|
||||
export const sysAssetSchema = z.object({
|
||||
__typename: z.literal(ContentEnum.blocks.SysAsset),
|
||||
content_type: z.string().nullish(),
|
||||
description: z.string().nullish(),
|
||||
dimension: z
|
||||
.object({
|
||||
height: z.number(),
|
||||
width: z.number(),
|
||||
})
|
||||
.nullish(),
|
||||
metadata: z.any(), // JSON
|
||||
// system for SysAssets is not the same type
|
||||
// as for all other types eventhough they have
|
||||
// the exact same structure, that's why systemSchema
|
||||
// is not used as that correlates to the
|
||||
// EntrySystemField type
|
||||
system: z
|
||||
.object({
|
||||
uid: z.string(),
|
||||
})
|
||||
.nullish(),
|
||||
title: z.string().nullish(),
|
||||
url: z.string().nullish(),
|
||||
})
|
||||
|
||||
export const sysAssetRefsSchema = z.object({
|
||||
__typename: z.literal(ContentEnum.blocks.SysAsset),
|
||||
})
|
||||
@@ -0,0 +1,58 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { BlocksEnums } from "../../../../types/blocks"
|
||||
|
||||
export const tableSchema = z.object({
|
||||
typename: z
|
||||
.literal(BlocksEnums.block.Table)
|
||||
.optional()
|
||||
.default(BlocksEnums.block.Table),
|
||||
table: z
|
||||
.object({
|
||||
heading: z.string().optional(),
|
||||
preamble: z.string().optional().default(""),
|
||||
column_widths: z.array(z.number()),
|
||||
table: z.object({
|
||||
tableState: z.object({
|
||||
columns: z.array(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
label: z.string().default(""),
|
||||
accessor: z.string(),
|
||||
dataType: z.string(),
|
||||
})
|
||||
),
|
||||
data: z.array(z.object({}).catchall(z.string())),
|
||||
skipReset: z.boolean(),
|
||||
tableActionEnabled: z.boolean(),
|
||||
headerRowAdded: z.boolean().optional().default(false),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
const totalWidth = data.column_widths.reduce(
|
||||
(acc, width) => acc + width,
|
||||
0
|
||||
)
|
||||
const columns = data.table.tableState.columns.map((col, idx) => ({
|
||||
id: col.id,
|
||||
header: col.label || "",
|
||||
width: data.column_widths[idx] || 0,
|
||||
}))
|
||||
|
||||
const rows = data.table.tableState.data.map((rowData) =>
|
||||
columns.reduce<Record<string, string>>((transformedRow, column) => {
|
||||
transformedRow[column.id] = rowData[column.id] || ""
|
||||
return transformedRow
|
||||
}, {})
|
||||
)
|
||||
|
||||
return {
|
||||
heading: data.heading,
|
||||
preamble: data.preamble,
|
||||
columns,
|
||||
rows,
|
||||
totalWidth,
|
||||
}
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,81 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { BlocksEnums } from "../../../../types/blocks"
|
||||
import { ContentEnum } from "../../../../types/content"
|
||||
import {
|
||||
linkRefsUnionSchema,
|
||||
linkUnionSchema,
|
||||
transformPageLink,
|
||||
} from "../pageLinks"
|
||||
import { sysAssetRefsSchema, sysAssetSchema } from "./sysAsset"
|
||||
|
||||
export const textColsSchema = z.object({
|
||||
typename: z
|
||||
.literal(BlocksEnums.block.TextCols)
|
||||
.optional()
|
||||
.default(BlocksEnums.block.TextCols),
|
||||
text_cols: z.object({
|
||||
columns: z.array(
|
||||
z.object({
|
||||
title: z.string().optional().default(""),
|
||||
text: z.object({
|
||||
json: z.any(), // JSON
|
||||
embedded_itemsConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z
|
||||
.discriminatedUnion("__typename", [
|
||||
sysAssetSchema,
|
||||
...linkUnionSchema.options,
|
||||
])
|
||||
.transform((data) => {
|
||||
const link = transformPageLink(data)
|
||||
if (link) {
|
||||
return link
|
||||
}
|
||||
return data
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
|
||||
type Refs = {
|
||||
node: z.TypeOf<typeof linkUnionSchema>
|
||||
}
|
||||
|
||||
export const textColsRefsSchema = z.object({
|
||||
text_cols: z
|
||||
.object({
|
||||
columns: z.array(
|
||||
z.object({
|
||||
text: z.object({
|
||||
embedded_itemsConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z.discriminatedUnion("__typename", [
|
||||
sysAssetRefsSchema,
|
||||
...linkRefsUnionSchema.options,
|
||||
]),
|
||||
})
|
||||
),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
),
|
||||
})
|
||||
.transform((data) => {
|
||||
return data.columns
|
||||
.map((column) => {
|
||||
const filtered = column.text.embedded_itemsConnection.edges.filter(
|
||||
(block) => block.node.__typename !== ContentEnum.blocks.SysAsset
|
||||
) as unknown as Refs[] // TS issue with filtered out types
|
||||
return filtered.map(({ node }) => node.system)
|
||||
})
|
||||
.flat()
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,24 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { BlocksEnums } from "../../../../types/blocks"
|
||||
import { sysAssetSchema } from "./sysAsset"
|
||||
|
||||
export const textContentSchema = z.object({
|
||||
typename: z
|
||||
.literal(BlocksEnums.block.TextContent)
|
||||
.optional()
|
||||
.default(BlocksEnums.block.TextContent),
|
||||
text_content: z.object({
|
||||
content: z.object({
|
||||
json: z.any(),
|
||||
embedded_itemsConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z.discriminatedUnion("__typename", [sysAssetSchema]),
|
||||
})
|
||||
),
|
||||
totalCount: z.number(),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,91 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { BlocksEnums } from "../../../../types/blocks"
|
||||
import { UspGridEnum } from "../../../../types/uspGrid"
|
||||
import {
|
||||
linkRefsUnionSchema,
|
||||
linkUnionSchema,
|
||||
transformPageLink,
|
||||
} from "../pageLinks"
|
||||
|
||||
const uspCardSchema = z.object({
|
||||
icon: UspGridEnum.uspIcons,
|
||||
text: z.object({
|
||||
json: z.any(), // JSON
|
||||
embedded_itemsConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: linkUnionSchema.transform((data) => {
|
||||
const link = transformPageLink(data)
|
||||
if (link) {
|
||||
return link
|
||||
}
|
||||
return data
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
|
||||
export const uspGridSchema = z.object({
|
||||
typename: z
|
||||
.literal(BlocksEnums.block.UspGrid)
|
||||
.optional()
|
||||
.default(BlocksEnums.block.UspGrid),
|
||||
usp_grid: z
|
||||
.object({
|
||||
cardsConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z.object({
|
||||
usp_card: z.array(uspCardSchema),
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
return {
|
||||
usp_card: data.cardsConnection.edges.flatMap(
|
||||
(edge) => edge.node.usp_card
|
||||
),
|
||||
}
|
||||
}),
|
||||
})
|
||||
|
||||
export const uspGridRefsSchema = z.object({
|
||||
usp_grid: z
|
||||
.object({
|
||||
cardsConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z.object({
|
||||
usp_card: z.array(
|
||||
z.object({
|
||||
text: z.object({
|
||||
embedded_itemsConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: linkRefsUnionSchema,
|
||||
})
|
||||
),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
return data.cardsConnection.edges.flatMap(({ node }) =>
|
||||
node.usp_card.flatMap((card) =>
|
||||
card.text.embedded_itemsConnection.edges.map(
|
||||
({ node }) => node.system
|
||||
)
|
||||
)
|
||||
)
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,52 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { linkUnionSchema, transformPageLink } from "../../pageLinks"
|
||||
|
||||
export const buttonSchema = z
|
||||
.object({
|
||||
cta_text: z.string().optional().default(""),
|
||||
open_in_new_tab: z.boolean().default(false),
|
||||
is_contentstack_link: z.boolean().optional(),
|
||||
external_link: z
|
||||
.object({
|
||||
href: z.string().optional().default(""),
|
||||
title: z.string().optional(),
|
||||
})
|
||||
.optional(),
|
||||
linkConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: linkUnionSchema.transform((data) => {
|
||||
const link = transformPageLink(data)
|
||||
if (link) {
|
||||
return link
|
||||
}
|
||||
return data
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
if (
|
||||
data.linkConnection?.edges?.length &&
|
||||
data.is_contentstack_link !== false
|
||||
) {
|
||||
const link = data.linkConnection.edges[0].node
|
||||
return {
|
||||
href: link.url,
|
||||
isExternal: false,
|
||||
openInNewTab: data.open_in_new_tab,
|
||||
title: data.cta_text ? data.cta_text : "",
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
href: data.external_link?.href ?? "",
|
||||
isExternal: true,
|
||||
openInNewTab: data.open_in_new_tab,
|
||||
title: data.external_link?.title
|
||||
? data.external_link?.title
|
||||
: data.cta_text,
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,21 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { linkRefsUnionSchema } from "../../pageLinks"
|
||||
|
||||
export const linkConnectionRefsSchema = z
|
||||
.object({
|
||||
linkConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: linkRefsUnionSchema,
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
if (!data.linkConnection.edges.length) {
|
||||
return null
|
||||
}
|
||||
|
||||
return data.linkConnection.edges[0].node.system
|
||||
})
|
||||
@@ -0,0 +1,11 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { DynamicContentEnum } from "../../../../types/dynamicContent"
|
||||
|
||||
export const dynamicContentSchema = z.object({
|
||||
component: z.enum(DynamicContentEnum.Headers.enums).nullish(),
|
||||
})
|
||||
|
||||
export const dynamicContentRefsSchema = z.object({
|
||||
component: z.enum(DynamicContentEnum.Headers.enums).nullish(),
|
||||
})
|
||||
163
packages/trpc/lib/routers/contentstack/schemas/imageVault.ts
Normal file
163
packages/trpc/lib/routers/contentstack/schemas/imageVault.ts
Normal file
@@ -0,0 +1,163 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { insertResponseToImageVaultAsset } from "../../../utils/imageVault"
|
||||
|
||||
import type { ImageVaultAssetResponse } from "../../../types/imageVault"
|
||||
|
||||
const metaData = z.object({
|
||||
DefinitionType: z.number().nullable().optional(),
|
||||
Description: z.string().nullable(),
|
||||
LanguageId: z.number().nullable(),
|
||||
MetadataDefinitionId: z.number(),
|
||||
Name: z.string(),
|
||||
Value: z.string().nullable(),
|
||||
})
|
||||
|
||||
export const focalPointSchema = z.object({
|
||||
x: z.number(),
|
||||
y: z.number(),
|
||||
})
|
||||
|
||||
/**
|
||||
* Defines a media asset, original or conversion
|
||||
*/
|
||||
const mediaConversion = z.object({
|
||||
/**
|
||||
* Aspect ratio of the conversion
|
||||
*/
|
||||
AspectRatio: z.number(),
|
||||
/**
|
||||
* Content type of the conversion
|
||||
*/
|
||||
ContentType: z.string(),
|
||||
/**
|
||||
* Aspect ratio of the selected/requested format
|
||||
*/
|
||||
FormatAspectRatio: z.number(),
|
||||
/**
|
||||
* Height of the selected/requested format
|
||||
*/
|
||||
FormatHeight: z.number(),
|
||||
/**
|
||||
* Width of the selected/requested format
|
||||
*/
|
||||
FormatWidth: z.number(),
|
||||
/**
|
||||
* Height, in pixels, of the conversion
|
||||
*/
|
||||
Height: z.number(),
|
||||
/**
|
||||
* Html representing the conversion
|
||||
*/
|
||||
Html: z.string(),
|
||||
/**
|
||||
* Id of the selected media format
|
||||
*/
|
||||
MediaFormatId: z.number(),
|
||||
/**
|
||||
* Name of the media format
|
||||
*/
|
||||
MediaFormatName: z.string(),
|
||||
/**
|
||||
* Name of the conversion
|
||||
*/
|
||||
Name: z.string(),
|
||||
/**
|
||||
* The url to the conversion
|
||||
*/
|
||||
Url: z.string(),
|
||||
/**
|
||||
* Width, in pixels, of the conversion
|
||||
*/
|
||||
Width: z.number(),
|
||||
})
|
||||
|
||||
/**
|
||||
* The response from ImageVault when inserting an asset
|
||||
*/
|
||||
export const imageVaultAssetSchema = z.object({
|
||||
/**
|
||||
* The media item id of the asset
|
||||
*/
|
||||
Id: z.number(),
|
||||
/**
|
||||
* The id of the vault where the asset resides
|
||||
*/
|
||||
VaultId: z.number(),
|
||||
/**
|
||||
* The name of the asset
|
||||
*/
|
||||
Name: z.string(),
|
||||
/**
|
||||
* The conversion selected by the user. Is an array but will only contain one object
|
||||
*/
|
||||
MediaConversions: z.array(mediaConversion),
|
||||
Metadata: z.array(metaData),
|
||||
/**
|
||||
* Date when the asset was added to ImageVault
|
||||
*/
|
||||
DateAdded: z.string(),
|
||||
/**
|
||||
* Name of the user that added the asset to ImageVault
|
||||
*/
|
||||
AddedBy: z.string(),
|
||||
FocalPoint: focalPointSchema.optional(),
|
||||
})
|
||||
|
||||
export const imageVaultAssetTransformedSchema = imageVaultAssetSchema.transform(
|
||||
(rawData) => {
|
||||
const alt = rawData.Metadata?.find((meta) =>
|
||||
meta.Name.includes("AltText_")
|
||||
)?.Value
|
||||
|
||||
const caption = rawData.Metadata?.find((meta) =>
|
||||
meta.Name.includes("Title_")
|
||||
)?.Value
|
||||
const mediaConversion = rawData.MediaConversions[0]
|
||||
const aspectRatio =
|
||||
mediaConversion.FormatAspectRatio ||
|
||||
mediaConversion.AspectRatio ||
|
||||
mediaConversion.Width / mediaConversion.Height
|
||||
|
||||
return {
|
||||
url: mediaConversion.Url,
|
||||
id: rawData.Id,
|
||||
meta: {
|
||||
alt,
|
||||
caption,
|
||||
},
|
||||
title: rawData.Name,
|
||||
dimensions: {
|
||||
width: mediaConversion.Width,
|
||||
height: mediaConversion.Height,
|
||||
aspectRatio,
|
||||
},
|
||||
focalPoint: rawData.FocalPoint || { x: 50, y: 50 },
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
export const tempImageVaultAssetSchema = imageVaultAssetSchema
|
||||
.nullable()
|
||||
.optional()
|
||||
.or(
|
||||
// Temp since there is a bug in Contentstack
|
||||
// sending empty objects when there has been an
|
||||
// image selected previously but has since been
|
||||
// deleted
|
||||
z.object({})
|
||||
)
|
||||
.transform((data) => {
|
||||
if (data) {
|
||||
if ("Name" in data) {
|
||||
return makeImageVaultImage(data)
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
})
|
||||
|
||||
function makeImageVaultImage(image: any) {
|
||||
return image && !!Object.keys(image).length
|
||||
? insertResponseToImageVaultAsset(image as ImageVaultAssetResponse)
|
||||
: undefined
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import {
|
||||
linkRefsUnionSchema,
|
||||
linkUnionSchema,
|
||||
transformPageLink,
|
||||
transformPageLinkRef,
|
||||
} from "./pageLinks"
|
||||
|
||||
const titleSchema = z.object({
|
||||
title: z.string().optional().default(""),
|
||||
})
|
||||
|
||||
export const linkConnectionSchema = z
|
||||
.object({
|
||||
linkConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: linkUnionSchema,
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
if (data.linkConnection.edges.length) {
|
||||
const linkNode = data.linkConnection.edges[0].node
|
||||
if (linkNode) {
|
||||
const link = transformPageLink(linkNode)
|
||||
if (link) {
|
||||
return {
|
||||
link,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
link: null,
|
||||
}
|
||||
})
|
||||
|
||||
export const linkAndTitleSchema = z.intersection(
|
||||
linkConnectionSchema,
|
||||
titleSchema
|
||||
)
|
||||
|
||||
export const linkConnectionRefs = z
|
||||
.object({
|
||||
linkConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: linkRefsUnionSchema,
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
if (data.linkConnection.edges.length) {
|
||||
const linkNode = data.linkConnection.edges[0].node
|
||||
if (linkNode) {
|
||||
const link = transformPageLinkRef(linkNode)
|
||||
if (link) {
|
||||
return {
|
||||
link,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return { link: null }
|
||||
})
|
||||
@@ -0,0 +1,25 @@
|
||||
import { z } from "zod"
|
||||
|
||||
export const mapLocationSchema = z
|
||||
.object({
|
||||
longitude: z.number().nullable(),
|
||||
latitude: z.number().nullable(),
|
||||
default_zoom: z.number().nullable(),
|
||||
})
|
||||
.nullish()
|
||||
.transform((val) => {
|
||||
if (val) {
|
||||
const longitude = val.longitude
|
||||
const latitude = val.latitude
|
||||
const default_zoom = val.default_zoom || 3
|
||||
|
||||
if (longitude !== null && latitude !== null) {
|
||||
return {
|
||||
longitude,
|
||||
latitude,
|
||||
default_zoom: Math.round(default_zoom),
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
})
|
||||
254
packages/trpc/lib/routers/contentstack/schemas/pageLinks.ts
Normal file
254
packages/trpc/lib/routers/contentstack/schemas/pageLinks.ts
Normal file
@@ -0,0 +1,254 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { removeMultipleSlashes } from "@scandic-hotels/common/utils/url"
|
||||
|
||||
import { ContentEnum } from "../../../types/content"
|
||||
import { systemSchema } from "./system"
|
||||
|
||||
export const pageLinkSchema = z.object({
|
||||
system: systemSchema,
|
||||
title: z.string().optional().default(""),
|
||||
url: z.string().optional().default(""),
|
||||
})
|
||||
|
||||
export const accountPageSchema = z
|
||||
.object({
|
||||
__typename: z.literal(ContentEnum.blocks.AccountPage),
|
||||
})
|
||||
.merge(pageLinkSchema)
|
||||
|
||||
export const accountPageRefSchema = z.object({
|
||||
__typename: z.literal(ContentEnum.blocks.AccountPage),
|
||||
system: systemSchema,
|
||||
})
|
||||
|
||||
export const extendedPageLinkSchema = pageLinkSchema.merge(
|
||||
z.object({
|
||||
web: z
|
||||
.object({
|
||||
original_url: z.string().optional().default(""),
|
||||
})
|
||||
.default({ original_url: "" }),
|
||||
})
|
||||
)
|
||||
|
||||
export const campaignOverviewPageSchema = z
|
||||
.object({
|
||||
__typename: z.literal(ContentEnum.blocks.CampaignOverviewPage),
|
||||
})
|
||||
.merge(extendedPageLinkSchema)
|
||||
|
||||
export const campaignOverviewPageRefSchema = z.object({
|
||||
__typename: z.literal(ContentEnum.blocks.CampaignOverviewPage),
|
||||
system: systemSchema,
|
||||
})
|
||||
|
||||
export const collectionPageSchema = z
|
||||
.object({
|
||||
__typename: z.literal(ContentEnum.blocks.CollectionPage),
|
||||
})
|
||||
.merge(extendedPageLinkSchema)
|
||||
|
||||
export const collectionPageRefSchema = z.object({
|
||||
__typename: z.literal(ContentEnum.blocks.CollectionPage),
|
||||
system: systemSchema,
|
||||
})
|
||||
|
||||
export const contentPageSchema = z
|
||||
.object({
|
||||
__typename: z.literal(ContentEnum.blocks.ContentPage),
|
||||
})
|
||||
.merge(extendedPageLinkSchema)
|
||||
|
||||
export const contentPageRefSchema = z.object({
|
||||
__typename: z.literal(ContentEnum.blocks.ContentPage),
|
||||
system: systemSchema,
|
||||
})
|
||||
|
||||
export const destinationCityPageSchema = z
|
||||
.object({
|
||||
__typename: z.literal(ContentEnum.blocks.DestinationCityPage),
|
||||
})
|
||||
.merge(pageLinkSchema)
|
||||
|
||||
export const destinationCityPageRefSchema = z.object({
|
||||
__typename: z.literal(ContentEnum.blocks.DestinationCityPage),
|
||||
system: systemSchema,
|
||||
})
|
||||
|
||||
export const campaignPageSchema = z
|
||||
.object({
|
||||
__typename: z.literal(ContentEnum.blocks.CampaignPage),
|
||||
})
|
||||
.merge(pageLinkSchema)
|
||||
|
||||
export const campaignPageRefSchema = z.object({
|
||||
__typename: z.literal(ContentEnum.blocks.CampaignPage),
|
||||
system: systemSchema,
|
||||
})
|
||||
|
||||
export const destinationCountryPageSchema = z
|
||||
.object({
|
||||
__typename: z.literal(ContentEnum.blocks.DestinationCountryPage),
|
||||
})
|
||||
.merge(pageLinkSchema)
|
||||
|
||||
export const destinationCountryPageRefSchema = z.object({
|
||||
__typename: z.literal(ContentEnum.blocks.DestinationCountryPage),
|
||||
system: systemSchema,
|
||||
})
|
||||
|
||||
export const destinationOverviewPageSchema = z
|
||||
.object({
|
||||
__typename: z.literal(ContentEnum.blocks.DestinationOverviewPage),
|
||||
})
|
||||
.merge(pageLinkSchema)
|
||||
|
||||
export const destinationOverviewPageRefSchema = z.object({
|
||||
__typename: z.literal(ContentEnum.blocks.DestinationOverviewPage),
|
||||
system: systemSchema,
|
||||
})
|
||||
|
||||
export const hotelPageSchema = z
|
||||
.object({
|
||||
__typename: z.literal(ContentEnum.blocks.HotelPage),
|
||||
})
|
||||
.merge(pageLinkSchema)
|
||||
|
||||
export const hotelPageRefSchema = z.object({
|
||||
__typename: z.literal(ContentEnum.blocks.HotelPage),
|
||||
system: systemSchema,
|
||||
})
|
||||
|
||||
export const loyaltyPageSchema = z
|
||||
.object({
|
||||
__typename: z.literal(ContentEnum.blocks.LoyaltyPage),
|
||||
})
|
||||
.merge(extendedPageLinkSchema)
|
||||
|
||||
export const loyaltyPageRefSchema = z.object({
|
||||
__typename: z.literal(ContentEnum.blocks.LoyaltyPage),
|
||||
system: systemSchema,
|
||||
})
|
||||
|
||||
export const startPageSchema = z
|
||||
.object({
|
||||
__typename: z.literal(ContentEnum.blocks.StartPage),
|
||||
})
|
||||
.merge(pageLinkSchema)
|
||||
|
||||
export const startPageRefSchema = z.object({
|
||||
__typename: z.literal(ContentEnum.blocks.StartPage),
|
||||
system: systemSchema,
|
||||
})
|
||||
|
||||
export const linkUnionSchema = z.discriminatedUnion("__typename", [
|
||||
accountPageSchema,
|
||||
campaignOverviewPageSchema,
|
||||
campaignPageSchema,
|
||||
collectionPageSchema,
|
||||
contentPageSchema,
|
||||
destinationCityPageSchema,
|
||||
destinationCountryPageSchema,
|
||||
destinationOverviewPageSchema,
|
||||
hotelPageSchema,
|
||||
loyaltyPageSchema,
|
||||
startPageSchema,
|
||||
])
|
||||
|
||||
type Data =
|
||||
| z.output<typeof accountPageSchema>
|
||||
| z.output<typeof campaignOverviewPageSchema>
|
||||
| z.output<typeof campaignPageSchema>
|
||||
| z.output<typeof collectionPageSchema>
|
||||
| z.output<typeof contentPageSchema>
|
||||
| z.output<typeof destinationCityPageSchema>
|
||||
| z.output<typeof destinationCountryPageSchema>
|
||||
| z.output<typeof destinationOverviewPageSchema>
|
||||
| z.output<typeof hotelPageSchema>
|
||||
| z.output<typeof loyaltyPageSchema>
|
||||
| z.output<typeof startPageSchema>
|
||||
| Object
|
||||
|
||||
export function transformPageLink(data: Data) {
|
||||
if (data && "__typename" in data) {
|
||||
switch (data.__typename) {
|
||||
case ContentEnum.blocks.AccountPage:
|
||||
case ContentEnum.blocks.CampaignOverviewPage:
|
||||
case ContentEnum.blocks.CampaignPage:
|
||||
case ContentEnum.blocks.DestinationCityPage:
|
||||
case ContentEnum.blocks.DestinationCountryPage:
|
||||
case ContentEnum.blocks.DestinationOverviewPage:
|
||||
case ContentEnum.blocks.HotelPage:
|
||||
case ContentEnum.blocks.StartPage:
|
||||
return {
|
||||
__typename: data.__typename,
|
||||
system: data.system,
|
||||
title: data.title,
|
||||
url: removeMultipleSlashes(`/${data.system.locale}/${data.url}`),
|
||||
}
|
||||
case ContentEnum.blocks.CollectionPage:
|
||||
case ContentEnum.blocks.ContentPage:
|
||||
case ContentEnum.blocks.LoyaltyPage:
|
||||
// TODO: Once all links use this transform
|
||||
// `web` can be removed and not to be worried
|
||||
// about throughout the application
|
||||
return {
|
||||
__typename: data.__typename,
|
||||
system: data.system,
|
||||
title: data.title,
|
||||
url: data.web?.original_url
|
||||
? data.web.original_url
|
||||
: removeMultipleSlashes(`/${data.system.locale}/${data.url}`),
|
||||
web: data.web,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const linkRefsUnionSchema = z.discriminatedUnion("__typename", [
|
||||
accountPageRefSchema,
|
||||
campaignOverviewPageRefSchema,
|
||||
campaignPageRefSchema,
|
||||
collectionPageRefSchema,
|
||||
contentPageRefSchema,
|
||||
destinationCityPageRefSchema,
|
||||
destinationCountryPageRefSchema,
|
||||
destinationOverviewPageRefSchema,
|
||||
hotelPageRefSchema,
|
||||
loyaltyPageRefSchema,
|
||||
startPageRefSchema,
|
||||
])
|
||||
|
||||
type RefData =
|
||||
| z.output<typeof accountPageRefSchema>
|
||||
| z.output<typeof campaignOverviewPageRefSchema>
|
||||
| z.output<typeof campaignPageRefSchema>
|
||||
| z.output<typeof collectionPageRefSchema>
|
||||
| z.output<typeof contentPageRefSchema>
|
||||
| z.output<typeof destinationCityPageRefSchema>
|
||||
| z.output<typeof destinationCountryPageRefSchema>
|
||||
| z.output<typeof destinationOverviewPageRefSchema>
|
||||
| z.output<typeof hotelPageRefSchema>
|
||||
| z.output<typeof loyaltyPageRefSchema>
|
||||
| z.output<typeof startPageRefSchema>
|
||||
| Object
|
||||
|
||||
export function transformPageLinkRef(data: RefData) {
|
||||
if (data && "__typename" in data) {
|
||||
switch (data.__typename) {
|
||||
case ContentEnum.blocks.AccountPage:
|
||||
case ContentEnum.blocks.CampaignOverviewPage:
|
||||
case ContentEnum.blocks.CampaignPage:
|
||||
case ContentEnum.blocks.CollectionPage:
|
||||
case ContentEnum.blocks.ContentPage:
|
||||
case ContentEnum.blocks.DestinationCityPage:
|
||||
case ContentEnum.blocks.DestinationCountryPage:
|
||||
case ContentEnum.blocks.DestinationOverviewPage:
|
||||
case ContentEnum.blocks.HotelPage:
|
||||
case ContentEnum.blocks.LoyaltyPage:
|
||||
case ContentEnum.blocks.StartPage:
|
||||
return data.system
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { ContentEnum } from "../../../../types/content"
|
||||
import { SidebarEnums } from "../../../../types/sidebar"
|
||||
import {
|
||||
imageContainerRefsSchema,
|
||||
imageContainerSchema,
|
||||
} from "../blocks/imageContainer"
|
||||
import { sysAssetRefsSchema, sysAssetSchema } from "../blocks/sysAsset"
|
||||
import {
|
||||
linkRefsUnionSchema,
|
||||
linkUnionSchema,
|
||||
transformPageLink,
|
||||
} from "../pageLinks"
|
||||
|
||||
export const contentSchema = z.object({
|
||||
typename: z
|
||||
.literal(SidebarEnums.blocks.Content)
|
||||
.optional()
|
||||
.default(SidebarEnums.blocks.Content),
|
||||
content: z
|
||||
.object({
|
||||
content: z.object({
|
||||
json: z.any(), // JSON
|
||||
embedded_itemsConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z
|
||||
.discriminatedUnion("__typename", [
|
||||
imageContainerSchema,
|
||||
sysAssetSchema,
|
||||
...linkUnionSchema.options,
|
||||
])
|
||||
.transform((data) => {
|
||||
const link = transformPageLink(data)
|
||||
if (link) {
|
||||
return link
|
||||
}
|
||||
return data
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
return {
|
||||
embedded_itemsConnection: data.content.embedded_itemsConnection,
|
||||
json: data.content.json,
|
||||
}
|
||||
}),
|
||||
})
|
||||
|
||||
const actualRefs = z.discriminatedUnion("__typename", [
|
||||
imageContainerRefsSchema,
|
||||
...linkRefsUnionSchema.options,
|
||||
])
|
||||
|
||||
type Ref = typeof actualRefs._type
|
||||
type Refs = {
|
||||
node: Ref
|
||||
}
|
||||
|
||||
export const contentRefsSchema = z.object({
|
||||
content: z
|
||||
.object({
|
||||
content: z.object({
|
||||
embedded_itemsConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z.discriminatedUnion("__typename", [
|
||||
sysAssetRefsSchema,
|
||||
...actualRefs.options,
|
||||
]),
|
||||
})
|
||||
),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
const filtered = data.content.embedded_itemsConnection.edges.filter(
|
||||
(block) => block.node.__typename !== ContentEnum.blocks.SysAsset
|
||||
) as unknown as Refs[] // TS issues with filtered arrays
|
||||
return filtered.map((block) => block.node.system)
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,14 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { DynamicContentEnum } from "../../../../types/dynamicContent"
|
||||
import { SidebarEnums } from "../../../../types/sidebar"
|
||||
|
||||
export const dynamicContentSchema = z.object({
|
||||
typename: z
|
||||
.literal(SidebarEnums.blocks.DynamicContent)
|
||||
.optional()
|
||||
.default(SidebarEnums.blocks.DynamicContent),
|
||||
dynamic_content: z.object({
|
||||
component: z.enum(DynamicContentEnum.Sidebar.enums),
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,57 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { JoinLoyaltyContactEnums } from "../../../../types/joinLoyaltyContact"
|
||||
import { SidebarEnums } from "../../../../types/sidebar"
|
||||
import { buttonSchema } from "../blocks/utils/buttonLinkSchema"
|
||||
import { linkConnectionRefsSchema } from "../blocks/utils/linkConnection"
|
||||
|
||||
export const contactSchema = z.object({
|
||||
contact: z.array(
|
||||
z
|
||||
.object({
|
||||
__typename: z
|
||||
.literal(JoinLoyaltyContactEnums.ContentStack.contact.ContentPage)
|
||||
.or(
|
||||
z.literal(JoinLoyaltyContactEnums.ContentStack.contact.LoyaltyPage)
|
||||
),
|
||||
typename: z
|
||||
.literal(JoinLoyaltyContactEnums.contact.Contact)
|
||||
.optional()
|
||||
.default(JoinLoyaltyContactEnums.contact.Contact),
|
||||
contact: z.object({
|
||||
contact_field: z.string(),
|
||||
display_text: z.string().optional().nullable().default(null),
|
||||
contact_footnote: z.string().optional().nullable(),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
return {
|
||||
__typename: data.__typename,
|
||||
typename: data.typename,
|
||||
contact_field: data.contact.contact_field,
|
||||
display_text: data.contact.display_text,
|
||||
footnote: data.contact.contact_footnote,
|
||||
}
|
||||
})
|
||||
),
|
||||
})
|
||||
|
||||
export const joinLoyaltyContactSchema = z.object({
|
||||
typename: z
|
||||
.literal(SidebarEnums.blocks.JoinLoyaltyContact)
|
||||
.optional()
|
||||
.default(SidebarEnums.blocks.JoinLoyaltyContact),
|
||||
join_loyalty_contact: z
|
||||
.object({
|
||||
button: buttonSchema,
|
||||
preamble: z.string().optional(),
|
||||
title: z.string().optional(),
|
||||
})
|
||||
.merge(contactSchema),
|
||||
})
|
||||
|
||||
export const joinLoyaltyContactRefsSchema = z.object({
|
||||
join_loyalty_contact: z.object({
|
||||
button: linkConnectionRefsSchema,
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,15 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { SidebarEnums } from "../../../../types/sidebar"
|
||||
import { shortcutsBlockSchema, shortcutsRefsSchema } from "../blocks/shortcuts"
|
||||
|
||||
export const quickLinksSchema = z
|
||||
.object({
|
||||
typename: z
|
||||
.literal(SidebarEnums.blocks.QuickLinks)
|
||||
.optional()
|
||||
.default(SidebarEnums.blocks.QuickLinks),
|
||||
})
|
||||
.merge(shortcutsBlockSchema)
|
||||
|
||||
export const quickLinksRefschema = shortcutsRefsSchema
|
||||
@@ -0,0 +1,56 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { scriptedCardThemeEnum } from "../../../../enums/scriptedCard"
|
||||
import { SidebarEnums } from "../../../../types/sidebar"
|
||||
import {
|
||||
cardBlockRefsSchema,
|
||||
cardBlockSchema,
|
||||
transformCardBlock,
|
||||
transformCardBlockRefs,
|
||||
} from "../blocks/cardsGrid"
|
||||
|
||||
export const scriptedCardsSchema = z.object({
|
||||
typename: z
|
||||
.literal(SidebarEnums.blocks.ScriptedCard)
|
||||
.optional()
|
||||
.default(SidebarEnums.blocks.ScriptedCard),
|
||||
scripted_card: z
|
||||
.object({
|
||||
theme: z.nativeEnum(scriptedCardThemeEnum).nullable(),
|
||||
scripted_cardConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: cardBlockSchema,
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
return {
|
||||
theme: data.theme,
|
||||
...transformCardBlock(data.scripted_cardConnection.edges[0].node),
|
||||
}
|
||||
}),
|
||||
})
|
||||
|
||||
export const scriptedCardRefschema = z.object({
|
||||
scripted_card: z
|
||||
.object({
|
||||
scripted_cardConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: cardBlockRefsSchema,
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
let card = null
|
||||
if (data.scripted_cardConnection.edges.length) {
|
||||
card = transformCardBlockRefs(
|
||||
data.scripted_cardConnection.edges[0].node
|
||||
)
|
||||
}
|
||||
return card
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,53 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { SidebarEnums } from "../../../../types/sidebar"
|
||||
import {
|
||||
teaserCardBlockRefsSchema,
|
||||
teaserCardBlockSchema,
|
||||
transformTeaserCardBlock,
|
||||
} from "../blocks/cards/teaserCard"
|
||||
import { transformCardBlockRefs } from "../blocks/cardsGrid"
|
||||
|
||||
export const teaserCardsSchema = z.object({
|
||||
typename: z
|
||||
.literal(SidebarEnums.blocks.TeaserCard)
|
||||
.optional()
|
||||
.default(SidebarEnums.blocks.TeaserCard),
|
||||
teaser_card: z
|
||||
.object({
|
||||
theme: z.enum(["featured", "default"]).nullable().default("default"),
|
||||
teaser_cardConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: teaserCardBlockSchema,
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
return {
|
||||
...transformTeaserCardBlock(data.teaser_cardConnection.edges[0].node),
|
||||
theme: data.theme,
|
||||
}
|
||||
}),
|
||||
})
|
||||
|
||||
export const teaserCardRefschema = z.object({
|
||||
teaser_card: z
|
||||
.object({
|
||||
teaser_cardConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: teaserCardBlockRefsSchema,
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
let card = null
|
||||
if (data.teaser_cardConnection.edges.length) {
|
||||
card = transformCardBlockRefs(data.teaser_cardConnection.edges[0].node)
|
||||
}
|
||||
return card
|
||||
}),
|
||||
})
|
||||
13
packages/trpc/lib/routers/contentstack/schemas/system.ts
Normal file
13
packages/trpc/lib/routers/contentstack/schemas/system.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { Lang } from "@scandic-hotels/common/constants/language"
|
||||
|
||||
export const systemSchema = z.object({
|
||||
content_type_uid: z.string(),
|
||||
locale: z.nativeEnum(Lang),
|
||||
uid: z.string(),
|
||||
})
|
||||
|
||||
export interface System {
|
||||
system: z.output<typeof systemSchema>
|
||||
}
|
||||
Reference in New Issue
Block a user