Merged in feat/SW-1450-destination-page-cs-components (pull request #1204)

feat(SW-1450): added components in destination pages from cs

* feat(SW-1450): added components in destination pages from cs

* feat(SW-1450): added correct refs and removed classNames


Approved-by: Fredrik Thorsson
This commit is contained in:
Erik Tiekstra
2025-01-24 12:06:43 +00:00
parent 7343d873c2
commit a88a033e30
45 changed files with 1237 additions and 195 deletions

View File

@@ -1,25 +1,180 @@
import { z } from "zod"
import * as pageLinks from "@/server/routers/contentstack/schemas/pageLinks"
import { tempImageVaultAssetSchema } from "../schemas/imageVault"
import { systemSchema } from "../schemas/system"
export const destinationCityPageSchema = z.object({
destination_city_page: z.object({
title: z.string(),
system: systemSchema.merge(
z.object({
created_at: z.string(),
updated_at: z.string(),
})
),
}),
trackingProps: z.object({
url: z.string(),
}),
})
import type { ImageVaultAsset } from "@/types/components/imageVault"
import {
TrackingChannelEnum,
type TrackingSDKPageData,
} from "@/types/components/tracking"
import { Country } from "@/types/enums/country"
export const destinationCityPageSchema = z
.object({
destination_city_page: z.object({
title: z.string(),
destination_settings: z
.object({
countryConnection: z
.object({
edges: z.array(
z.object({
node: z.object({
destination_settings: z.object({
country: z.nativeEnum(Country),
}),
}),
})
),
})
.transform(
(countryConnection) =>
countryConnection.edges[0].node.destination_settings.country
),
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(),
})
.transform(
({
countryConnection: country,
city_denmark,
city_finland,
city_germany,
city_norway,
city_poland,
city_sweden,
}) => {
switch (country) {
case Country.Denmark:
return { country, city: city_denmark }
case Country.Finland:
return { country, city: city_finland }
case Country.Germany:
return { country, city: city_germany }
case Country.Poland:
return { country, city: city_poland }
case Country.Norway:
return { country, city: city_norway }
case Country.Sweden:
return { country, city: city_sweden }
default:
throw new Error(`Invalid country: ${country}`)
}
}
),
heading: z.string(),
preamble: z.string(),
experiences: z
.object({
destination_experiences: z.array(z.string()),
})
.transform(({ destination_experiences }) => destination_experiences),
images: z
.array(z.object({ image: tempImageVaultAssetSchema }))
.transform((images) =>
images
.map((image) => image.image)
.filter((image): image is ImageVaultAsset => !!image)
),
has_sidepeek: z.boolean().default(false),
sidepeek_button_text: z.string().default(""),
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", [
pageLinks.accountPageSchema,
pageLinks.contentPageSchema,
pageLinks.hotelPageSchema,
pageLinks.loyaltyPageSchema,
pageLinks.collectionPageSchema,
])
.transform((data) => {
const link = pageLinks.transform(data)
if (link) {
return link
}
return data
}),
})
),
}),
}),
}),
system: systemSchema.merge(
z.object({
created_at: z.string(),
updated_at: z.string(),
})
),
}),
trackingProps: z.object({
url: z.string(),
}),
})
.transform((data) => {
const destinationCityPage = data.destination_city_page
const system = destinationCityPage.system
const trackingUrl = data.trackingProps.url
const tracking: TrackingSDKPageData = {
pageId: system.uid,
domainLanguage: system.locale,
publishDate: system.updated_at,
createDate: system.created_at,
channel: TrackingChannelEnum["destination-page"],
pageType: "staticcontentpage",
pageName: trackingUrl,
siteSections: trackingUrl,
siteVersion: "new-web",
}
return {
destinationCityPage,
tracking,
}
})
/** REFS */
export const destinationCityPageRefsSchema = z.object({
destination_city_page: z.object({
destination_settings: z.object({
countryConnection: z.object({
edges: z.array(
z.object({
node: pageLinks.destinationCountryPageRefSchema,
})
),
}),
}),
sidepeek_content: z.object({
content: z.object({
embedded_itemsConnection: z.object({
edges: z.array(
z.object({
node: z.discriminatedUnion("__typename", [
pageLinks.accountPageRefSchema,
pageLinks.contentPageRefSchema,
pageLinks.hotelPageRefSchema,
pageLinks.loyaltyPageRefSchema,
pageLinks.collectionPageRefSchema,
]),
})
),
}),
}),
}),
system: systemSchema,
}),
})

View File

