feat(SW-66, SW-348): search functionality and ui
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import * as pageLinks from "@/server/routers/contentstack/schemas/pageLinks"
|
||||
|
||||
import { removeMultipleSlashes } from "@/utils/url"
|
||||
|
||||
import { tempImageVaultAssetSchema } from "../imageVault"
|
||||
|
||||
import { HotelPageEnum } from "@/types/enums/hotelPage"
|
||||
|
||||
export const activitiesCard = 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(),
|
||||
heading: z.string(),
|
||||
open_in_new_tab: z.boolean(),
|
||||
scripted_title: z.string().optional(),
|
||||
hotel_page_activities_content_pageConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z.discriminatedUnion("__typename", [
|
||||
pageLinks.contentPageSchema,
|
||||
]),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
let contentPage = { href: "" }
|
||||
if (data.hotel_page_activities_content_pageConnection.edges.length) {
|
||||
const page =
|
||||
data.hotel_page_activities_content_pageConnection.edges[0].node
|
||||
if (page.web.original_url) {
|
||||
contentPage = {
|
||||
href: page.web.original_url,
|
||||
}
|
||||
} else {
|
||||
contentPage = {
|
||||
href: removeMultipleSlashes(`/${page.system.locale}/${page.url}`),
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
background_image: data.background_image,
|
||||
body_text: data.body_text,
|
||||
contentPage,
|
||||
cta_text: data.cta_text,
|
||||
heading: data.heading,
|
||||
open_in_new_tab: !!data.open_in_new_tab,
|
||||
scripted_title: data.scripted_title,
|
||||
}
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,162 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { tempImageVaultAssetSchema } from "../imageVault"
|
||||
import { systemSchema } from "../system"
|
||||
import { buttonSchema } from "./utils/buttonLinkSchema"
|
||||
import { linkConnectionRefsSchema } from "./utils/linkConnection"
|
||||
|
||||
import { BlocksEnums } from "@/types/enums/blocks"
|
||||
import { CardsGridEnum } from "@/types/enums/cardsGrid"
|
||||
|
||||
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),
|
||||
has_sidepeek_button: z.boolean().optional().default(false),
|
||||
heading: z.string().optional().default(""),
|
||||
is_content_card: z.boolean().optional().default(false),
|
||||
primary_button: buttonSchema,
|
||||
scripted_top_title: z.string().optional(),
|
||||
secondary_button: buttonSchema,
|
||||
sidepeek_button: z
|
||||
.object({
|
||||
call_to_action_text: z.string().optional(),
|
||||
})
|
||||
.optional(),
|
||||
system: systemSchema,
|
||||
title: z.string().optional(),
|
||||
})
|
||||
|
||||
const loyaltyCardBlockSchema = z.object({
|
||||
__typename: z.literal(CardsGridEnum.cards.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 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,
|
||||
]),
|
||||
})
|
||||
),
|
||||
}),
|
||||
layout: z.enum(["twoColumnGrid", "threeColumnGrid", "twoPlusOne"]),
|
||||
preamble: z.string().optional().default(""),
|
||||
theme: z.enum(["one", "two", "three"]).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 {
|
||||
__typename: card.node.__typename,
|
||||
backgroundImage: card.node.background_image,
|
||||
body_text: card.node.body_text,
|
||||
heading: card.node.heading,
|
||||
isContentCard: card.node.is_content_card,
|
||||
primaryButton: card.node.has_primary_button
|
||||
? card.node.primary_button
|
||||
: undefined,
|
||||
scripted_top_title: card.node.scripted_top_title,
|
||||
secondaryButton: card.node.has_secondary_button
|
||||
? card.node.secondary_button
|
||||
: undefined,
|
||||
sidePeekButton:
|
||||
card.node.has_sidepeek_button &&
|
||||
card.node.sidepeek_button?.call_to_action_text
|
||||
? {
|
||||
title: card.node.sidepeek_button.call_to_action_text,
|
||||
}
|
||||
: undefined,
|
||||
system: card.node.system,
|
||||
title: card.node.title,
|
||||
}
|
||||
} 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,
|
||||
}
|
||||
}
|
||||
}),
|
||||
}
|
||||
}),
|
||||
})
|
||||
|
||||
const cardBlockRefsSchema = z.object({
|
||||
__typename: z.literal(CardsGridEnum.cards.Card),
|
||||
primary_button: linkConnectionRefsSchema,
|
||||
secondary_button: linkConnectionRefsSchema,
|
||||
system: systemSchema,
|
||||
})
|
||||
|
||||
const loyaltyCardBlockRefsSchema = z.object({
|
||||
__typename: z.literal(CardsGridEnum.cards.LoyaltyCard),
|
||||
link: linkConnectionRefsSchema,
|
||||
system: systemSchema,
|
||||
})
|
||||
|
||||
export const cardGridRefsSchema = z.object({
|
||||
cards_grid: z
|
||||
.object({
|
||||
cardConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z.discriminatedUnion("__typename", [
|
||||
cardBlockRefsSchema,
|
||||
loyaltyCardBlockRefsSchema,
|
||||
]),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
return data.cardConnection.edges
|
||||
.map(({ node }) => {
|
||||
if (node.__typename === CardsGridEnum.cards.Card) {
|
||||
const cards = [node.system]
|
||||
if (node.primary_button) {
|
||||
cards.push(node.primary_button)
|
||||
}
|
||||
if (node.secondary_button) {
|
||||
cards.push(node.secondary_button)
|
||||
}
|
||||
return cards
|
||||
} else {
|
||||
const loyaltyCards = [node.system]
|
||||
if (node.link) {
|
||||
loyaltyCards.push(node.link)
|
||||
}
|
||||
return loyaltyCards
|
||||
}
|
||||
})
|
||||
.flat()
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,83 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import * as pageLinks from "@/server/routers/contentstack/schemas/pageLinks"
|
||||
|
||||
import { imageRefsSchema, imageSchema } from "./image"
|
||||
import {
|
||||
imageContainerRefsSchema,
|
||||
imageContainerSchema,
|
||||
} from "./imageContainer"
|
||||
|
||||
import { BlocksEnums } from "@/types/enums/blocks"
|
||||
import { ContentEnum } from "@/types/enums/content"
|
||||
|
||||
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,
|
||||
imageSchema,
|
||||
pageLinks.accountPageSchema,
|
||||
pageLinks.contentPageSchema,
|
||||
pageLinks.hotelPageSchema,
|
||||
pageLinks.loyaltyPageSchema,
|
||||
])
|
||||
.transform((data) => {
|
||||
const link = pageLinks.transform(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", [
|
||||
imageRefsSchema,
|
||||
imageContainerRefsSchema,
|
||||
pageLinks.accountPageRefSchema,
|
||||
pageLinks.contentPageRefSchema,
|
||||
pageLinks.hotelPageRefSchema,
|
||||
pageLinks.loyaltyPageRefSchema,
|
||||
]),
|
||||
})
|
||||
),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
.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,23 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import * as pageLinks from "@/server/routers/contentstack/schemas/pageLinks"
|
||||
|
||||
import { imageSchema } from "./image"
|
||||
import { imageContainerSchema } from "./imageContainer"
|
||||
|
||||
export const contentEmbedsSchema = z
|
||||
.discriminatedUnion("__typename", [
|
||||
imageContainerSchema,
|
||||
imageSchema,
|
||||
pageLinks.accountPageSchema,
|
||||
pageLinks.contentPageSchema,
|
||||
pageLinks.hotelPageSchema,
|
||||
pageLinks.loyaltyPageSchema,
|
||||
])
|
||||
.transform((data) => {
|
||||
const link = pageLinks.transform(data)
|
||||
if (link) {
|
||||
return link
|
||||
}
|
||||
return data
|
||||
})
|
||||
@@ -0,0 +1,79 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import * as pageLinks from "@/server/routers/contentstack/schemas/pageLinks"
|
||||
|
||||
import { BlocksEnums } from "@/types/enums/blocks"
|
||||
import { DynamicContentEnum } from "@/types/enums/dynamicContent"
|
||||
|
||||
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: z
|
||||
.discriminatedUnion("__typename", [
|
||||
pageLinks.accountPageSchema,
|
||||
pageLinks.contentPageSchema,
|
||||
pageLinks.hotelPageSchema,
|
||||
pageLinks.loyaltyPageSchema,
|
||||
])
|
||||
.transform((data) => {
|
||||
const link = pageLinks.transform(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: z.discriminatedUnion("__typename", [
|
||||
pageLinks.accountPageRefSchema,
|
||||
pageLinks.contentPageRefSchema,
|
||||
pageLinks.hotelPageRefSchema,
|
||||
pageLinks.loyaltyPageRefSchema,
|
||||
]),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
if (data.linkConnection?.edges.length) {
|
||||
return data.linkConnection.edges[0].node.system
|
||||
}
|
||||
return null
|
||||
}),
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,27 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { ContentEnum } from "@/types/enums/content"
|
||||
|
||||
export const imageSchema = z.object({
|
||||
__typename: z.literal(ContentEnum.blocks.SysAsset),
|
||||
description: z.string().optional(),
|
||||
dimension: z.object({
|
||||
height: z.number(),
|
||||
width: z.number(),
|
||||
}),
|
||||
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(),
|
||||
}),
|
||||
title: z.string().optional(),
|
||||
url: z.string().optional(),
|
||||
})
|
||||
|
||||
export const imageRefsSchema = z.object({
|
||||
__typename: z.literal(ContentEnum.blocks.SysAsset),
|
||||
})
|
||||
@@ -0,0 +1,21 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { tempImageVaultAssetSchema } from "../imageVault"
|
||||
import { systemSchema } from "../system"
|
||||
|
||||
import { ContentEnum } from "@/types/enums/content"
|
||||
|
||||
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,83 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import * as pageLinks from "@/server/routers/contentstack/schemas/pageLinks"
|
||||
|
||||
import { BlocksEnums } from "@/types/enums/blocks"
|
||||
|
||||
export const shortcutsSchema = z.object({
|
||||
typename: z
|
||||
.literal(BlocksEnums.block.Shortcuts)
|
||||
.optional()
|
||||
.default(BlocksEnums.block.Shortcuts),
|
||||
shortcuts: z.object({
|
||||
subtitle: z.string().nullable(),
|
||||
title: z.string().nullable(),
|
||||
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: z
|
||||
.discriminatedUnion("__typename", [
|
||||
pageLinks.accountPageSchema,
|
||||
pageLinks.contentPageSchema,
|
||||
pageLinks.loyaltyPageSchema,
|
||||
])
|
||||
.transform((data) => {
|
||||
const link = pageLinks.transform(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,
|
||||
}
|
||||
})
|
||||
}),
|
||||
}),
|
||||
})
|
||||
|
||||
export const shortcutsRefsSchema = z.object({
|
||||
shortcuts: z.object({
|
||||
shortcuts: z
|
||||
.array(
|
||||
z.object({
|
||||
linkConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z.discriminatedUnion("__typename", [
|
||||
pageLinks.accountPageRefSchema,
|
||||
pageLinks.contentPageRefSchema,
|
||||
pageLinks.loyaltyPageRefSchema,
|
||||
]),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
)
|
||||
.transform((data) =>
|
||||
data
|
||||
.map((shortcut) => {
|
||||
return shortcut.linkConnection.edges.map(({ node }) => node.system)
|
||||
})
|
||||
.flat()
|
||||
),
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,84 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import * as pageLinks from "@/server/routers/contentstack/schemas/pageLinks"
|
||||
import { imageRefsSchema, imageSchema } from "./image"
|
||||
|
||||
import { BlocksEnums } from "@/types/enums/blocks"
|
||||
import { ContentEnum } from "@/types/enums/content"
|
||||
|
||||
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", [
|
||||
imageSchema,
|
||||
pageLinks.contentPageSchema,
|
||||
pageLinks.hotelPageSchema,
|
||||
pageLinks.loyaltyPageSchema,
|
||||
])
|
||||
.transform((data) => {
|
||||
const link = pageLinks.transform(data)
|
||||
if (link) {
|
||||
return link
|
||||
}
|
||||
return data
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
|
||||
const actualRefs = z.discriminatedUnion("__typename", [
|
||||
pageLinks.contentPageRefSchema,
|
||||
pageLinks.hotelPageRefSchema,
|
||||
pageLinks.loyaltyPageRefSchema,
|
||||
])
|
||||
|
||||
type Refs = {
|
||||
node: z.TypeOf<typeof actualRefs>
|
||||
}
|
||||
|
||||
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", [
|
||||
imageRefsSchema,
|
||||
...actualRefs.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,25 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { imageSchema } from "./image"
|
||||
|
||||
import { BlocksEnums } from "@/types/enums/blocks"
|
||||
|
||||
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", [imageSchema]),
|
||||
})
|
||||
),
|
||||
totalCount: z.number(),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
@@ -0,0 +1,54 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import * as pageLinks from "@/server/routers/contentstack/schemas/pageLinks"
|
||||
|
||||
export const buttonSchema = z
|
||||
.object({
|
||||
cta_text: z.string().optional().default(""),
|
||||
open_in_new_tab: z.boolean().default(false),
|
||||
external_link: z
|
||||
.object({
|
||||
href: z.string().optional().default(""),
|
||||
title: z.string().optional(),
|
||||
})
|
||||
.optional(),
|
||||
linkConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z
|
||||
.discriminatedUnion("__typename", [
|
||||
pageLinks.accountPageSchema,
|
||||
pageLinks.contentPageSchema,
|
||||
pageLinks.loyaltyPageSchema,
|
||||
])
|
||||
.transform((data) => {
|
||||
const link = pageLinks.transform(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,
|
||||
isExternal: false,
|
||||
openInNewTab: data.open_in_new_tab,
|
||||
title: data.cta_text ? data.cta_text : link.title,
|
||||
}
|
||||
} 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,25 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import * as pageLinks from "@/server/routers/contentstack/schemas/pageLinks"
|
||||
|
||||
export const linkConnectionRefsSchema = z
|
||||
.object({
|
||||
linkConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z.discriminatedUnion("__typename", [
|
||||
pageLinks.accountPageRefSchema,
|
||||
pageLinks.contentPageRefSchema,
|
||||
pageLinks.loyaltyPageRefSchema,
|
||||
]),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
if (!data.linkConnection.edges.length) {
|
||||
return null
|
||||
}
|
||||
|
||||
return data.linkConnection.edges[0].node.system
|
||||
})
|
||||
@@ -1,5 +1,7 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { makeImageVaultImage } from "@/utils/imageVault"
|
||||
|
||||
const metaData = z.object({
|
||||
DefinitionType: z.number().nullable().optional(),
|
||||
Description: z.string().nullable(),
|
||||
@@ -120,3 +122,21 @@ export const imageVaultAssetTransformedSchema = imageVaultAssetSchema.transform(
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
export const tempImageVaultAssetSchema = imageVaultAssetSchema
|
||||
.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
|
||||
})
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { systemSchema } from "./system"
|
||||
|
||||
export const getMetaDataSchema = z.object({
|
||||
breadcrumbsTitle: z.string().optional(),
|
||||
title: z.string().optional(),
|
||||
description: z.string().optional(),
|
||||
imageConnection: z
|
||||
.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z.object({
|
||||
url: z.string(),
|
||||
}),
|
||||
})
|
||||
),
|
||||
})
|
||||
.optional(),
|
||||
})
|
||||
|
||||
export const page = z.object({
|
||||
web: z.object({
|
||||
seo_metadata: z.object({
|
||||
title: z.string().optional(),
|
||||
description: z.string().optional(),
|
||||
imageConnection: z
|
||||
.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z.object({
|
||||
url: z.string(),
|
||||
}),
|
||||
})
|
||||
),
|
||||
})
|
||||
.optional(),
|
||||
}),
|
||||
breadcrumbs: z.object({
|
||||
title: z.string(),
|
||||
}),
|
||||
}),
|
||||
system: systemSchema,
|
||||
})
|
||||
|
||||
export type Page = z.infer<typeof page>
|
||||
@@ -0,0 +1,120 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { removeMultipleSlashes } from "@/utils/url"
|
||||
|
||||
import { systemSchema } from "./system"
|
||||
|
||||
import { ContentEnum } from "@/types/enums/content"
|
||||
|
||||
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(""),
|
||||
}),
|
||||
})
|
||||
)
|
||||
|
||||
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 hotelPageSchema = z
|
||||
.object({
|
||||
__typename: z.literal(ContentEnum.blocks.HotelPage),
|
||||
})
|
||||
.merge(extendedPageLinkSchema)
|
||||
|
||||
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,
|
||||
})
|
||||
|
||||
type Data =
|
||||
| z.output<typeof accountPageSchema>
|
||||
| z.output<typeof contentPageSchema>
|
||||
| z.output<typeof hotelPageSchema>
|
||||
| z.output<typeof loyaltyPageSchema>
|
||||
| Object
|
||||
|
||||
export function transform(data: Data) {
|
||||
if (data && "__typename" in data) {
|
||||
switch (data.__typename) {
|
||||
case ContentEnum.blocks.AccountPage:
|
||||
case ContentEnum.blocks.HotelPage:
|
||||
return {
|
||||
__typename: data.__typename,
|
||||
system: data.system,
|
||||
title: data.title,
|
||||
url: removeMultipleSlashes(`/${data.system.locale}/${data.url}`),
|
||||
}
|
||||
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
|
||||
? removeMultipleSlashes(data.web.original_url)
|
||||
: removeMultipleSlashes(`/${data.system.locale}/${data.url}`),
|
||||
web: data.web,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type RefData =
|
||||
| z.output<typeof accountPageRefSchema>
|
||||
| z.output<typeof contentPageRefSchema>
|
||||
| z.output<typeof hotelPageRefSchema>
|
||||
| z.output<typeof loyaltyPageRefSchema>
|
||||
| Object
|
||||
|
||||
export function transformRef(data: RefData) {
|
||||
if (data && "__typename" in data) {
|
||||
switch (data.__typename) {
|
||||
case ContentEnum.blocks.AccountPage:
|
||||
case ContentEnum.blocks.ContentPage:
|
||||
case ContentEnum.blocks.HotelPage:
|
||||
case ContentEnum.blocks.LoyaltyPage:
|
||||
return data.system
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import * as pageLinks from "@/server/routers/contentstack/schemas/pageLinks"
|
||||
|
||||
import { imageRefsSchema, imageSchema } from "../blocks/image"
|
||||
import {
|
||||
imageContainerRefsSchema,
|
||||
imageContainerSchema,
|
||||
} from "../blocks/imageContainer"
|
||||
|
||||
import { ContentEnum } from "@/types/enums/content"
|
||||
import { SidebarEnums } from "@/types/enums/sidebar"
|
||||
import { System } from "@/types/requests/system"
|
||||
|
||||
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,
|
||||
imageSchema,
|
||||
pageLinks.contentPageSchema,
|
||||
pageLinks.loyaltyPageSchema,
|
||||
])
|
||||
.transform((data) => {
|
||||
const link = pageLinks.transform(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,
|
||||
pageLinks.contentPageRefSchema,
|
||||
pageLinks.loyaltyPageRefSchema,
|
||||
])
|
||||
|
||||
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", [
|
||||
imageRefsSchema,
|
||||
...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/enums/dynamicContent"
|
||||
import { SidebarEnums } from "@/types/enums/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,58 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { buttonSchema } from "../blocks/utils/buttonLinkSchema"
|
||||
import { linkConnectionRefsSchema } from "../blocks/utils/linkConnection"
|
||||
|
||||
import { JoinLoyaltyContactEnums } from "@/types/enums/joinLoyaltyContact"
|
||||
import { SidebarEnums } from "@/types/enums/sidebar"
|
||||
|
||||
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),
|
||||
footnote: z.string().optional().nullable().default(null),
|
||||
}),
|
||||
})
|
||||
.transform((data) => {
|
||||
return {
|
||||
__typename: data.__typename,
|
||||
typename: data.typename,
|
||||
contact_field: data.contact.contact_field,
|
||||
display_text: data.contact.display_text,
|
||||
footnote: data.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,9 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { Lang } from "@/constants/languages"
|
||||
|
||||
export const systemSchema = z.object({
|
||||
content_type_uid: z.string(),
|
||||
locale: z.nativeEnum(Lang),
|
||||
uid: z.string(),
|
||||
})
|
||||
Reference in New Issue
Block a user