diff --git a/components/ContentType/HotelPage/SidePeeks/WellnessAndExercise/index.tsx b/components/ContentType/HotelPage/SidePeeks/WellnessAndExercise/index.tsx index 97ac09a91..6d690a643 100644 --- a/components/ContentType/HotelPage/SidePeeks/WellnessAndExercise/index.tsx +++ b/components/ContentType/HotelPage/SidePeeks/WellnessAndExercise/index.tsx @@ -14,7 +14,8 @@ import type { WellnessAndExerciseSidePeekProps } from "@/types/components/hotelP export default async function WellnessAndExerciseSidePeek({ healthFacilities, - buttonUrl, + wellnessExerciseButton, + spaPage, }: WellnessAndExerciseSidePeekProps) { const intl = await getIntl() const lang = getLang() @@ -29,13 +30,26 @@ export default async function WellnessAndExerciseSidePeek({ ))} - {buttonUrl && ( + {(spaPage || wellnessExerciseButton) && (
- + {spaPage && ( + + )} + {wellnessExerciseButton && ( + + )}
)} diff --git a/components/ContentType/HotelPage/SidePeeks/WellnessAndExercise/wellnessAndExercise.module.css b/components/ContentType/HotelPage/SidePeeks/WellnessAndExercise/wellnessAndExercise.module.css index 11a410f13..f6f47761e 100644 --- a/components/ContentType/HotelPage/SidePeeks/WellnessAndExercise/wellnessAndExercise.module.css +++ b/components/ContentType/HotelPage/SidePeeks/WellnessAndExercise/wellnessAndExercise.module.css @@ -15,4 +15,6 @@ position: absolute; left: 0; bottom: 0; + display: grid; + gap: var(--Spacing-x2); } diff --git a/components/ContentType/HotelPage/index.tsx b/components/ContentType/HotelPage/index.tsx index 992cdc2d2..180a5d16d 100644 --- a/components/ContentType/HotelPage/index.tsx +++ b/components/ContentType/HotelPage/index.tsx @@ -9,7 +9,6 @@ import Breadcrumbs from "@/components/Breadcrumbs" import SidePeekProvider from "@/components/SidePeeks/SidePeekProvider" import Alert from "@/components/TempDesignSystem/Alert" import BreadcrumbsSkeleton from "@/components/TempDesignSystem/Breadcrumbs/BreadcrumbsSkeleton" -import SidePeek from "@/components/TempDesignSystem/SidePeek" import { getIntl } from "@/i18n" import { getLang } from "@/i18n/serverContext" import { getRestaurantHeading } from "@/utils/facilityCards" @@ -43,6 +42,10 @@ import type { HotelPageProps } from "@/types/components/hotelPage/hotelPage" import { HotelHashValues } from "@/types/components/hotelPage/tabNavigation" import type { Facility } from "@/types/hotel" import { PageContentTypeEnum } from "@/types/requests/contentType" +import type { + ActivitiesCard, + SpaPage, +} from "@/types/trpc/routers/contentstack/hotelPage" export default async function HotelPage({ hotelId }: HotelPageProps) { const lang = getLang() @@ -83,7 +86,8 @@ export default async function HotelPage({ hotelId }: HotelPageProps) { const restaurants = hotelData.included?.restaurants || [] const images = gallery?.smallerImages const description = hotelContent.texts.descriptions.medium - const activitiesCard = content?.[0]?.upcoming_activities_card || null + + const { spaPage, activitiesCard } = content const facilities: Facility[] = [ { @@ -162,7 +166,10 @@ export default async function HotelPage({ hotelId }: HotelPageProps) { ) : null} - + {faq.accordions.length > 0 && ( )} @@ -200,10 +207,15 @@ export default async function HotelPage({ hotelId }: HotelPageProps) { ecoLabels={hotelFacts.ecoLabels} descriptions={hotelContent.texts} /> - + {activitiesCard && ( - + )} { + let spaPage: SpaPage | undefined + let activitiesCard: ActivitiesCard | undefined + data?.map((block) => { + switch (block.typename) { + case HotelPageEnum.ContentStack.blocks.ActivitiesCard: + activitiesCard = block + break + case HotelPageEnum.ContentStack.blocks.SpaPage: + spaPage = block + break + default: + break + } + }) + return { spaPage, activitiesCard } + }), faq: hotelFaqSchema, hotel_page_id: z.string(), title: z.string(), @@ -40,14 +70,21 @@ export const hotelPageSchema = z.object({ }) /** REFS */ -const hotelPageActiviesCardRefs = z +const hotelPageActivitiesCardRefs = z .object({ __typename: z.literal(HotelPageEnum.ContentStack.blocks.ActivitiesCard), }) .merge(activitiesCardRefSchema) +const hotelPageSpaPageRefs = z + .object({ + __typename: z.literal(HotelPageEnum.ContentStack.blocks.SpaPage), + }) + .merge(spaPageRefSchema) + const hotelPageBlockRefsItem = z.discriminatedUnion("__typename", [ - hotelPageActiviesCardRefs, + hotelPageActivitiesCardRefs, + hotelPageSpaPageRefs, ]) export const hotelPageRefsSchema = z.object({ diff --git a/server/routers/contentstack/schemas/blocks/spaPage.ts b/server/routers/contentstack/schemas/blocks/spaPage.ts new file mode 100644 index 000000000..f353bd736 --- /dev/null +++ b/server/routers/contentstack/schemas/blocks/spaPage.ts @@ -0,0 +1,68 @@ +import { z } from "zod" + +import * as pageLinks from "@/server/routers/contentstack/schemas/pageLinks" + +import { removeMultipleSlashes } from "@/utils/url" + +import { HotelPageEnum } from "@/types/enums/hotelPage" + +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", [ + pageLinks.contentPageRefSchema, + pageLinks.collectionPageRefSchema, + ]), + }) + ), + }), + }) + .transform((data) => { + return data.pageConnection.edges.flatMap(({ node }) => node.system) || [] + }), +}) diff --git a/types/components/hotelPage/facilities.ts b/types/components/hotelPage/facilities.ts index 5c753797a..dcc58651f 100644 --- a/types/components/hotelPage/facilities.ts +++ b/types/components/hotelPage/facilities.ts @@ -4,7 +4,7 @@ import type { CardProps } from "@/components/TempDesignSystem/Card/card" export type FacilitiesProps = { facilities: Facility[] - activitiesCard: ActivityCard | null + activitiesCard?: ActivityCard } export type FacilityImage = { diff --git a/types/components/hotelPage/sidepeek/wellnessAndExercise.ts b/types/components/hotelPage/sidepeek/wellnessAndExercise.ts index 828f3ee8b..4e70b9210 100644 --- a/types/components/hotelPage/sidepeek/wellnessAndExercise.ts +++ b/types/components/hotelPage/sidepeek/wellnessAndExercise.ts @@ -2,5 +2,9 @@ import type { Hotel } from "@/types/hotel" export type WellnessAndExerciseSidePeekProps = { healthFacilities: Hotel["healthFacilities"] - buttonUrl?: string + wellnessExerciseButton?: string + spaPage?: { + buttonCTA: string + url: string + } } diff --git a/types/enums/hotelPage.ts b/types/enums/hotelPage.ts index bfae4bfbe..8cc5f8839 100644 --- a/types/enums/hotelPage.ts +++ b/types/enums/hotelPage.ts @@ -3,6 +3,7 @@ export namespace HotelPageEnum { export const enum blocks { Faq = "HotelPageFaq", ActivitiesCard = "HotelPageContentUpcomingActivitiesCard", + SpaPage = "HotelPageContentSpaPage", } } } diff --git a/types/trpc/routers/contentstack/hotelPage.ts b/types/trpc/routers/contentstack/hotelPage.ts index 6b98f5ca2..7a983d419 100644 --- a/types/trpc/routers/contentstack/hotelPage.ts +++ b/types/trpc/routers/contentstack/hotelPage.ts @@ -7,13 +7,16 @@ import type { hotelPageUrlSchema, } from "@/server/routers/contentstack/hotelPage/output" import type { activitiesCardSchema } from "@/server/routers/contentstack/schemas/blocks/activitiesCard" +import type { spaPageSchema } from "@/server/routers/contentstack/schemas/blocks/spaPage" export interface GetHotelPageData extends z.input {} export interface HotelPage extends z.output {} export interface ActivitiesCard extends z.output {} export type ActivityCard = ActivitiesCard["upcoming_activities_card"] -export interface ContentBlock extends z.output {} + +export interface SpaPage extends z.output {} +export type ContentBlock = z.output export interface GetHotelPageRefsSchema extends z.input {}