@@ -20,11 +20,8 @@ import {
getDestinationCityPageRefsSuccessCounter,
getDestinationCityPageSuccessCounter,
} from "./telemetry"
import { generatePageTags } from "./utils"
import {
TrackingChannelEnum,
type TrackingSDKPageData,
} from "@/types/components/tracking"
import type {
GetDestinationCityPageData,
GetDestinationCityPageRefsSchema,
@@ -91,6 +88,8 @@ export const destinationCityPageQueryRouter = router({
JSON.stringify({ query: { lang, uid } })
)
const tags = generatePageTags(validatedRefsData.data, lang)
getDestinationCityPageCounter.add(1, { lang, uid: `${uid}` })
console.info(
"contentstack.destinationCityPage start",
@@ -107,7 +106,7 @@ export const destinationCityPageQueryRouter = router({
{
cache: "force-cache",
next: {
tags: [generateTag(lang, uid)],
tags,
},
}
)
@@ -129,22 +128,22 @@ export const destinationCityPageQueryRouter = router({
throw notFoundError
}
const destinationCityPage = destinationCityPageSchema.safeParse(
const validatedDestinationCityPage = destinationCityPageSchema.safeParse(
response.data
)
if (!destinationCityPage.success) {
if (!validatedDestinationCityPage.success) {
getDestinationCityPageFailCounter.add(1, {
lang,
uid: `${uid}`,
error_type: "validation_error",
error: JSON.stringify(destinationCityPage.error),
error: JSON.stringify(validatedDestinationCityPage.error),
})
console.error(
"contentstack.destinationCityPage validation error",
JSON.stringify({
query: { lang, uid },
error: destinationCityPage.error,
error: validatedDestinationCityPage.error,
})
)
return null
@@ -158,22 +157,6 @@ export const destinationCityPageQueryRouter = router({
})
)
const system = destinationCityPage.data.destination_city_page.system
const tracking: TrackingSDKPageData = {
pageId: system.uid,
domainLanguage: lang,
publishDate: system.updated_at,
createDate: system.created_at,
channel: TrackingChannelEnum["destination-page"],
pageType: "staticcontentpage",
pageName: destinationCityPage.data.trackingProps.url,
siteSections: destinationCityPage.data.trackingProps.url,
siteVersion: "new-web",
}
return {
destinationCityPage: destinationCityPage.data.destination_city_page,
tracking,
}
return validatedDestinationCityPage.data
}),
})

View File

@@ -0,0 +1,37 @@
import { generateTag, generateTagsFromSystem } from "@/utils/generateTag"
import type { System } from "@/types/requests/system"
import type { GetDestinationCityPageRefsSchema } from "@/types/trpc/routers/contentstack/destinationCityPage"
import type { Lang } from "@/constants/languages"
export function generatePageTags(
validatedData: GetDestinationCityPageRefsSchema,
lang: Lang
): string[] {
const connections = getConnections(validatedData)
return [
generateTagsFromSystem(lang, connections),
generateTag(lang, validatedData.destination_city_page.system.uid),
].flat()
}
export function getConnections({
destination_city_page,
}: GetDestinationCityPageRefsSchema) {
const connections: System["system"][] = [destination_city_page.system]
connections.push(
destination_city_page.destination_settings.countryConnection.edges[0].node
.system
)
if (destination_city_page.sidepeek_content) {
destination_city_page.sidepeek_content.content.embedded_itemsConnection.edges.forEach(
({ node }) => {
connections.push(node.system)
}
)
}
return connections
}

View File

@@ -1,25 +1,120 @@
import { z } from "zod"
import * as pageLinks from "@/server/routers/contentstack/schemas/pageLinks"
import { tempImageVaultAssetSchema } from "../schemas/imageVault"
import { systemSchema } from "../schemas/system"
export const destinationCountryPageSchema = z.object({
destination_country_page: z.object({
title: z.string(),
system: systemSchema.merge(
z.object({
created_at: z.string(),
updated_at: z.string(),
})
),
}),
trackingProps: z.object({
url: z.string(),
}),
})
import type { ImageVaultAsset } from "@/types/components/imageVault"
import {
TrackingChannelEnum,
type TrackingSDKPageData,
} from "@/types/components/tracking"
import { Country } from "@/types/enums/country"
export const destinationCountryPageSchema = z
.object({
destination_country_page: z.object({
title: z.string(),
destination_settings: z.object({
country: z.nativeEnum(Country),
}),
heading: z.string(),
preamble: z.string(),
experiences: z
.object({
destination_experiences: z.array(z.string()),
})
.transform(({ destination_experiences }) => destination_experiences),
images: z
.array(z.object({ image: tempImageVaultAssetSchema }))
.transform((images) =>
images
.map((image) => image.image)
.filter((image): image is ImageVaultAsset => !!image)
),
has_sidepeek: z.boolean().default(false),
sidepeek_button_text: z.string().default(""),
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", [
pageLinks.accountPageSchema,
pageLinks.contentPageSchema,
pageLinks.hotelPageSchema,
pageLinks.loyaltyPageSchema,
pageLinks.collectionPageSchema,
])
.transform((data) => {
const link = pageLinks.transform(data)
if (link) {
return link
}
return data
}),
})
),
}),
}),
}),
system: systemSchema.merge(
z.object({
created_at: z.string(),
updated_at: z.string(),
})
),
}),
trackingProps: z.object({
url: z.string(),
}),
})
.transform((data) => {
const countryPageData = data.destination_country_page
const system = countryPageData.system
const trackingUrl = data.trackingProps.url
const tracking: TrackingSDKPageData = {
pageId: system.uid,
domainLanguage: system.locale,
publishDate: system.updated_at,
createDate: system.created_at,
channel: TrackingChannelEnum["destination-page"],
pageType: "staticcontentpage",
pageName: trackingUrl,
siteSections: trackingUrl,
siteVersion: "new-web",
}
return {
destinationCountryPage: countryPageData,
tracking,
}
})
/** REFS */
export const destinationCountryPageRefsSchema = z.object({
destination_country_page: z.object({
sidepeek_content: z.object({
content: z.object({
embedded_itemsConnection: z.object({
edges: z.array(
z.object({
node: z.discriminatedUnion("__typename", [
pageLinks.accountPageRefSchema,
pageLinks.contentPageRefSchema,
pageLinks.hotelPageRefSchema,
pageLinks.loyaltyPageRefSchema,
pageLinks.collectionPageRefSchema,
]),
})
),
}),
}),
}),
system: systemSchema,
}),
})

View File

@@ -20,11 +20,8 @@ import {
getDestinationCountryPageRefsSuccessCounter,
getDestinationCountryPageSuccessCounter,
} from "./telemetry"
import { generatePageTags } from "./utils"
import {
TrackingChannelEnum,
type TrackingSDKPageData,
} from "@/types/components/tracking"
import type {
GetDestinationCountryPageData,
GetDestinationCountryPageRefsSchema,
@@ -91,6 +88,8 @@ export const destinationCountryPageQueryRouter = router({
JSON.stringify({ query: { lang, uid } })
)
const tags = generatePageTags(validatedRefsData.data, lang)
getDestinationCountryPageCounter.add(1, { lang, uid: `${uid}` })
console.info(
"contentstack.destinationCountryPage start",
@@ -107,7 +106,7 @@ export const destinationCountryPageQueryRouter = router({
{
cache: "force-cache",
next: {
tags: [generateTag(lang, uid)],
tags,
},
}
)
@@ -158,23 +157,6 @@ export const destinationCountryPageQueryRouter = router({
})
)
const system = destinationCountryPage.data.destination_country_page.system
const tracking: TrackingSDKPageData = {
pageId: system.uid,
domainLanguage: lang,
publishDate: system.updated_at,
createDate: system.created_at,
channel: TrackingChannelEnum["destination-page"],
pageType: "staticcontentpage",
pageName: destinationCountryPage.data.trackingProps.url,
siteSections: destinationCountryPage.data.trackingProps.url,
siteVersion: "new-web",
}
return {
destinationCountryPage:
destinationCountryPage.data.destination_country_page,
tracking,
}
return destinationCountryPage.data
}),
})

View File

@@ -0,0 +1,32 @@
import { generateTag, generateTagsFromSystem } from "@/utils/generateTag"
import type { System } from "@/types/requests/system"
import type { GetDestinationCountryPageRefsSchema } from "@/types/trpc/routers/contentstack/destinationCountryPage"
import type { Lang } from "@/constants/languages"
export function generatePageTags(
validatedData: GetDestinationCountryPageRefsSchema,
lang: Lang
): string[] {
const connections = getConnections(validatedData)
return [
generateTagsFromSystem(lang, connections),
generateTag(lang, validatedData.destination_country_page.system.uid),
].flat()
}
export function getConnections({
destination_country_page,
}: GetDestinationCountryPageRefsSchema) {
const connections: System["system"][] = [destination_country_page.system]
if (destination_country_page.sidepeek_content) {
destination_country_page.sidepeek_content.content.embedded_itemsConnection.edges.forEach(
({ node }) => {
connections.push(node.system)
}
)
}
return connections
}

View File

@@ -52,6 +52,33 @@ export const contentPageRefSchema = z.object({
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 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 destinationOverviewPageRefSchema = z.object({
__typename: z.literal(ContentEnum.blocks.DestinationOverviewPage),
system: systemSchema,
})
export const hotelPageSchema = z
.object({
__typename: z.literal(ContentEnum.blocks.HotelPage),