diff --git a/app/[lang]/(live)/(public)/[contentType]/[uid]/page.tsx b/app/[lang]/(live)/(public)/[contentType]/[uid]/page.tsx index 08fa09422..d96f10f38 100644 --- a/app/[lang]/(live)/(public)/[contentType]/[uid]/page.tsx +++ b/app/[lang]/(live)/(public)/[contentType]/[uid]/page.tsx @@ -2,9 +2,10 @@ import { notFound } from "next/navigation" import { env } from "@/env/server" -import ContentPage from "@/components/ContentType/ContentPage" import HotelPage from "@/components/ContentType/HotelPage" import LoyaltyPage from "@/components/ContentType/LoyaltyPage" +import CollectionPage from "@/components/ContentType/StaticPages/CollectionPage" +import ContentPage from "@/components/ContentType/StaticPages/ContentPage" import { setLang } from "@/i18n/serverContext" import { @@ -22,6 +23,11 @@ export default function ContentTypePage({ setLang(params.lang) switch (params.contentType) { + case "collection-page": + if (env.HIDE_FOR_NEXT_RELEASE) { + return notFound() + } + return case "content-page": if (env.HIDE_FOR_NEXT_RELEASE) { return notFound() diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-rate/page.tsx b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-rate/page.tsx index 502a5833c..1e1787d75 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-rate/page.tsx +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-rate/page.tsx @@ -1,6 +1,7 @@ import { notFound } from "next/navigation" -import { getProfileSafely } from "@/lib/trpc/memoizedRequests" +import { dt } from "@/lib/dt" +import { getLocations, getProfileSafely } from "@/lib/trpc/memoizedRequests" import { serverClient } from "@/lib/trpc/server" import { HotelIncludeEnum } from "@/server/routers/hotels/input" @@ -21,6 +22,17 @@ export default async function SelectRatePage({ }: PageArgs) { setLang(params.lang) + const locations = await getLocations() + if (!locations || "error" in locations) { + return null + } + const hotel = locations.data.find( + (location) => + "operaId" in location && location.operaId == searchParams.hotel + ) + if (!hotel) { + return notFound() + } const selectRoomParams = new URLSearchParams(searchParams) const selectRoomParamsObject = getHotelReservationQueryParams(selectRoomParams) @@ -29,7 +41,16 @@ export default async function SelectRatePage({ return notFound() } - const adults = selectRoomParamsObject.room[0].adults // TODO: Handle multiple rooms + const validFromDate = + searchParams.fromDate && + dt(searchParams.fromDate).isAfter(dt().subtract(1, "day")) + ? searchParams.fromDate + : dt().utc().format("YYYY-MM-DD") + const validToDate = + searchParams.toDate && dt(searchParams.toDate).isAfter(validFromDate) + ? searchParams.toDate + : dt().utc().add(1, "day").format("YYYY-MM-DD") + const adults = selectRoomParamsObject.room[0].adults || 1 // TODO: Handle multiple rooms const childrenCount = selectRoomParamsObject.room[0].child?.length const children = selectRoomParamsObject.room[0].child ? generateChildrenString(selectRoomParamsObject.room[0].child) @@ -43,8 +64,8 @@ export default async function SelectRatePage({ }), serverClient().hotel.availability.rooms({ hotelId: parseInt(searchParams.hotel, 10), - roomStayStartDate: searchParams.fromDate, - roomStayEndDate: searchParams.toDate, + roomStayStartDate: validFromDate, + roomStayEndDate: validToDate, adults, children, }), diff --git a/app/[lang]/(preview)/layout.tsx b/app/[lang]/(preview)/layout.tsx index 25727e7d6..948bcceba 100644 --- a/app/[lang]/(preview)/layout.tsx +++ b/app/[lang]/(preview)/layout.tsx @@ -1,26 +1,29 @@ -import InitLivePreview from "@/components/Current/LivePreview" -import { setLang } from "@/i18n/serverContext" +import "@/app/globals.css" +import "@scandic-hotels/design-system/style.css" -import type { Metadata } from "next" +import TrpcProvider from "@/lib/trpc/Provider" + +import InitLivePreview from "@/components/LivePreview" +import { getIntl } from "@/i18n" +import ServerIntlProvider from "@/i18n/Provider" +import { setLang } from "@/i18n/serverContext" import type { LangParams, LayoutArgs } from "@/types/params" -export const metadata: Metadata = { - description: "New web", - title: "Scandic Hotels", -} - -export default function RootLayout({ +export default async function RootLayout({ children, params, }: React.PropsWithChildren>) { setLang(params.lang) + const { defaultLocale, locale, messages } = await getIntl() return ( - {children} + + {children} + ) diff --git a/app/[lang]/(preview)/preview/[contentType]/[uid]/page.tsx b/app/[lang]/(preview)/preview/[contentType]/[uid]/page.tsx index fbdfa4893..ff954a31d 100644 --- a/app/[lang]/(preview)/preview/[contentType]/[uid]/page.tsx +++ b/app/[lang]/(preview)/preview/[contentType]/[uid]/page.tsx @@ -1,6 +1,14 @@ +import { ContentstackLivePreview } from "@contentstack/live-preview-utils" +import { notFound } from "next/navigation" + +import HotelPage from "@/components/ContentType/HotelPage" +import LoyaltyPage from "@/components/ContentType/LoyaltyPage" +import CollectionPage from "@/components/ContentType/StaticPages/CollectionPage" +import ContentPage from "@/components/ContentType/StaticPages/ContentPage" +import LoadingSpinner from "@/components/LoadingSpinner" import { setLang } from "@/i18n/serverContext" -import { +import type { ContentTypeParams, LangParams, PageArgs, @@ -13,12 +21,32 @@ export default async function PreviewPage({ }: PageArgs) { setLang(params.lang) - return ( -
-

- Preview for {params.contentType}:{params.uid} in {params.lang} with - params

{JSON.stringify(searchParams, null, 2)}
goes here -

-
- ) + try { + ContentstackLivePreview.setConfigFromParams(searchParams) + + if (!searchParams.live_preview) { + return + } + + switch (params.contentType) { + case "content-page": + return + case "loyalty-page": + return + case "collection-page": + return + case "hotel-page": + return + default: + console.log({ PREVIEW: params }) + const type = params.contentType + console.error(`Unsupported content type given: ${type}`) + notFound() + } + } catch (error) { + // TODO: throw 500 + console.error("Error in preview page") + console.error(error) + throw new Error("Something went wrong") + } } diff --git a/app/[lang]/(preview-current)/layout.tsx b/app/[lang]/(preview-current)/layout.tsx index 3e98666c8..e5ff698bb 100644 --- a/app/[lang]/(preview-current)/layout.tsx +++ b/app/[lang]/(preview-current)/layout.tsx @@ -1,6 +1,6 @@ import Footer from "@/components/Current/Footer" import LangPopup from "@/components/Current/LangPopup" -import InitLivePreview from "@/components/Current/LivePreview" +import InitLivePreview from "@/components/LivePreview" import SkipToMainContent from "@/components/SkipToMainContent" import { setLang } from "@/i18n/serverContext" diff --git a/app/[lang]/(preview-current)/preview-current/page.tsx b/app/[lang]/(preview-current)/preview-current/page.tsx index f8ca81201..82c1e9c45 100644 --- a/app/[lang]/(preview-current)/preview-current/page.tsx +++ b/app/[lang]/(preview-current)/preview-current/page.tsx @@ -1,4 +1,4 @@ -import ContentstackLivePreview from "@contentstack/live-preview-utils" +import { ContentstackLivePreview } from "@contentstack/live-preview-utils" import { previewRequest } from "@/lib/graphql/previewRequest" import { GetCurrentBlockPage } from "@/lib/graphql/Query/Current/CurrentBlockPage.graphql" diff --git a/components/Blocks/CardsGrid.tsx b/components/Blocks/CardsGrid.tsx index 1c07b73ec..92d98a61b 100644 --- a/components/Blocks/CardsGrid.tsx +++ b/components/Blocks/CardsGrid.tsx @@ -42,13 +42,17 @@ export default function CardsGrid({ case CardsGridEnum.cards.Card: return ( ) case CardsGridEnum.cards.TeaserCard: diff --git a/components/Blocks/DynamicContent/OverviewTable/LargeTable/index.tsx b/components/Blocks/DynamicContent/OverviewTable/LargeTable/index.tsx index f19b42444..aa9d320cd 100644 --- a/components/Blocks/DynamicContent/OverviewTable/LargeTable/index.tsx +++ b/components/Blocks/DynamicContent/OverviewTable/LargeTable/index.tsx @@ -70,7 +70,7 @@ function RewardTableHeader({ name, description }: RewardTableHeaderProps) {
- + <Title as="h4" level="h2" textTransform={"regular"}> {name} diff --git a/components/Blocks/DynamicContent/OverviewTable/RewardList/Card/index.tsx b/components/Blocks/DynamicContent/OverviewTable/RewardList/Card/index.tsx index b54d9722d..4a49abd04 100644 --- a/components/Blocks/DynamicContent/OverviewTable/RewardList/Card/index.tsx +++ b/components/Blocks/DynamicContent/OverviewTable/RewardList/Card/index.tsx @@ -19,7 +19,7 @@ export default function RewardCard({
- + <Title as="h4" level="h2" textTransform={"regular"}> {title} diff --git a/components/Blocks/DynamicContent/Rewards/NextLevel/index.tsx b/components/Blocks/DynamicContent/Rewards/NextLevel/index.tsx index 7517ed955..cc311048d 100644 --- a/components/Blocks/DynamicContent/Rewards/NextLevel/index.tsx +++ b/components/Blocks/DynamicContent/Rewards/NextLevel/index.tsx @@ -56,7 +56,7 @@ export default async function NextLevelRewardsBlock({ { level: nextLevelRewards.level?.name } )} - + <Title level="h4" as="h4" color="pale" textAlign="center"> {reward.label} diff --git a/components/Blocks/DynamicContent/Stays/Previous/EmptyPreviousStays/index.tsx b/components/Blocks/DynamicContent/Stays/Previous/EmptyPreviousStays/index.tsx index e80cab97c..e4da92974 100644 --- a/components/Blocks/DynamicContent/Stays/Previous/EmptyPreviousStays/index.tsx +++ b/components/Blocks/DynamicContent/Stays/Previous/EmptyPreviousStays/index.tsx @@ -7,7 +7,7 @@ export default async function EmptyPreviousStaysBlock() { const { formatMessage } = await getIntl() return (
- + <Title as="h4" level="h3" color="red" textAlign="center"> {formatMessage({ id: "You have no previous stays.", })} diff --git a/components/Blocks/DynamicContent/Stays/Soonest/EmptyUpcomingStays/index.tsx b/components/Blocks/DynamicContent/Stays/Soonest/EmptyUpcomingStays/index.tsx index 1cd297438..0db81b6ce 100644 --- a/components/Blocks/DynamicContent/Stays/Soonest/EmptyUpcomingStays/index.tsx +++ b/components/Blocks/DynamicContent/Stays/Soonest/EmptyUpcomingStays/index.tsx @@ -14,7 +14,7 @@ export default async function EmptyUpcomingStaysBlock() { return ( <section className={styles.container}> <div className={styles.titleContainer}> - <Title as="h5" level="h3" color="red" className={styles.title}> + <Title as="h4" level="h3" color="red" className={styles.title}> {formatMessage({ id: "You have no upcoming stays." })} <span className={styles.burgundyTitle}> {formatMessage({ id: "Where should you go next?" })} diff --git a/components/Blocks/DynamicContent/Stays/StayCard/index.tsx b/components/Blocks/DynamicContent/Stays/StayCard/index.tsx index 9e63c0f77..59c768156 100644 --- a/components/Blocks/DynamicContent/Stays/StayCard/index.tsx +++ b/components/Blocks/DynamicContent/Stays/StayCard/index.tsx @@ -47,7 +47,7 @@ export default function StayCard({ stay }: StayCardProps) { height={240} /> <footer className={styles.footer}> - <Title as="h5" className={styles.hotel} level="h3"> + <Title as="h4" className={styles.hotel} level="h3"> {hotelInformation.hotelName}
diff --git a/components/Blocks/DynamicContent/Stays/Upcoming/EmptyUpcomingStays/index.tsx b/components/Blocks/DynamicContent/Stays/Upcoming/EmptyUpcomingStays/index.tsx index 1cd297438..0db81b6ce 100644 --- a/components/Blocks/DynamicContent/Stays/Upcoming/EmptyUpcomingStays/index.tsx +++ b/components/Blocks/DynamicContent/Stays/Upcoming/EmptyUpcomingStays/index.tsx @@ -14,7 +14,7 @@ export default async function EmptyUpcomingStaysBlock() { return (
- + <Title as="h4" level="h3" color="red" className={styles.title}> {formatMessage({ id: "You have no upcoming stays." })} <span className={styles.burgundyTitle}> {formatMessage({ id: "Where should you go next?" })} diff --git a/components/BookingWidget/Client.tsx b/components/BookingWidget/Client.tsx index 46942ca44..af4bf4c48 100644 --- a/components/BookingWidget/Client.tsx +++ b/components/BookingWidget/Client.tsx @@ -47,10 +47,10 @@ export default function BookingWidgetClient({ const bookingWidgetSearchData: BookingWidgetSearchParams | undefined = searchParams ? (getFormattedUrlQueryParams(new URLSearchParams(searchParams), { - adults: "number", - age: "number", - bed: "number", - }) as BookingWidgetSearchParams) + adults: "number", + age: "number", + bed: "number", + }) as BookingWidgetSearchParams) : undefined const getLocationObj = (destination: string): Location | undefined => { @@ -67,18 +67,20 @@ export default function BookingWidgetClient({ return undefined } + const reqFromDate = bookingWidgetSearchData?.fromDate?.toString() + const reqToDate = bookingWidgetSearchData?.toDate?.toString() + const isDateParamValid = - bookingWidgetSearchData?.fromDate && - bookingWidgetSearchData?.toDate && - dt(bookingWidgetSearchData?.toDate.toString()).isAfter( - dt(bookingWidgetSearchData?.fromDate.toString()) - ) + reqFromDate && + reqToDate && + dt(reqFromDate).isAfter(dt().subtract(1, "day")) && + dt(reqToDate).isAfter(dt(reqFromDate)) const selectedLocation = bookingWidgetSearchData ? getLocationObj( - (bookingWidgetSearchData.city ?? - bookingWidgetSearchData.hotel) as string - ) + (bookingWidgetSearchData.city ?? + bookingWidgetSearchData.hotel) as string + ) : undefined const methods = useForm<BookingWidgetSchema>({ diff --git a/components/ContentType/StaticPages/CollectionPage/index.tsx b/components/ContentType/StaticPages/CollectionPage/index.tsx new file mode 100644 index 000000000..41a06391c --- /dev/null +++ b/components/ContentType/StaticPages/CollectionPage/index.tsx @@ -0,0 +1,22 @@ +import { serverClient } from "@/lib/trpc/server" + +import StaticPage from ".." + +export default async function CollectionPage() { + const collectionPageRes = + await serverClient().contentstack.collectionPage.get() + + if (!collectionPageRes) { + return null + } + + const { tracking, collectionPage } = collectionPageRes + + return ( + <StaticPage + content={collectionPage} + tracking={tracking} + pageType="collection" + /> + ) +} diff --git a/components/ContentType/StaticPages/ContentPage/index.tsx b/components/ContentType/StaticPages/ContentPage/index.tsx new file mode 100644 index 000000000..037f011b8 --- /dev/null +++ b/components/ContentType/StaticPages/ContentPage/index.tsx @@ -0,0 +1,17 @@ +import { serverClient } from "@/lib/trpc/server" + +import StaticPage from ".." + +export default async function ContentPage() { + const contentPageRes = await serverClient().contentstack.contentPage.get() + + if (!contentPageRes) { + return null + } + + const { tracking, contentPage } = contentPageRes + + return ( + <StaticPage content={contentPage} tracking={tracking} pageType="content" /> + ) +} diff --git a/components/ContentType/ContentPage/index.tsx b/components/ContentType/StaticPages/index.tsx similarity index 75% rename from components/ContentType/ContentPage/index.tsx rename to components/ContentType/StaticPages/index.tsx index b6a556dc5..4eed6b89b 100644 --- a/components/ContentType/ContentPage/index.tsx +++ b/components/ContentType/StaticPages/index.tsx @@ -1,5 +1,3 @@ -import { serverClient } from "@/lib/trpc/server" - import Blocks from "@/components/Blocks" import Hero from "@/components/Hero" import Sidebar from "@/components/Sidebar" @@ -8,21 +6,22 @@ import Preamble from "@/components/TempDesignSystem/Text/Preamble" import Title from "@/components/TempDesignSystem/Text/Title" import TrackingSDK from "@/components/TrackingSDK" -import styles from "./contentPage.module.css" +import { staticPageVariants } from "./variants" -export default async function ContentPage() { - const contentPageRes = await serverClient().contentstack.contentPage.get() +import styles from "./staticPage.module.css" - if (!contentPageRes) { - return null - } +import type { StaticPageProps } from "./staticPage" - const { tracking, contentPage } = contentPageRes - const { blocks, hero_image, header, sidebar } = contentPage +export default function StaticPage({ + content, + tracking, + pageType, +}: StaticPageProps) { + const { blocks, hero_image, header } = content return ( <> - <section className={styles.contentPage}> + <section className={staticPageVariants({ pageType })}> <header className={styles.header}> <div className={styles.headerContent}> {header ? ( @@ -54,7 +53,9 @@ export default async function ContentPage() { {blocks ? <Blocks blocks={blocks} /> : null} </main> - {sidebar?.length ? <Sidebar blocks={sidebar} /> : null} + {"sidebar" in content && content.sidebar?.length ? ( + <Sidebar blocks={content.sidebar} /> + ) : null} </div> </section> diff --git a/components/ContentType/ContentPage/contentPage.module.css b/components/ContentType/StaticPages/staticPage.module.css similarity index 87% rename from components/ContentType/ContentPage/contentPage.module.css rename to components/ContentType/StaticPages/staticPage.module.css index 825a2445d..13d2f440e 100644 --- a/components/ContentType/ContentPage/contentPage.module.css +++ b/components/ContentType/StaticPages/staticPage.module.css @@ -1,4 +1,4 @@ -.contentPage { +.page { padding-bottom: var(--Spacing-x9); } @@ -32,20 +32,27 @@ } .contentContainer { + padding: var(--Spacing-x4) var(--Spacing-x2) 0; +} + +.content .contentContainer { display: grid; grid-template-areas: "main" "sidebar"; gap: var(--Spacing-x4); align-items: start; - padding: var(--Spacing-x4) var(--Spacing-x2) 0; } .mainContent { - grid-area: main; display: grid; gap: var(--Spacing-x4); width: 100%; + gap: var(--Spacing-x6); +} + +.content .mainContent { + grid-area: main; } @media (min-width: 768px) { @@ -58,12 +65,20 @@ .heroContainer { padding: var(--Spacing-x4) 0; } + .contentContainer { + max-width: var(--max-width-content); + padding: var(--Spacing-x4) 0 0; + margin: 0 auto; + } + + .content .contentContainer { grid-template-areas: "main sidebar"; grid-template-columns: var(--max-width-text-block) 1fr; gap: var(--Spacing-x9); - max-width: var(--max-width-content); - margin: 0 auto; - padding: var(--Spacing-x4) 0 0; + } + + .mainContent { + gap: var(--Spacing-x9); } } diff --git a/components/ContentType/StaticPages/staticPage.ts b/components/ContentType/StaticPages/staticPage.ts new file mode 100644 index 000000000..5a3bf84b4 --- /dev/null +++ b/components/ContentType/StaticPages/staticPage.ts @@ -0,0 +1,15 @@ +import { staticPageVariants } from "./variants" + +import type { VariantProps } from "class-variance-authority" + +import type { TrackingSDKPageData } from "@/types/components/tracking" +import type { CollectionPage } from "@/types/trpc/routers/contentstack/collectionPage" +import type { ContentPage } from "@/types/trpc/routers/contentstack/contentPage" + +export interface StaticPageProps + extends Omit<React.HTMLAttributes<HTMLDivElement>, "content">, + VariantProps<typeof staticPageVariants> { + pageType?: "collection" | "content" + content: CollectionPage["collection_page"] | ContentPage["content_page"] + tracking: TrackingSDKPageData +} diff --git a/components/ContentType/StaticPages/variants.ts b/components/ContentType/StaticPages/variants.ts new file mode 100644 index 000000000..4d59bc641 --- /dev/null +++ b/components/ContentType/StaticPages/variants.ts @@ -0,0 +1,15 @@ +import { cva } from "class-variance-authority" + +import styles from "./staticPage.module.css" + +export const staticPageVariants = cva(styles.page, { + variants: { + pageType: { + collection: styles.collection, + content: styles.content, + }, + }, + defaultVariants: { + pageType: "content", + }, +}) diff --git a/components/DatePicker/date-picker.module.css b/components/DatePicker/date-picker.module.css index b2e23cd41..ee9034648 100644 --- a/components/DatePicker/date-picker.module.css +++ b/components/DatePicker/date-picker.module.css @@ -14,6 +14,7 @@ outline: none; padding: 0; width: 100%; + text-align: left; } .body { diff --git a/components/GuestsRoomsPicker/guests-rooms-picker.module.css b/components/GuestsRoomsPicker/guests-rooms-picker.module.css index 971699d95..23a84fd62 100644 --- a/components/GuestsRoomsPicker/guests-rooms-picker.module.css +++ b/components/GuestsRoomsPicker/guests-rooms-picker.module.css @@ -27,6 +27,7 @@ outline: none; padding: 0; width: 100%; + text-align: left; } .body { opacity: 0.8; diff --git a/components/HotelReservation/EnterDetails/SectionAccordion/index.tsx b/components/HotelReservation/EnterDetails/SectionAccordion/index.tsx index a508974c5..05a2f038e 100644 --- a/components/HotelReservation/EnterDetails/SectionAccordion/index.tsx +++ b/components/HotelReservation/EnterDetails/SectionAccordion/index.tsx @@ -11,7 +11,12 @@ import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" import styles from "./sectionAccordion.module.css" +import { + StepEnum, + StepStoreKeys, +} from "@/types/components/hotelReservation/enterDetails/step" import { SectionAccordionProps } from "@/types/components/hotelReservation/selectRate/sectionAccordion" +import { BreakfastPackageEnum } from "@/types/enums/breakfast" export default function SectionAccordion({ header, @@ -23,9 +28,27 @@ export default function SectionAccordion({ const currentStep = useEnterDetailsStore((state) => state.currentStep) const [isComplete, setIsComplete] = useState(false) const [isOpen, setIsOpen] = useState(false) - const isValid = useEnterDetailsStore((state) => state.isValid[step]) const navigate = useEnterDetailsStore((state) => state.navigate) + const stepData = useEnterDetailsStore((state) => state.userData) + const stepStoreKey = StepStoreKeys[step] + const [title, setTitle] = useState(label) + + useEffect(() => { + if (step === StepEnum.selectBed) { + const value = stepData.bedType + value && setTitle(value) + } + // If breakfast step, check if an option has been selected + if (step === StepEnum.breakfast && stepData.breakfast) { + const value = stepData.breakfast + if (value === BreakfastPackageEnum.NO_BREAKFAST) { + setTitle(intl.formatMessage({ id: "No breakfast" })) + } else { + setTitle(intl.formatMessage({ id: "Breakfast buffet" })) + } + } + }, [stepData, stepStoreKey, step, intl]) useEffect(() => { // We need to set the state on mount because of hydration errors @@ -39,7 +62,6 @@ export default function SectionAccordion({ function onModify() { navigate(step) } - return ( <section className={styles.wrapper} data-open={isOpen} data-step={step}> <div className={styles.iconWrapper}> @@ -65,7 +87,7 @@ export default function SectionAccordion({ className={styles.selection} color="uiTextHighContrast" > - {label} + {title} </Subtitle> </div> {isComplete && !isOpen && ( diff --git a/components/HotelReservation/SelectRate/SelectionCard/index.tsx b/components/HotelReservation/SelectRate/SelectionCard/index.tsx index bf3b8caeb..e902993a1 100644 --- a/components/HotelReservation/SelectRate/SelectionCard/index.tsx +++ b/components/HotelReservation/SelectRate/SelectionCard/index.tsx @@ -20,7 +20,7 @@ export default function SelectionCard({ return ( <div className={styles.card}> <div> - <Title className={styles.name} as="h5" level="h3"> + <Title className={styles.name} as="h4" level="h3"> {title}
i
diff --git a/components/Current/LivePreview/index.tsx b/components/LivePreview/index.tsx similarity index 75% rename from components/Current/LivePreview/index.tsx rename to components/LivePreview/index.tsx index c75d9bc66..5258da67b 100644 --- a/components/Current/LivePreview/index.tsx +++ b/components/LivePreview/index.tsx @@ -1,6 +1,6 @@ "use client" -import ContentstackLivePreview from "@contentstack/live-preview-utils" +import { ContentstackLivePreview } from "@contentstack/live-preview-utils" import { useEffect } from "react" export default function InitLivePreview() { diff --git a/components/Sidebar/index.tsx b/components/Sidebar/index.tsx index 02e317e54..53e88126e 100644 --- a/components/Sidebar/index.tsx +++ b/components/Sidebar/index.tsx @@ -60,7 +60,7 @@ export default function Sidebar({ blocks }: SidebarProps) { ) : null} - + <Title as="h4" level="h3" textAlign="center"> {heading} {bodyText ? {bodyText} : null} diff --git a/components/TempDesignSystem/SidePeek/index.tsx b/components/TempDesignSystem/SidePeek/index.tsx index 9afe22c1f..76aea7dcf 100644 --- a/components/TempDesignSystem/SidePeek/index.tsx +++ b/components/TempDesignSystem/SidePeek/index.tsx @@ -41,7 +41,7 @@ function SidePeek({ if (isSSR) { return ( -
+

{title}

{children}
diff --git a/components/TempDesignSystem/SidePeek/sidePeek.module.css b/components/TempDesignSystem/SidePeek/sidePeek.module.css index 4c2bb9187..68f588ab3 100644 --- a/components/TempDesignSystem/SidePeek/sidePeek.module.css +++ b/components/TempDesignSystem/SidePeek/sidePeek.module.css @@ -21,6 +21,12 @@ } } +.visuallyHidden { + position: absolute; + opacity: 0; + visibility: hidden; +} + .overlay { position: fixed; top: 0; @@ -40,7 +46,7 @@ height: 100vh; background-color: var(--Base-Background-Primary-Normal); z-index: var(--sidepeek-z-index); - box-shadow: 0 0 10px rgba(0, 0, 0, 0.85); + outline: none; } .modal[data-entering] { diff --git a/components/TempDesignSystem/TeaserCard/Sidepeek/index.tsx b/components/TempDesignSystem/TeaserCard/Sidepeek/index.tsx index ee3c6be79..cc90086ce 100644 --- a/components/TempDesignSystem/TeaserCard/Sidepeek/index.tsx +++ b/components/TempDesignSystem/TeaserCard/Sidepeek/index.tsx @@ -21,7 +21,7 @@ export default function TeaserCardSidepeek({ const { heading, content, primary_button, secondary_button } = sidePeekContent return ( - <> +
- +
) } diff --git a/components/TempDesignSystem/TeaserCard/index.tsx b/components/TempDesignSystem/TeaserCard/index.tsx index bc40df889..67f25998f 100644 --- a/components/TempDesignSystem/TeaserCard/index.tsx +++ b/components/TempDesignSystem/TeaserCard/index.tsx @@ -19,25 +19,23 @@ export default function TeaserCard({ sidePeekButton, sidePeekContent, image, - style = "default", + intent, alwaysStack = false, className, }: TeaserCardProps) { - const cardClasses = teaserCardVariants({ style, alwaysStack, className }) + const classNames = teaserCardVariants({ intent, alwaysStack, className }) return ( -
+
{image && ( -
- {image.meta?.alt -
+ {image.meta?.alt )}
diff --git a/components/TempDesignSystem/TeaserCard/teaserCard.module.css b/components/TempDesignSystem/TeaserCard/teaserCard.module.css index d1bc40165..49f084d20 100644 --- a/components/TempDesignSystem/TeaserCard/teaserCard.module.css +++ b/components/TempDesignSystem/TeaserCard/teaserCard.module.css @@ -18,24 +18,17 @@ border: 1px solid var(--Base-Border-Subtle); } -.imageContainer { +.image { width: 100%; - height: 12.58625rem; /* 201.38px / 16 = 12.58625rem */ - overflow: hidden; -} - -.backgroundImage { - width: 100%; - height: 100%; - object-fit: cover; + height: 12.5rem; /* 200px */ } .content { - display: flex; - flex-direction: column; + display: grid; gap: var(--Spacing-x-one-and-half); - align-items: flex-start; padding: var(--Spacing-x2) var(--Spacing-x3); + grid-template-rows: auto 1fr auto; + flex-grow: 1; } .description { @@ -53,17 +46,6 @@ width: 100%; } -.body { - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 3; - line-clamp: 3; - overflow: hidden; - text-overflow: ellipsis; - /* line-height variables are in %, so using the value in rem instead */ - max-height: calc(3 * 1.5rem); -} - @media (min-width: 1367px) { .card:not(.alwaysStack) .ctaContainer { grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); diff --git a/components/TempDesignSystem/TeaserCard/variants.ts b/components/TempDesignSystem/TeaserCard/variants.ts index b6ca7744d..294f6d913 100644 --- a/components/TempDesignSystem/TeaserCard/variants.ts +++ b/components/TempDesignSystem/TeaserCard/variants.ts @@ -4,7 +4,7 @@ import styles from "./teaserCard.module.css" export const teaserCardVariants = cva(styles.card, { variants: { - style: { + intent: { default: styles.default, featured: styles.featured, }, @@ -14,7 +14,7 @@ export const teaserCardVariants = cva(styles.card, { }, }, defaultVariants: { - style: "default", + intent: "default", alwaysStack: false, }, }) diff --git a/components/TempDesignSystem/Text/Title/title.module.css b/components/TempDesignSystem/Text/Title/title.module.css index d01be3335..b970de2bb 100644 --- a/components/TempDesignSystem/Text/Title/title.module.css +++ b/components/TempDesignSystem/Text/Title/title.module.css @@ -4,7 +4,9 @@ font-weight: 500; } -.h1 { +/* Temporarily remove h1 styling until design tokens är updated */ + +/* .h1 { font-family: var(--typography-Title-1-fontFamily); font-size: clamp( var(--typography-Title-1-Mobile-fontSize), @@ -14,9 +16,9 @@ letter-spacing: var(--typography-Title-1-letterSpacing); line-height: var(--typography-Title-1-lineHeight); text-decoration: var(--typography-Title-1-textDecoration); -} +} */ -.h2 { +.h1 { font-family: var(--typography-Title-2-fontFamily); font-size: clamp( var(--typography-Title-2-Mobile-fontSize), @@ -26,9 +28,10 @@ letter-spacing: var(--typography-Title-2-letterSpacing); line-height: var(--typography-Title-2-lineHeight); text-decoration: var(--typography-Title-2-textDecoration); + font-weight: var(--typography-Title-2-fontWeight); } -.h3 { +.h2 { font-family: var(--typography-Title-3-fontFamily); font-size: clamp( var(--typography-Title-3-Mobile-fontSize), @@ -38,9 +41,10 @@ letter-spacing: var(--typography-Title-3-letterSpacing); line-height: var(--typography-Title-3-lineHeight); text-decoration: var(--typography-Title-3-textDecoration); + font-weight: var(--typography-Title-3-fontWeight); } -.h4 { +.h3 { font-family: var(--typography-Title-4-fontFamily); font-size: clamp( var(--typography-Title-4-Mobile-fontSize), @@ -50,9 +54,10 @@ letter-spacing: var(--typography-Title-4-letterSpacing); line-height: var(--typography-Title-4-lineHeight); text-decoration: var(--typography-Title-4-textDecoration); + font-weight: var(--typography-Title-4-fontWeight); } -.h5 { +.h4 { font-family: var(--typography-Title-5-fontFamily); font-size: clamp( var(--typography-Title-5-Mobile-fontSize), @@ -62,6 +67,7 @@ letter-spacing: var(--typography-Title-5-letterSpacing); line-height: var(--typography-Title-5-lineHeight); text-decoration: var(--typography-Title-5-textDecoration); + font-weight: var(--typography-Title-5-fontWeight); } .capitalize { diff --git a/components/TempDesignSystem/Text/Title/variants.ts b/components/TempDesignSystem/Text/Title/variants.ts index 641394ceb..f374daaf9 100644 --- a/components/TempDesignSystem/Text/Title/variants.ts +++ b/components/TempDesignSystem/Text/Title/variants.ts @@ -26,7 +26,7 @@ const config = { h2: styles.h2, h3: styles.h3, h4: styles.h4, - h5: styles.h5, + h5: styles.h4, }, }, defaultVariants: { diff --git a/hooks/useStickyPosition.ts b/hooks/useStickyPosition.ts index 923f56c73..2c7fdf6ea 100644 --- a/hooks/useStickyPosition.ts +++ b/hooks/useStickyPosition.ts @@ -95,7 +95,6 @@ export default function useStickyPosition({ }, 100) resizeObserver = new ResizeObserver(debouncedResizeHandler) - console.log("Initialized ResizeObserver") } resizeObserver.observe(document.body) diff --git a/lib/graphql/Fragments/Blocks/CardsGrid.graphql b/lib/graphql/Fragments/Blocks/CardsGrid.graphql index ce4eb3886..2011d8491 100644 --- a/lib/graphql/Fragments/Blocks/CardsGrid.graphql +++ b/lib/graphql/Fragments/Blocks/CardsGrid.graphql @@ -5,6 +5,7 @@ #import "./Refs/Card.graphql" #import "./Refs/LoyaltyCard.graphql" #import "./Refs/TeaserCard.graphql" + fragment CardsGrid_ContentPage on ContentPageBlocksCardsGrid { cards_grid { layout @@ -39,6 +40,38 @@ fragment CardsGrid_ContentPageRefs on ContentPageBlocksCardsGrid { } } +fragment CardsGrid_CollectionPage on CollectionPageBlocksCardsGrid { + cards_grid { + layout + preamble + theme + title + cardConnection(limit: 10) { + edges { + node { + __typename + ...CardBlock + ...TeaserCardBlock + } + } + } + } +} + +fragment CardsGrid_CollectionPageRefs on CollectionPageBlocksCardsGrid { + cards_grid { + cardConnection(limit: 10) { + edges { + node { + __typename + ...CardBlockRef + ...TeaserCardBlockRef + } + } + } + } +} + fragment CardsGrid_LoyaltyPage on LoyaltyPageBlocksCardsGrid { cards_grid { layout diff --git a/lib/graphql/Fragments/Blocks/Shortcuts.graphql b/lib/graphql/Fragments/Blocks/Shortcuts.graphql index 4ba566634..cfdb9bcbe 100644 --- a/lib/graphql/Fragments/Blocks/Shortcuts.graphql +++ b/lib/graphql/Fragments/Blocks/Shortcuts.graphql @@ -1,8 +1,10 @@ #import "../AccountPage/Ref.graphql" +#import "../CollectionPage/Ref.graphql" #import "../ContentPage/Ref.graphql" #import "../LoyaltyPage/Ref.graphql" #import "../PageLink/AccountPageLink.graphql" +#import "../PageLink/CollectionPageLink.graphql" #import "../PageLink/ContentPageLink.graphql" #import "../PageLink/LoyaltyPageLink.graphql" @@ -32,6 +34,12 @@ fragment Shortcuts_AccountPage on AccountPageContentShortcuts { } } +fragment Shortcuts_CollectionPage on CollectionPageBlocksShortcuts { + shortcuts { + ...Shortcuts + } +} + fragment Shortcuts_ContentPage on ContentPageBlocksShortcuts { shortcuts { ...Shortcuts @@ -65,6 +73,12 @@ fragment Shortcuts_AccountPageRefs on AccountPageContentShortcuts { } } +fragment Shortcuts_CollectionPageRefs on CollectionPageBlocksShortcuts { + shortcuts { + ...ShortcutsRefs + } +} + fragment Shortcuts_ContentPageRefs on ContentPageBlocksShortcuts { shortcuts { ...ShortcutsRefs diff --git a/lib/graphql/Fragments/Blocks/UspGrid.graphql b/lib/graphql/Fragments/Blocks/UspGrid.graphql index ae2df5aa8..e7f435b5a 100644 --- a/lib/graphql/Fragments/Blocks/UspGrid.graphql +++ b/lib/graphql/Fragments/Blocks/UspGrid.graphql @@ -68,3 +68,64 @@ fragment UspGrid_ContentPageRefs on ContentPageBlocksUspGrid { } } } + +fragment UspGrid_CollectionPage on CollectionPageBlocksUspGrid { + __typename + usp_grid { + cardsConnection { + edges { + node { + ... on UspGrid { + usp_card { + __typename + icon + text { + embedded_itemsConnection { + totalCount + edges { + node { + __typename + ...AccountPageLink + ...ContentPageLink + ...HotelPageLink + ...LoyaltyPageLink + } + } + } + json + } + } + } + } + } + } + } +} + +fragment UspGrid_CollectionPageRefs on CollectionPageBlocksUspGrid { + usp_grid { + cardsConnection { + edges { + node { + ... on UspGrid { + usp_card { + text { + embedded_itemsConnection { + edges { + node { + __typename + ...AccountPageRef + ...ContentPageRef + ...HotelPageRef + ...LoyaltyPageRef + } + } + } + } + } + } + } + } + } + } +} diff --git a/lib/graphql/Fragments/CollectionPage/NavigationLinks.graphql b/lib/graphql/Fragments/CollectionPage/NavigationLinks.graphql new file mode 100644 index 000000000..55a7572a1 --- /dev/null +++ b/lib/graphql/Fragments/CollectionPage/NavigationLinks.graphql @@ -0,0 +1,21 @@ +#import "../PageLink/CollectionPageLink.graphql" +#import "../PageLink/ContentPageLink.graphql" +#import "../PageLink/HotelPageLink.graphql" +#import "../PageLink/LoyaltyPageLink.graphql" + +fragment NavigationLinks on CollectionPageHeader { + navigation_links { + title + linkConnection { + edges { + node { + __typename + ...HotelPageLink + ...CollectionPageLink + ...ContentPageLink + ...LoyaltyPageLink + } + } + } + } +} diff --git a/lib/graphql/Fragments/CollectionPage/Ref.graphql b/lib/graphql/Fragments/CollectionPage/Ref.graphql new file mode 100644 index 000000000..dd746f5f4 --- /dev/null +++ b/lib/graphql/Fragments/CollectionPage/Ref.graphql @@ -0,0 +1,7 @@ +#import "../System.graphql" + +fragment CollectionPageRef on CollectionPage { + system { + ...System + } +} diff --git a/lib/graphql/Fragments/PageLink/CollectionPageLink.graphql b/lib/graphql/Fragments/PageLink/CollectionPageLink.graphql new file mode 100644 index 000000000..9ebbb4f11 --- /dev/null +++ b/lib/graphql/Fragments/PageLink/CollectionPageLink.graphql @@ -0,0 +1,12 @@ +#import "../System.graphql" + +fragment CollectionPageLink on CollectionPage { + title + url + system { + ...System + } + web { + original_url + } +} diff --git a/lib/graphql/Query/BookingWidgetToggle.graphql b/lib/graphql/Query/BookingWidgetToggle.graphql index fa6f73fff..017f07f9d 100644 --- a/lib/graphql/Query/BookingWidgetToggle.graphql +++ b/lib/graphql/Query/BookingWidgetToggle.graphql @@ -14,6 +14,14 @@ query GetLoyaltyPageSettings($uid: String!, $locale: String!) { } } +query GetCollectionPageSettings($uid: String!, $locale: String!) { + collection_page(uid: $uid, locale: $locale) { + page_settings { + hide_booking_widget + } + } +} + query GetContentPageSettings($uid: String!, $locale: String!) { content_page(uid: $uid, locale: $locale) { page_settings { diff --git a/lib/graphql/Query/Breadcrumbs/CollectionPage.graphql b/lib/graphql/Query/Breadcrumbs/CollectionPage.graphql new file mode 100644 index 000000000..1e9c3d522 --- /dev/null +++ b/lib/graphql/Query/Breadcrumbs/CollectionPage.graphql @@ -0,0 +1,28 @@ +#import "../../Fragments/Breadcrumbs/Breadcrumbs.graphql" +#import "../../Fragments/System.graphql" + +query GetCollectionPageBreadcrumbs($locale: String!, $uid: String!) { + collection_page(locale: $locale, uid: $uid) { + web { + breadcrumbs { + ...Breadcrumbs + } + } + system { + ...System + } + } +} + +query GetCollectionPageBreadcrumbsRefs($locale: String!, $uid: String!) { + collection_page(locale: $locale, uid: $uid) { + web { + breadcrumbs { + ...BreadcrumbsRefs + } + } + system { + ...System + } + } +} diff --git a/lib/graphql/Query/CollectionPage/CollectionPage.graphql b/lib/graphql/Query/CollectionPage/CollectionPage.graphql new file mode 100644 index 000000000..36d40b9fc --- /dev/null +++ b/lib/graphql/Query/CollectionPage/CollectionPage.graphql @@ -0,0 +1,83 @@ +#import "../../Fragments/System.graphql" + +#import "../../Fragments/Blocks/CardsGrid.graphql" +#import "../../Fragments/Blocks/Shortcuts.graphql" +#import "../../Fragments/Blocks/UspGrid.graphql" + +#import "../../Fragments/CollectionPage/NavigationLinks.graphql" + +query GetCollectionPage($locale: String!, $uid: String!) { + collection_page(uid: $uid, locale: $locale) { + hero_image + title + header { + heading + preamble + ...NavigationLinks + } + blocks { + __typename + ...CardsGrid_CollectionPage + ...Shortcuts_CollectionPage + ...UspGrid_CollectionPage + } + system { + ...System + created_at + updated_at + } + } +} + +query GetCollectionPageRefs($locale: String!, $uid: String!) { + collection_page(locale: $locale, uid: $uid) { + header { + navigation_links { + linkConnection { + edges { + node { + __typename + ...CollectionPageRef + ...ContentPageRef + ...HotelPageRef + ...LoyaltyPageRef + } + } + } + } + } + blocks { + __typename + ...CardsGrid_CollectionPageRefs + ...Shortcuts_CollectionPageRefs + ...UspGrid_CollectionPageRefs + } + system { + ...System + } + } +} + +query GetDaDeEnUrlsCollectionPage($uid: String!) { + de: collection_page(locale: "de", uid: $uid) { + url + } + en: collection_page(locale: "en", uid: $uid) { + url + } + da: collection_page(locale: "da", uid: $uid) { + url + } +} + +query GetFiNoSvUrlsCollectionPage($uid: String!) { + fi: collection_page(locale: "fi", uid: $uid) { + url + } + no: collection_page(locale: "no", uid: $uid) { + url + } + sv: collection_page(locale: "sv", uid: $uid) { + url + } +} diff --git a/lib/graphql/Query/ResolveEntry.graphql b/lib/graphql/Query/ResolveEntry.graphql index 0a07a9cbe..f512e1110 100644 --- a/lib/graphql/Query/ResolveEntry.graphql +++ b/lib/graphql/Query/ResolveEntry.graphql @@ -9,6 +9,14 @@ query ResolveEntryByUrl($locale: String!, $url: String!) { } total } + all_collection_page(where: { url: $url }, locale: $locale) { + items { + system { + ...System + } + } + total + } all_content_page(where: { url: $url }, locale: $locale) { items { system { diff --git a/lib/graphql/_request.ts b/lib/graphql/_request.ts index 4040dfd9e..814fe045c 100644 --- a/lib/graphql/_request.ts +++ b/lib/graphql/_request.ts @@ -1,5 +1,6 @@ import "server-only" +import { ContentstackLivePreview } from "@contentstack/live-preview-utils" import { ClientError, GraphQLClient } from "graphql-request" import { Lang } from "@/constants/languages" @@ -16,40 +17,54 @@ export async function request( params?: RequestInit ): Promise> { try { - if (params?.cache) { - client.requestConfig.cache = params.cache - } - if (params?.headers) { - client.requestConfig.headers = params.headers - } - if (params?.next) { - client.requestConfig.next = params.next - } + client.setHeaders({ + access_token: env.CMS_ACCESS_TOKEN, + "Content-Type": "application/json", + }) - if (env.PRINT_QUERY) { - const print = (await import("graphql/language/printer")).print - const rawResponse = await client.rawRequest( - print(query as DocumentNode), - variables, - { - access_token: env.CMS_ACCESS_TOKEN, - "Content-Type": "application/json", + const previewHash = ContentstackLivePreview.hash + if (previewHash) { + client.setEndpoint(env.CMS_PREVIEW_URL) + client.setHeader("preview_token", env.CMS_PREVIEW_TOKEN) + client.setHeader("live_preview", previewHash) + } else { + if (params?.cache) { + client.requestConfig.cache = params.cache + } + if (params?.headers) { + client.requestConfig.headers = params.headers + } + if (params?.next) { + client.requestConfig.next = params.next + } + + if (env.PRINT_QUERY) { + const print = (await import("graphql/language/printer")).print + const rawResponse = await client.rawRequest( + print(query as DocumentNode), + variables, + { + access_token: env.CMS_ACCESS_TOKEN, + "Content-Type": "application/json", + } + ) + + /** + * TODO: Send to Monitoring (Logging and Metrics) + */ + console.log({ + complexityLimit: rawResponse.headers.get("x-query-complexity"), + }) + console.log({ + referenceDepth: rawResponse.headers.get("x-reference-depth"), + }) + console.log({ + resolverCost: rawResponse.headers.get("x-resolver-cost"), + }) + + return { + data: rawResponse.data, } - ) - - /** - * TODO: Send to Monitoring (Logging and Metrics) - */ - console.log({ - complexityLimit: rawResponse.headers.get("x-query-complexity"), - }) - console.log({ - referenceDepth: rawResponse.headers.get("x-reference-depth"), - }) - console.log({ resolverCost: rawResponse.headers.get("x-resolver-cost") }) - - return { - data: rawResponse.data, } } @@ -78,10 +93,6 @@ export async function request( const response = await client.request({ document: query, - requestHeaders: { - access_token: env.CMS_ACCESS_TOKEN, - "Content-Type": "application/json", - }, variables, }) diff --git a/lib/graphql/previewRequest.ts b/lib/graphql/previewRequest.ts index eadf3fbba..2ea947ad6 100644 --- a/lib/graphql/previewRequest.ts +++ b/lib/graphql/previewRequest.ts @@ -1,6 +1,6 @@ import "server-only" -import ContentstackLivePreview from "@contentstack/live-preview-utils" +import { ContentstackLivePreview } from "@contentstack/live-preview-utils" import { request as graphqlRequest } from "graphql-request" import { env } from "@/env/server" diff --git a/middlewares/cmsContent.ts b/middlewares/cmsContent.ts index 3d931ebbe..d08c12af5 100644 --- a/middlewares/cmsContent.ts +++ b/middlewares/cmsContent.ts @@ -2,7 +2,6 @@ import { NextResponse } from "next/server" import { notFound } from "@/server/errors/next" -import { resolve as resolveEntry } from "@/utils/entry" import { findLang } from "@/utils/languages" import { removeTrailingSlash } from "@/utils/url" @@ -18,17 +17,21 @@ export const middleware: NextMiddleware = async (request) => { const pathWithoutTrailingSlash = removeTrailingSlash(nextUrl.pathname) - const pathNameWithoutLang = pathWithoutTrailingSlash.replace(`/${lang}`, "") + const contentTypePathName = pathWithoutTrailingSlash.replace(`/${lang}`, "") + const isPreview = request.nextUrl.pathname.includes("/preview") + const searchParams = new URLSearchParams(request.nextUrl.searchParams) const { contentType, uid } = await fetchAndCacheEntry( - pathNameWithoutLang, + isPreview + ? contentTypePathName.replace("/preview", "") + : contentTypePathName, lang ) if (!contentType || !uid) { throw notFound( - `Unable to resolve CMS entry for locale "${lang}": ${pathNameWithoutLang}` + `Unable to resolve CMS entry for locale "${lang}": ${contentTypePathName}` ) } const headers = getDefaultRequestHeaders(request) @@ -37,9 +40,9 @@ export const middleware: NextMiddleware = async (request) => { const isCurrent = contentType ? contentType.indexOf("current") >= 0 : false - if (request.nextUrl.pathname.includes("/preview")) { + if (isPreview) { if (isCurrent) { - searchParams.set("uri", pathNameWithoutLang.replace("/preview", "")) + searchParams.set("uri", contentTypePathName.replace("/preview", "")) return NextResponse.rewrite( new URL(`/${lang}/preview-current?${searchParams.toString()}`, nextUrl), { @@ -65,7 +68,7 @@ export const middleware: NextMiddleware = async (request) => { if (isCurrent) { searchParams.set("uid", uid) - searchParams.set("uri", pathNameWithoutLang) + searchParams.set("uri", contentTypePathName) return NextResponse.rewrite( new URL( `/${lang}/current-content-page?${searchParams.toString()}`, diff --git a/package-lock.json b/package-lock.json index e1cd6777e..36f965c48 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "hasInstallScript": true, "dependencies": { "@azure/monitor-opentelemetry-exporter": "^1.0.0-beta.24", - "@contentstack/live-preview-utils": "^1.4.0", + "@contentstack/live-preview-utils": "^2.0.4", "@hookform/error-message": "^2.0.1", "@hookform/resolvers": "^3.3.4", "@netlify/plugin-nextjs": "^5.1.1", @@ -118,16 +118,15 @@ } }, "node_modules/@auth/core": { - "version": "0.32.0", - "resolved": "https://registry.npmjs.org/@auth/core/-/core-0.32.0.tgz", - "integrity": "sha512-3+ssTScBd+1fd0/fscAyQN1tSygXzuhysuVVzB942ggU4mdfiTbv36P0ccVnExKWYJKvu3E2r3/zxXCCAmTOrg==", - "license": "ISC", + "version": "0.37.2", + "resolved": "https://registry.npmjs.org/@auth/core/-/core-0.37.2.tgz", + "integrity": "sha512-kUvzyvkcd6h1vpeMAojK2y7+PAV5H+0Cc9+ZlKYDFhDY31AlvsB+GW5vNO4qE3Y07KeQgvNO9U0QUx/fN62kBw==", "dependencies": { - "@panva/hkdf": "^1.1.1", + "@panva/hkdf": "^1.2.1", "@types/cookie": "0.6.0", - "cookie": "0.6.0", - "jose": "^5.1.3", - "oauth4webapi": "^2.9.0", + "cookie": "0.7.1", + "jose": "^5.9.3", + "oauth4webapi": "^3.0.0", "preact": "10.11.3", "preact-render-to-string": "5.2.3" }, @@ -2460,13 +2459,16 @@ } }, "node_modules/@contentstack/live-preview-utils": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@contentstack/live-preview-utils/-/live-preview-utils-1.4.1.tgz", - "integrity": "sha512-CbC+Wtc+t8NkD3qTTZaxl7KHCzNCrnKtpkPoarxig1ffyGk8GeEZwW5tLyEtqQ7zsvwLA+RIuWY55gKQumJQLQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@contentstack/live-preview-utils/-/live-preview-utils-2.0.4.tgz", + "integrity": "sha512-+56ExpzsOau5MEEg6sy1czaQMzPmEZAyGYx+LIyqeKKCbxFmTHcvg4Ag4vJ7KUf4LCtoGMUUT/Mkf6hqSkCvDA==", "dependencies": { + "goober": "^2.1.14", "just-camel-case": "^4.0.2", + "lodash-es": "^4.17.21", "morphdom": "^2.6.1", "mustache": "^4.2.0", + "post-robot": "8.0.31", "uuid": "^8.3.2" } }, @@ -3382,10 +3384,9 @@ } }, "node_modules/@next/env": { - "version": "14.2.7", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.7.tgz", - "integrity": "sha512-OTx9y6I3xE/eih+qtthppwLytmpJVPM5PPoJxChFsbjIEFXIayG0h/xLzefHGJviAa3Q5+Fd+9uYojKkHDKxoQ==", - "license": "MIT" + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.16.tgz", + "integrity": "sha512-fLrX5TfJzHCbnZ9YUSnGW63tMV3L4nSfhgOQ0iCcX21Pt+VSTDuaLsSuL8J/2XAiVA5AnzvXDpf6pMs60QxOag==" }, "node_modules/@next/eslint-plugin-next": { "version": "14.1.4", @@ -3397,13 +3398,12 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "14.2.7", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.7.tgz", - "integrity": "sha512-UhZGcOyI9LE/tZL3h9rs/2wMZaaJKwnpAyegUVDGZqwsla6hMfeSj9ssBWQS9yA4UXun3pPhrFLVnw5KXZs3vw==", + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.16.tgz", + "integrity": "sha512-uFT34QojYkf0+nn6MEZ4gIWQ5aqGF11uIZ1HSxG+cSbj+Mg3+tYm8qXYd3dKN5jqKUm5rBVvf1PBRO/MeQ6rxw==", "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "darwin" @@ -3413,13 +3413,12 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "14.2.7", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.7.tgz", - "integrity": "sha512-ys2cUgZYRc+CbyDeLAaAdZgS7N1Kpyy+wo0b/gAj+SeOeaj0Lw/q+G1hp+DuDiDAVyxLBCJXEY/AkhDmtihUTA==", + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.16.tgz", + "integrity": "sha512-mCecsFkYezem0QiZlg2bau3Xul77VxUD38b/auAjohMA22G9KTJneUYMv78vWoCCFkleFAhY1NIvbyjj1ncG9g==", "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "darwin" @@ -3429,13 +3428,12 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.2.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.7.tgz", - "integrity": "sha512-2xoWtE13sUJ3qrC1lwE/HjbDPm+kBQYFkkiVECJWctRASAHQ+NwjMzgrfqqMYHfMxFb5Wws3w9PqzZJqKFdWcQ==", + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.16.tgz", + "integrity": "sha512-yhkNA36+ECTC91KSyZcgWgKrYIyDnXZj8PqtJ+c2pMvj45xf7y/HrgI17hLdrcYamLfVt7pBaJUMxADtPaczHA==", "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -3445,13 +3443,12 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.2.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.7.tgz", - "integrity": "sha512-+zJ1gJdl35BSAGpkCbfyiY6iRTaPrt3KTl4SF/B1NyELkqqnrNX6cp4IjjjxKpd64/7enI0kf6b9O1Uf3cL0pw==", + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.16.tgz", + "integrity": "sha512-X2YSyu5RMys8R2lA0yLMCOCtqFOoLxrq2YbazFvcPOE4i/isubYjkh+JCpRmqYfEuCVltvlo+oGfj/b5T2pKUA==", "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -3461,13 +3458,12 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.2.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.7.tgz", - "integrity": "sha512-m6EBqrskeMUzykBrv0fDX/28lWIBGhMzOYaStp0ihkjzIYJiKUOzVYD1gULHc8XDf5EMSqoH/0/TRAgXqpQwmw==", + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.16.tgz", + "integrity": "sha512-9AGcX7VAkGbc5zTSa+bjQ757tkjr6C/pKS7OK8cX7QEiK6MHIIezBLcQ7gQqbDW2k5yaqba2aDtaBeyyZh1i6Q==", "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -3477,13 +3473,12 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "14.2.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.7.tgz", - "integrity": "sha512-gUu0viOMvMlzFRz1r1eQ7Ql4OE+hPOmA7smfZAhn8vC4+0swMZaZxa9CSIozTYavi+bJNDZ3tgiSdMjmMzRJlQ==", + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.16.tgz", + "integrity": "sha512-Klgeagrdun4WWDaOizdbtIIm8khUDQJ/5cRzdpXHfkbY91LxBXeejL4kbZBrpR/nmgRrQvmz4l3OtttNVkz2Sg==", "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -3493,13 +3488,12 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.2.7", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.7.tgz", - "integrity": "sha512-PGbONHIVIuzWlYmLvuFKcj+8jXnLbx4WrlESYlVnEzDsa3+Q2hI1YHoXaSmbq0k4ZwZ7J6sWNV4UZfx1OeOlbQ==", + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.16.tgz", + "integrity": "sha512-PwW8A1UC1Y0xIm83G3yFGPiOBftJK4zukTmk7DI1CebyMOoaVpd8aSy7K6GhobzhkjYvqS/QmzcfsWG2Dwizdg==", "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "win32" @@ -3509,13 +3503,12 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.2.7", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.7.tgz", - "integrity": "sha512-BiSY5umlx9ed5RQDoHcdbuKTUkuFORDqzYKPHlLeS+STUWQKWziVOn3Ic41LuTBvqE0TRJPKpio9GSIblNR+0w==", + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.16.tgz", + "integrity": "sha512-jhPl3nN0oKEshJBNDAo0etGMzv0j3q3VYorTSFqH1o3rwv1MQRdor27u1zhkgsHPNeY1jxcgyx1ZsCkDD1IHgg==", "cpu": [ "ia32" ], - "license": "MIT", "optional": true, "os": [ "win32" @@ -3525,13 +3518,12 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.2.7", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.7.tgz", - "integrity": "sha512-pxsI23gKWRt/SPHFkDEsP+w+Nd7gK37Hpv0ngc5HpWy2e7cKx9zR/+Q2ptAUqICNTecAaGWvmhway7pj/JLEWA==", + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.16.tgz", + "integrity": "sha512-OA7NtfxgirCjfqt+02BqxC3MIgM/JaGjw9tOe4fyZgPsqfseNiMPnCRP44Pfs+Gpo9zPN+SXaFsgP6vk8d571A==", "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "win32" @@ -3703,7 +3695,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.2.1.tgz", "integrity": "sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw==", - "license": "MIT", "funding": { "url": "https://github.com/sponsors/panva" } @@ -6378,8 +6369,7 @@ "node_modules/@types/cookie": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", - "license": "MIT" + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==" }, "node_modules/@types/google.maps": { "version": "3.58.0", @@ -7348,9 +7338,9 @@ } }, "node_modules/axios": { - "version": "1.6.8", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", - "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", "dev": true, "dependencies": { "follow-redirects": "^1.15.6", @@ -8640,10 +8630,9 @@ "license": "MIT" }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", - "license": "MIT", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "engines": { "node": ">= 0.6" } @@ -8764,6 +8753,22 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, + "node_modules/cross-domain-safe-weakmap": { + "version": "1.0.29", + "resolved": "https://registry.npmjs.org/cross-domain-safe-weakmap/-/cross-domain-safe-weakmap-1.0.29.tgz", + "integrity": "sha512-VLoUgf2SXnf3+na8NfeUFV59TRZkIJqCIATaMdbhccgtnTlSnHXkyTRwokngEGYdQXx8JbHT9GDYitgR2sdjuA==", + "dependencies": { + "cross-domain-utils": "^2.0.0" + } + }, + "node_modules/cross-domain-utils": { + "version": "2.0.38", + "resolved": "https://registry.npmjs.org/cross-domain-utils/-/cross-domain-utils-2.0.38.tgz", + "integrity": "sha512-zZfi3+2EIR9l4chrEiXI2xFleyacsJf8YMLR1eJ0Veb5FTMXeJ3DpxDjZkto2FhL/g717WSELqbptNSo85UJDw==", + "dependencies": { + "zalgo-promise": "^1.0.11" + } + }, "node_modules/cross-fetch": { "version": "3.1.8", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", @@ -9612,6 +9617,18 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/errno": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", @@ -11093,6 +11110,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/goober": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.16.tgz", + "integrity": "sha512-erjk19y1U33+XAMe1VTvIONHYoSqE4iS7BYUZfHaqeohLmnC0FdxEh7rQU+6MZ4OajItzjZFSRtVANrQwNq6/g==", + "peerDependencies": { + "csstype": "^3.0.10" + } + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -13259,10 +13284,9 @@ } }, "node_modules/jose": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/jose/-/jose-5.6.3.tgz", - "integrity": "sha512-1Jh//hEEwMhNYPDDLwXHa2ePWgWiFNNUadVmguAAw2IJ6sj9mNxV5tGXJNqlMkJAybF6Lgw1mISDxTePP/187g==", - "license": "MIT", + "version": "5.9.6", + "resolved": "https://registry.npmjs.org/jose/-/jose-5.9.6.tgz", + "integrity": "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ==", "funding": { "url": "https://github.com/sponsors/panva" } @@ -13840,9 +13864,9 @@ "dev": true }, "node_modules/koa-route/node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", "dev": true, "dependencies": { "isarray": "0.0.1" @@ -14020,12 +14044,15 @@ "integrity": "sha512-Ctgq2lXUpEJo5j1762NOzl2xo7z7pqmVWYai0p07LvAkQ32tbPv3wb+tcUeHEiXhKU5buM4H9MXsXo6OlM6C2g==" }, "node_modules/lilconfig": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", - "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", "dev": true, "engines": { "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" } }, "node_modules/lines-and-columns": { @@ -14036,21 +14063,21 @@ "license": "MIT" }, "node_modules/lint-staged": { - "version": "15.2.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.2.tgz", - "integrity": "sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==", + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.10.tgz", + "integrity": "sha512-5dY5t743e1byO19P9I4b3x8HJwalIznL5E1FWYnU6OWw33KxNBSLAc6Cy7F2PsFEO8FKnLwjwm5hx7aMF0jzZg==", "dev": true, "dependencies": { - "chalk": "5.3.0", - "commander": "11.1.0", - "debug": "4.3.4", - "execa": "8.0.1", - "lilconfig": "3.0.0", - "listr2": "8.0.1", - "micromatch": "4.0.5", - "pidtree": "0.6.0", - "string-argv": "0.3.2", - "yaml": "2.3.4" + "chalk": "~5.3.0", + "commander": "~12.1.0", + "debug": "~4.3.6", + "execa": "~8.0.1", + "lilconfig": "~3.1.2", + "listr2": "~8.2.4", + "micromatch": "~4.0.8", + "pidtree": "~0.6.0", + "string-argv": "~0.3.2", + "yaml": "~2.5.0" }, "bin": { "lint-staged": "bin/lint-staged.js" @@ -14063,21 +14090,24 @@ } }, "node_modules/lint-staged/node_modules/ansi-escapes": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", - "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", "dev": true, + "dependencies": { + "environment": "^1.0.0" + }, "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lint-staged/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "engines": { "node": ">=12" @@ -14111,15 +14141,15 @@ } }, "node_modules/lint-staged/node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, "dependencies": { - "restore-cursor": "^4.0.0" + "restore-cursor": "^5.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -14142,18 +14172,35 @@ } }, "node_modules/lint-staged/node_modules/commander": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", - "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", "dev": true, "engines": { - "node": ">=16" + "node": ">=18" + } + }, + "node_modules/lint-staged/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/lint-staged/node_modules/emoji-regex": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", - "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", "dev": true }, "node_modules/lint-staged/node_modules/execa": { @@ -14225,16 +14272,16 @@ } }, "node_modules/lint-staged/node_modules/listr2": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.0.1.tgz", - "integrity": "sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==", + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", + "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", "dev": true, "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", - "log-update": "^6.0.0", - "rfdc": "^1.3.0", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" }, "engines": { @@ -14242,14 +14289,14 @@ } }, "node_modules/lint-staged/node_modules/log-update": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", - "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", "dev": true, "dependencies": { - "ansi-escapes": "^6.2.0", - "cli-cursor": "^4.0.0", - "slice-ansi": "^7.0.0", + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" }, @@ -14303,6 +14350,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lint-staged/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, "node_modules/lint-staged/node_modules/npm-run-path": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", @@ -14346,51 +14399,36 @@ } }, "node_modules/lint-staged/node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lint-staged/node_modules/restore-cursor/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/lint-staged/node_modules/restore-cursor/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "dev": true, "dependencies": { - "mimic-fn": "^2.1.0" + "mimic-function": "^5.0.0" }, "engines": { - "node": ">=6" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lint-staged/node_modules/restore-cursor/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, "node_modules/lint-staged/node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -14420,9 +14458,9 @@ } }, "node_modules/lint-staged/node_modules/string-width": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", - "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "dependencies": { "emoji-regex": "^10.3.0", @@ -14588,6 +14626,11 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "node_modules/lodash.assignwith": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.assignwith/-/lodash.assignwith-4.2.0.tgz", @@ -15077,12 +15120,12 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -15132,6 +15175,18 @@ "node": ">=6" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mimic-response": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", @@ -15366,12 +15421,11 @@ } }, "node_modules/next": { - "version": "14.2.7", - "resolved": "https://registry.npmjs.org/next/-/next-14.2.7.tgz", - "integrity": "sha512-4Qy2aK0LwH4eQiSvQWyKuC7JXE13bIopEQesWE0c/P3uuNRnZCQanI0vsrMLmUQJLAto+A+/8+sve2hd+BQuOQ==", - "license": "MIT", + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.16.tgz", + "integrity": "sha512-LcO7WnFu6lYSvCzZoo1dB+IO0xXz5uEv52HF1IUN0IqVTUIZGHuuR10I5efiLadGt+4oZqTcNZyVVEem/TM5nA==", "dependencies": { - "@next/env": "14.2.7", + "@next/env": "14.2.16", "@swc/helpers": "0.5.5", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", @@ -15386,15 +15440,15 @@ "node": ">=18.17.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "14.2.7", - "@next/swc-darwin-x64": "14.2.7", - "@next/swc-linux-arm64-gnu": "14.2.7", - "@next/swc-linux-arm64-musl": "14.2.7", - "@next/swc-linux-x64-gnu": "14.2.7", - "@next/swc-linux-x64-musl": "14.2.7", - "@next/swc-win32-arm64-msvc": "14.2.7", - "@next/swc-win32-ia32-msvc": "14.2.7", - "@next/swc-win32-x64-msvc": "14.2.7" + "@next/swc-darwin-arm64": "14.2.16", + "@next/swc-darwin-x64": "14.2.16", + "@next/swc-linux-arm64-gnu": "14.2.16", + "@next/swc-linux-arm64-musl": "14.2.16", + "@next/swc-linux-x64-gnu": "14.2.16", + "@next/swc-linux-x64-musl": "14.2.16", + "@next/swc-win32-arm64-msvc": "14.2.16", + "@next/swc-win32-ia32-msvc": "14.2.16", + "@next/swc-win32-x64-msvc": "14.2.16" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", @@ -15416,17 +15470,16 @@ } }, "node_modules/next-auth": { - "version": "5.0.0-beta.19", - "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-5.0.0-beta.19.tgz", - "integrity": "sha512-YHu1igcAxZPh8ZB7GIM93dqgY6gcAzq66FOhQFheAdOx1raxNcApt05nNyNCSB6NegSiyJ4XOPsaNow4pfDmsg==", - "license": "ISC", + "version": "5.0.0-beta.25", + "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-5.0.0-beta.25.tgz", + "integrity": "sha512-2dJJw1sHQl2qxCrRk+KTQbeH+izFbGFPuJj5eGgBZFYyiYYtvlrBeUw1E/OJJxTRjuxbSYGnCTkUIRsIIW0bog==", "dependencies": { - "@auth/core": "0.32.0" + "@auth/core": "0.37.2" }, "peerDependencies": { "@simplewebauthn/browser": "^9.0.1", "@simplewebauthn/server": "^9.0.2", - "next": "^14 || ^15.0.0-0", + "next": "^14.0.0-0 || ^15.0.0-0", "nodemailer": "^6.6.5", "react": "^18.2.0 || ^19.0.0-0" }, @@ -15559,10 +15612,9 @@ "dev": true }, "node_modules/oauth4webapi": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-2.11.1.tgz", - "integrity": "sha512-aNzOnL98bL6izG97zgnZs1PFEyO4WDVRhz2Pd066NPak44w5ESLRCYmJIyey8avSBPOMtBjhF3ZDDm7bIb7UOg==", - "license": "MIT", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.1.2.tgz", + "integrity": "sha512-KQZkNU+xn02lWrFu5Vjqg9E81yPtDSxUZorRHlLWVoojD+H/0GFbH59kcnz5Thdjj7c4/mYMBPj/mhvGe/kKXA==", "funding": { "url": "https://github.com/sponsors/panva" } @@ -16047,9 +16099,9 @@ } }, "node_modules/path-to-regexp": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", - "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", "dev": true }, "node_modules/path-type": { @@ -16224,6 +16276,16 @@ "node": ">= 0.4" } }, + "node_modules/post-robot": { + "version": "8.0.31", + "resolved": "https://registry.npmjs.org/post-robot/-/post-robot-8.0.31.tgz", + "integrity": "sha512-nUhtKgtmcgyuPm4RnIhUB3gsDYJBHOgFry3TvOxhIHpgfwYY/T69d4oB90tw4YUllFZUUwqLEv1Wgyg6eOoJ7A==", + "dependencies": { + "cross-domain-safe-weakmap": "^1.0.1", + "cross-domain-utils": "^2.0.0", + "zalgo-promise": "^1.0.3" + } + }, "node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", @@ -16365,7 +16427,6 @@ "version": "10.11.3", "resolved": "https://registry.npmjs.org/preact/-/preact-10.11.3.tgz", "integrity": "sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==", - "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" @@ -16375,7 +16436,6 @@ "version": "5.2.3", "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.2.3.tgz", "integrity": "sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==", - "license": "MIT", "dependencies": { "pretty-format": "^3.8.0" }, @@ -16422,8 +16482,7 @@ "node_modules/pretty-format": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz", - "integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==", - "license": "MIT" + "integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==" }, "node_modules/process": { "version": "0.11.10", @@ -17428,9 +17487,9 @@ } }, "node_modules/rfdc": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", - "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "dev": true }, "node_modules/rimraf": { @@ -19883,10 +19942,13 @@ } }, "node_modules/yaml": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", - "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", "dev": true, + "bin": { + "yaml": "bin.mjs" + }, "engines": { "node": ">= 14" } @@ -19958,6 +20020,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/zalgo-promise": { + "version": "1.0.48", + "resolved": "https://registry.npmjs.org/zalgo-promise/-/zalgo-promise-1.0.48.tgz", + "integrity": "sha512-LLHANmdm53+MucY9aOFIggzYtUdkSBFxUsy4glTTQYNyK6B3uCPWTbfiGvSrEvLojw0mSzyFJ1/RRLv+QMNdzQ==" + }, "node_modules/zod": { "version": "3.22.4", "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", diff --git a/package.json b/package.json index 0f8bd14a2..f5f7ea4cb 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ }, "dependencies": { "@azure/monitor-opentelemetry-exporter": "^1.0.0-beta.24", - "@contentstack/live-preview-utils": "^1.4.0", + "@contentstack/live-preview-utils": "^2.0.4", "@hookform/error-message": "^2.0.1", "@hookform/resolvers": "^3.3.4", "@netlify/plugin-nextjs": "^5.1.1", diff --git a/server/routers/contentstack/bookingwidget/output.ts b/server/routers/contentstack/bookingwidget/output.ts index e113bae95..d13951a63 100644 --- a/server/routers/contentstack/bookingwidget/output.ts +++ b/server/routers/contentstack/bookingwidget/output.ts @@ -11,6 +11,7 @@ const bookingWidgetToggleSchema = z export const validateBookingWidgetToggleSchema = z.object({ account_page: bookingWidgetToggleSchema, loyalty_page: bookingWidgetToggleSchema, + collection_page: bookingWidgetToggleSchema, content_page: bookingWidgetToggleSchema, hotel_page: bookingWidgetToggleSchema, current_blocks_page: bookingWidgetToggleSchema, diff --git a/server/routers/contentstack/bookingwidget/query.ts b/server/routers/contentstack/bookingwidget/query.ts index f87899965..50af970e1 100644 --- a/server/routers/contentstack/bookingwidget/query.ts +++ b/server/routers/contentstack/bookingwidget/query.ts @@ -2,6 +2,7 @@ import { ValueOf } from "next/dist/shared/lib/constants" import { GetAccountPageSettings, + GetCollectionPageSettings, GetContentPageSettings, GetCurrentBlocksPageSettings, GetHotelPageSettings, @@ -43,6 +44,9 @@ export const bookingwidgetQueryRouter = router({ case ContentTypeEnum.loyaltyPage: GetPageSettings = GetLoyaltyPageSettings break + case ContentTypeEnum.collectionPage: + GetPageSettings = GetCollectionPageSettings + break case ContentTypeEnum.contentPage: GetPageSettings = GetContentPageSettings break diff --git a/server/routers/contentstack/breadcrumbs/output.ts b/server/routers/contentstack/breadcrumbs/output.ts index e5a058699..d9b8b2f95 100644 --- a/server/routers/contentstack/breadcrumbs/output.ts +++ b/server/routers/contentstack/breadcrumbs/output.ts @@ -50,6 +50,16 @@ export type GetLoyaltyPageBreadcrumbsRefsData = z.infer< typeof validateLoyaltyPageBreadcrumbsRefsContentstackSchema > +export const validateCollectionPageBreadcrumbsRefsContentstackSchema = z.object( + { + collection_page: breadcrumbsRefs, + } +) + +export type GetCollectionPageBreadcrumbsRefsData = z.infer< + typeof validateCollectionPageBreadcrumbsRefsContentstackSchema +> + export const validateContentPageBreadcrumbsRefsContentstackSchema = z.object({ content_page: breadcrumbsRefs, }) @@ -107,3 +117,11 @@ export const validateContentPageBreadcrumbsContentstackSchema = z.object({ export type GetContentPageBreadcrumbsData = z.infer< typeof validateContentPageBreadcrumbsContentstackSchema > + +export const validateCollectionPageBreadcrumbsContentstackSchema = z.object({ + collection_page: page, +}) + +export type GetCollectionPageBreadcrumbsData = z.infer< + typeof validateCollectionPageBreadcrumbsContentstackSchema +> diff --git a/server/routers/contentstack/breadcrumbs/query.ts b/server/routers/contentstack/breadcrumbs/query.ts index b4dc3ecd2..ff96fcc49 100644 --- a/server/routers/contentstack/breadcrumbs/query.ts +++ b/server/routers/contentstack/breadcrumbs/query.ts @@ -2,6 +2,10 @@ import { GetMyPagesBreadcrumbs, GetMyPagesBreadcrumbsRefs, } from "@/lib/graphql/Query/Breadcrumbs/AccountPage.graphql" +import { + GetCollectionPageBreadcrumbs, + GetCollectionPageBreadcrumbsRefs, +} from "@/lib/graphql/Query/Breadcrumbs/CollectionPage.graphql" import { GetContentPageBreadcrumbs, GetContentPageBreadcrumbsRefs, @@ -13,12 +17,16 @@ import { import { contentstackExtendedProcedureUID, router } from "@/server/trpc" import { + GetCollectionPageBreadcrumbsData, + GetCollectionPageBreadcrumbsRefsData, type GetContentPageBreadcrumbsData, type GetContentPageBreadcrumbsRefsData, type GetLoyaltyPageBreadcrumbsData, type GetLoyaltyPageBreadcrumbsRefsData, type GetMyPagesBreadcrumbsData, type GetMyPagesBreadcrumbsRefsData, + validateCollectionPageBreadcrumbsContentstackSchema, + validateCollectionPageBreadcrumbsRefsContentstackSchema, validateContentPageBreadcrumbsContentstackSchema, validateContentPageBreadcrumbsRefsContentstackSchema, validateLoyaltyPageBreadcrumbsContentstackSchema, @@ -84,6 +92,48 @@ async function getLoyaltyPageBreadcrumbs(variables: Variables) { ) } +async function getCollectionPageBreadcrumbs(variables: Variables) { + const refsResponse = + await getRefsResponse( + GetCollectionPageBreadcrumbsRefs, + variables + ) + const validatedRefsData = + validateCollectionPageBreadcrumbsRefsContentstackSchema.safeParse( + refsResponse.data + ) + + if (!validatedRefsData.success) { + console.error( + `Failed to validate CollectionPpage Breadcrumbs Refs - (uid: ${variables.uid})` + ) + console.error(validatedRefsData.error) + return null + } + const tags = getTags(validatedRefsData.data.collection_page, variables) + const response = await getResponse( + GetCollectionPageBreadcrumbs, + variables, + tags + ) + if (!response.data.collection_page.web?.breadcrumbs?.title) { + return null + } + const validatedBreadcrumbsData = + validateCollectionPageBreadcrumbsContentstackSchema.safeParse(response.data) + if (!validatedBreadcrumbsData.success) { + console.error( + `Failed to validate Collectionpage Breadcrumbs Data - (uid: ${variables.uid})` + ) + console.error(validatedBreadcrumbsData.error) + return null + } + return getBreadcrumbs( + validatedBreadcrumbsData.data.collection_page, + variables.locale + ) +} + async function getContentPageBreadcrumbs(variables: Variables) { const refsResponse = await getRefsResponse( GetContentPageBreadcrumbsRefs, @@ -189,6 +239,8 @@ export const breadcrumbsQueryRouter = router({ switch (ctx.contentType) { case PageTypeEnum.accountPage: return await getMyPagesBreadcrumbs(variables) + case PageTypeEnum.collectionPage: + return await getCollectionPageBreadcrumbs(variables) case PageTypeEnum.contentPage: return await getContentPageBreadcrumbs(variables) case PageTypeEnum.loyaltyPage: diff --git a/server/routers/contentstack/collectionPage/index.ts b/server/routers/contentstack/collectionPage/index.ts new file mode 100644 index 000000000..04f372da8 --- /dev/null +++ b/server/routers/contentstack/collectionPage/index.ts @@ -0,0 +1,5 @@ +import { mergeRouters } from "@/server/trpc" + +import { collectionPageQueryRouter } from "./query" + +export const collectionPageRouter = mergeRouters(collectionPageQueryRouter) diff --git a/server/routers/contentstack/collectionPage/output.ts b/server/routers/contentstack/collectionPage/output.ts new file mode 100644 index 000000000..5ea3fa9d4 --- /dev/null +++ b/server/routers/contentstack/collectionPage/output.ts @@ -0,0 +1,121 @@ +import { z } from "zod" + +import { discriminatedUnionArray } from "@/lib/discriminatedUnion" + +import { + cardGridRefsSchema, + cardsGridSchema, +} from "../schemas/blocks/cardsGrid" +import { + shortcutsRefsSchema, + shortcutsSchema, +} from "../schemas/blocks/shortcuts" +import { uspGridRefsSchema, uspGridSchema } from "../schemas/blocks/uspGrid" +import { tempImageVaultAssetSchema } from "../schemas/imageVault" +import { + linkAndTitleSchema, + linkConnectionRefs, +} from "../schemas/linkConnection" +import { systemSchema } from "../schemas/system" + +import { CollectionPageEnum } from "@/types/enums/collectionPage" + +// Block schemas +export const collectionPageCards = z + .object({ + __typename: z.literal(CollectionPageEnum.ContentStack.blocks.CardsGrid), + }) + .merge(cardsGridSchema) + +export const collectionPageShortcuts = z + .object({ + __typename: z.literal(CollectionPageEnum.ContentStack.blocks.Shortcuts), + }) + .merge(shortcutsSchema) + +export const collectionPageUspGrid = z + .object({ + __typename: z.literal(CollectionPageEnum.ContentStack.blocks.UspGrid), + }) + .merge(uspGridSchema) + +export const blocksSchema = z.discriminatedUnion("__typename", [ + collectionPageCards, + collectionPageShortcuts, + collectionPageUspGrid, +]) + +const navigationLinksSchema = z + .array(linkAndTitleSchema) + .nullable() + .transform((data) => { + if (!data) { + return null + } + + return data + .filter((item) => !!item.link) + .map((item) => ({ + url: item.link!.url, + title: item.title || item.link!.title, + })) + }) + +// Content Page Schema and types +export const collectionPageSchema = z.object({ + collection_page: z.object({ + hero_image: tempImageVaultAssetSchema, + blocks: discriminatedUnionArray(blocksSchema.options).nullable(), + title: z.string(), + header: z.object({ + heading: z.string(), + preamble: z.string(), + navigation_links: navigationLinksSchema, + }), + system: systemSchema.merge( + z.object({ + created_at: z.string(), + updated_at: z.string(), + }) + ), + }), +}) + +/** REFS */ +const collectionPageCardsRefs = z + .object({ + __typename: z.literal(CollectionPageEnum.ContentStack.blocks.CardsGrid), + }) + .merge(cardGridRefsSchema) + +const collectionPageShortcutsRefs = z + .object({ + __typename: z.literal(CollectionPageEnum.ContentStack.blocks.Shortcuts), + }) + .merge(shortcutsRefsSchema) + +const collectionPageUspGridRefs = z + .object({ + __typename: z.literal(CollectionPageEnum.ContentStack.blocks.UspGrid), + }) + .merge(uspGridRefsSchema) + +const collectionPageBlockRefsItem = z.discriminatedUnion("__typename", [ + collectionPageShortcutsRefs, + collectionPageCardsRefs, + collectionPageUspGridRefs, +]) + +const collectionPageHeaderRefs = z.object({ + navigation_links: z.array(linkConnectionRefs), +}) + +export const collectionPageRefsSchema = z.object({ + collection_page: z.object({ + header: collectionPageHeaderRefs, + blocks: discriminatedUnionArray( + collectionPageBlockRefsItem.options + ).nullable(), + system: systemSchema, + }), +}) diff --git a/server/routers/contentstack/collectionPage/query.ts b/server/routers/contentstack/collectionPage/query.ts new file mode 100644 index 000000000..196eb0098 --- /dev/null +++ b/server/routers/contentstack/collectionPage/query.ts @@ -0,0 +1,78 @@ +import { Lang } from "@/constants/languages" +import { GetCollectionPage } from "@/lib/graphql/Query/CollectionPage/CollectionPage.graphql" +import { request } from "@/lib/graphql/request" +import { contentstackExtendedProcedureUID, router } from "@/server/trpc" + +import { collectionPageSchema } from "./output" +import { + fetchCollectionPageRefs, + generatePageTags, + getCollectionPageCounter, + validateCollectionPageRefs, +} from "./utils" + +import { + TrackingChannelEnum, + type TrackingSDKPageData, +} from "@/types/components/tracking" +import { GetCollectionPageSchema } from "@/types/trpc/routers/contentstack/collectionPage" + +export const collectionPageQueryRouter = router({ + get: contentstackExtendedProcedureUID.query(async ({ ctx }) => { + const { lang, uid } = ctx + + const collectionPageRefsData = await fetchCollectionPageRefs(lang, uid) + + const collectionPageRefs = validateCollectionPageRefs( + collectionPageRefsData, + lang, + uid + ) + if (!collectionPageRefs) { + return null + } + const tags = generatePageTags(collectionPageRefs, lang) + + getCollectionPageCounter.add(1, { lang, uid }) + console.info( + "contentstack.collectionPage start", + JSON.stringify({ + query: { lang, uid }, + }) + ) + + const response = await request( + GetCollectionPage, + { locale: lang, uid }, + { + cache: "force-cache", + next: { + tags, + }, + } + ) + + const collectionPage = collectionPageSchema.safeParse(response.data) + if (!collectionPage.success) { + console.error( + `Failed to validate CollectionPage Data - (lang: ${lang}, uid: ${uid})` + ) + console.error(collectionPage.error?.format()) + return null + } + + const tracking: TrackingSDKPageData = { + pageId: collectionPage.data.collection_page.system.uid, + lang: collectionPage.data.collection_page.system.locale as Lang, + publishedDate: collectionPage.data.collection_page.system.updated_at, + createdDate: collectionPage.data.collection_page.system.created_at, + channel: TrackingChannelEnum["collection-page"], + pageType: "collectionpage", + } + + return { + collectionPage: collectionPage.data.collection_page, + tracking, + } + }), +}) diff --git a/server/routers/contentstack/collectionPage/utils.ts b/server/routers/contentstack/collectionPage/utils.ts new file mode 100644 index 000000000..cfb9ceca9 --- /dev/null +++ b/server/routers/contentstack/collectionPage/utils.ts @@ -0,0 +1,152 @@ +import { metrics } from "@opentelemetry/api" + +import { Lang } from "@/constants/languages" +import { GetCollectionPageRefs } from "@/lib/graphql/Query/CollectionPage/CollectionPage.graphql" +import { request } from "@/lib/graphql/request" +import { notFound } from "@/server/errors/trpc" + +import { generateTag, generateTagsFromSystem } from "@/utils/generateTag" + +import { collectionPageRefsSchema } from "./output" + +import { CollectionPageEnum } from "@/types/enums/collectionPage" +import { System } from "@/types/requests/system" +import { + CollectionPageRefs, + GetCollectionPageRefsSchema, +} from "@/types/trpc/routers/contentstack/collectionPage" + +const meter = metrics.getMeter("trpc.collectionPage") +// OpenTelemetry metrics: CollectionPage + +export const getCollectionPageCounter = meter.createCounter( + "trpc.contentstack.collectionPage.get" +) + +const getCollectionPageRefsCounter = meter.createCounter( + "trpc.contentstack.collectionPage.get" +) +const getCollectionPageRefsFailCounter = meter.createCounter( + "trpc.contentstack.collectionPage.get-fail" +) +const getCollectionPageRefsSuccessCounter = meter.createCounter( + "trpc.contentstack.collectionPage.get-success" +) + +export async function fetchCollectionPageRefs(lang: Lang, uid: string) { + getCollectionPageRefsCounter.add(1, { lang, uid }) + console.info( + "contentstack.collectionPage.refs start", + JSON.stringify({ + query: { lang, uid }, + }) + ) + const refsResponse = await request( + GetCollectionPageRefs, + { locale: lang, uid }, + { + cache: "force-cache", + next: { + tags: [generateTag(lang, uid)], + }, + } + ) + + if (!refsResponse.data) { + const notFoundError = notFound(refsResponse) + getCollectionPageRefsFailCounter.add(1, { + lang, + uid, + error_type: "http_error", + error: JSON.stringify({ + code: notFoundError.code, + }), + }) + console.error( + "contentstack.collectionPage.refs not found error", + JSON.stringify({ + query: { + lang, + uid, + }, + error: { code: notFoundError.code }, + }) + ) + throw notFoundError + } + + return refsResponse.data +} + +export function validateCollectionPageRefs( + data: GetCollectionPageRefsSchema, + lang: Lang, + uid: string +) { + const validatedData = collectionPageRefsSchema.safeParse(data) + if (!validatedData.success) { + getCollectionPageRefsFailCounter.add(1, { + lang, + uid, + error_type: "validation_error", + error: JSON.stringify(validatedData.error), + }) + console.error( + "contentstack.collectionPage.refs validation error", + JSON.stringify({ + query: { lang, uid }, + error: validatedData.error, + }) + ) + return null + } + getCollectionPageRefsSuccessCounter.add(1, { lang, uid }) + console.info( + "contentstack.collectionPage.refs success", + JSON.stringify({ + query: { lang, uid }, + }) + ) + + return validatedData.data +} + +export function generatePageTags( + validatedData: CollectionPageRefs, + lang: Lang +): string[] { + const connections = getConnections(validatedData) + return [ + generateTagsFromSystem(lang, connections), + generateTag(lang, validatedData.collection_page.system.uid), + ].flat() +} + +export function getConnections({ collection_page }: CollectionPageRefs) { + const connections: System["system"][] = [collection_page.system] + if (collection_page.blocks) { + collection_page.blocks.forEach((block) => { + switch (block.__typename) { + case CollectionPageEnum.ContentStack.blocks.Shortcuts: { + if (block.shortcuts.shortcuts.length) { + connections.push(...block.shortcuts.shortcuts) + } + break + } + case CollectionPageEnum.ContentStack.blocks.CardsGrid: { + if (block.cards_grid.length) { + connections.push(...block.cards_grid) + } + break + } + case CollectionPageEnum.ContentStack.blocks.UspGrid: { + if (block.usp_grid.length) { + connections.push(...block.usp_grid) + } + } + } + }) + } + + return connections +} diff --git a/server/routers/contentstack/contentPage/utils.ts b/server/routers/contentstack/contentPage/utils.ts index 6e41c92e4..092595813 100644 --- a/server/routers/contentstack/contentPage/utils.ts +++ b/server/routers/contentstack/contentPage/utils.ts @@ -162,6 +162,18 @@ export function getConnections({ content_page }: ContentPageRefs) { } } break + case ContentPageEnum.ContentStack.blocks.CardsGrid: { + if (block.cards_grid.length) { + connections.push(...block.cards_grid) + } + break + } + case ContentPageEnum.ContentStack.blocks.DynamicContent: { + if (block.dynamic_content.link) { + connections.push(block.dynamic_content.link) + } + break + } case ContentPageEnum.ContentStack.blocks.Shortcuts: { if (block.shortcuts.shortcuts.length) { connections.push(...block.shortcuts.shortcuts) diff --git a/server/routers/contentstack/index.ts b/server/routers/contentstack/index.ts index bde6065db..2456c4f97 100644 --- a/server/routers/contentstack/index.ts +++ b/server/routers/contentstack/index.ts @@ -4,6 +4,7 @@ import { accountPageRouter } from "./accountPage" import { baseRouter } from "./base" import { bookingwidgetRouter } from "./bookingwidget" import { breadcrumbsRouter } from "./breadcrumbs" +import { collectionPageRouter } from "./collectionPage" import { contentPageRouter } from "./contentPage" import { hotelPageRouter } from "./hotelPage" import { languageSwitcherRouter } from "./languageSwitcher" @@ -21,6 +22,7 @@ export const contentstackRouter = router({ hotelPage: hotelPageRouter, languageSwitcher: languageSwitcherRouter, loyaltyPage: loyaltyPageRouter, + collectionPage: collectionPageRouter, contentPage: contentPageRouter, myPages: myPagesRouter, metaData: metaDataRouter, diff --git a/server/routers/contentstack/languageSwitcher/query.ts b/server/routers/contentstack/languageSwitcher/query.ts index 89e7f82ce..3aa4cea6d 100644 --- a/server/routers/contentstack/languageSwitcher/query.ts +++ b/server/routers/contentstack/languageSwitcher/query.ts @@ -7,6 +7,10 @@ import { GetDaDeEnUrlsAccountPage, GetFiNoSvUrlsAccountPage, } from "@/lib/graphql/Query/AccountPage/AccountPage.graphql" +import { + GetDaDeEnUrlsCollectionPage, + GetFiNoSvUrlsCollectionPage, +} from "@/lib/graphql/Query/CollectionPage/CollectionPage.graphql" import { GetDaDeEnUrlsContentPage, GetFiNoSvUrlsContentPage, @@ -88,6 +92,10 @@ async function getLanguageSwitcher(options: LanguageSwitcherVariables) { daDeEnDocument = GetDaDeEnUrlsContentPage fiNoSvDocument = GetFiNoSvUrlsContentPage break + case PageTypeEnum.collectionPage: + daDeEnDocument = GetDaDeEnUrlsCollectionPage + fiNoSvDocument = GetFiNoSvUrlsCollectionPage + break default: console.error(`type: [${options.contentType}]`) console.error(`Trying to get a content type that is not supported`) diff --git a/server/routers/contentstack/schemas/blocks/cardsGrid.ts b/server/routers/contentstack/schemas/blocks/cardsGrid.ts index a9de83854..0cf13859e 100644 --- a/server/routers/contentstack/schemas/blocks/cardsGrid.ts +++ b/server/routers/contentstack/schemas/blocks/cardsGrid.ts @@ -11,6 +11,7 @@ import { imageContainerSchema } from "./imageContainer" import { BlocksEnums } from "@/types/enums/blocks" import { CardsGridEnum, CardsGridLayoutEnum } from "@/types/enums/cardsGrid" +import { scriptedCardThemeEnum } from "@/types/enums/scriptedCard" export const cardBlockSchema = z.object({ __typename: z.literal(CardsGridEnum.cards.Card), @@ -91,7 +92,22 @@ export const teaserCardBlockSchema = z.object({ has_secondary_button: z.boolean().default(false), secondary_button: buttonSchema, }) - .optional(), + .optional() + .transform((data) => { + if (!data) { + return undefined + } + + return { + ...data, + primary_button: data.has_primary_button + ? data.primary_button + : undefined, + secondary_button: data.has_secondary_button + ? data.secondary_button + : undefined, + } + }), system: systemSchema, }) @@ -146,7 +162,7 @@ export const cardsGridSchema = z.object({ }), layout: z.nativeEnum(CardsGridLayoutEnum), preamble: z.string().optional().default(""), - theme: z.enum(["one", "two", "three"]).nullable(), + theme: z.nativeEnum(scriptedCardThemeEnum).nullable(), title: z.string().optional().default(""), }) .transform((data) => { diff --git a/server/routers/contentstack/schemas/linkConnection.ts b/server/routers/contentstack/schemas/linkConnection.ts index 902e6fca1..8fd074ba9 100644 --- a/server/routers/contentstack/schemas/linkConnection.ts +++ b/server/routers/contentstack/schemas/linkConnection.ts @@ -5,6 +5,7 @@ import * as pageLinks from "@/server/routers/contentstack/schemas/pageLinks" const linkUnionSchema = z.discriminatedUnion("__typename", [ pageLinks.contentPageSchema, + pageLinks.collectionPageSchema, pageLinks.hotelPageSchema, pageLinks.loyaltyPageSchema, ]) diff --git a/server/routers/contentstack/schemas/pageLinks.ts b/server/routers/contentstack/schemas/pageLinks.ts index c98a47d2b..b23c85d96 100644 --- a/server/routers/contentstack/schemas/pageLinks.ts +++ b/server/routers/contentstack/schemas/pageLinks.ts @@ -30,6 +30,16 @@ export const extendedPageLinkSchema = pageLinkSchema.merge( }), }) ) +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({ @@ -67,6 +77,7 @@ export const loyaltyPageRefSchema = z.object({ type Data = | z.output | z.output + | z.output | z.output | z.output | Object @@ -83,6 +94,7 @@ export function transform(data: Data) { url: removeMultipleSlashes(`/${data.system.locale}/${data.url}`), } case ContentEnum.blocks.ContentPage: + case ContentEnum.blocks.CollectionPage: case ContentEnum.blocks.LoyaltyPage: // TODO: Once all links use this transform // `web` can be removed and not to be worried @@ -102,6 +114,7 @@ export function transform(data: Data) { type RefData = | z.output + | z.output | z.output | z.output | z.output @@ -112,6 +125,7 @@ export function transformRef(data: RefData) { switch (data.__typename) { case ContentEnum.blocks.AccountPage: case ContentEnum.blocks.ContentPage: + case ContentEnum.blocks.CollectionPage: case ContentEnum.blocks.HotelPage: case ContentEnum.blocks.LoyaltyPage: return data.system diff --git a/server/routers/contentstack/schemas/sidebar/scriptedCard.ts b/server/routers/contentstack/schemas/sidebar/scriptedCard.ts index 0579a4be4..a391f4bc0 100644 --- a/server/routers/contentstack/schemas/sidebar/scriptedCard.ts +++ b/server/routers/contentstack/schemas/sidebar/scriptedCard.ts @@ -7,6 +7,7 @@ import { transformCardBlockRefs, } from "../blocks/cardsGrid" +import { scriptedCardThemeEnum } from "@/types/enums/scriptedCard" import { SidebarEnums } from "@/types/enums/sidebar" export const scriptedCardsSchema = z.object({ @@ -16,17 +17,7 @@ export const scriptedCardsSchema = z.object({ .default(SidebarEnums.blocks.ScriptedCard), scripted_card: z .object({ - theme: z - .enum([ - "one", - "two", - "three", - "primaryDim", - "primaryDark", - "primaryInverted", - "primaryStrong", - ]) - .nullable(), + theme: z.nativeEnum(scriptedCardThemeEnum).nullable(), scripted_cardConnection: z.object({ edges: z.array( z.object({ diff --git a/types/components/blocks/cardsGrid.ts b/types/components/blocks/cardsGrid.ts index 5b1566b27..c4a5f0a91 100644 --- a/types/components/blocks/cardsGrid.ts +++ b/types/components/blocks/cardsGrid.ts @@ -1,4 +1,4 @@ -import { CardsGrid } from "@/types/trpc/routers/contentstack/blocks" +import type { CardsGrid } from "@/types/trpc/routers/contentstack/blocks" export interface CardsGridProps extends Pick { firstItem?: boolean diff --git a/types/components/blocks/index.ts b/types/components/blocks/index.ts index 5ddc0765c..501e8dfc9 100644 --- a/types/components/blocks/index.ts +++ b/types/components/blocks/index.ts @@ -1,8 +1,13 @@ import type { Block as AccountPageBlock } from "@/types/trpc/routers/contentstack/accountPage" +import type { Block as CollectionPageBlock } from "@/types/trpc/routers/contentstack/collectionPage" import type { Block as ContentPageBlock } from "@/types/trpc/routers/contentstack/contentPage" import type { Block as LoyaltyPageBlock } from "@/types/trpc/routers/contentstack/loyaltyPage" -export type Blocks = AccountPageBlock | ContentPageBlock | LoyaltyPageBlock +export type Blocks = + | AccountPageBlock + | CollectionPageBlock + | ContentPageBlock + | LoyaltyPageBlock export interface BlocksProps { blocks: Blocks[] diff --git a/types/components/hotelReservation/enterDetails/step.ts b/types/components/hotelReservation/enterDetails/step.ts index e52d3c856..45de5a009 100644 --- a/types/components/hotelReservation/enterDetails/step.ts +++ b/types/components/hotelReservation/enterDetails/step.ts @@ -4,3 +4,10 @@ export enum StepEnum { details = "details", payment = "payment", } + +export const StepStoreKeys: Record = { + "select-bed": "bedType", + breakfast: "breakfast", + details: null, + payment: null, +} diff --git a/types/components/tracking.ts b/types/components/tracking.ts index 72aa6f853..aa42ae5fe 100644 --- a/types/components/tracking.ts +++ b/types/components/tracking.ts @@ -5,6 +5,7 @@ import type { Lang } from "@/constants/languages" export enum TrackingChannelEnum { "scandic-friends" = "scandic-friends", "static-content-page" = "static-content-page", + "collection-page" = "collection-page", } export type TrackingChannel = keyof typeof TrackingChannelEnum diff --git a/types/enums/collectionPage.ts b/types/enums/collectionPage.ts new file mode 100644 index 000000000..d48d68e34 --- /dev/null +++ b/types/enums/collectionPage.ts @@ -0,0 +1,9 @@ +export namespace CollectionPageEnum { + export namespace ContentStack { + export const enum blocks { + CardsGrid = "CollectionPageBlocksCardsGrid", + Shortcuts = "CollectionPageBlocksShortcuts", + UspGrid = "CollectionPageBlocksUspGrid", + } + } +} diff --git a/types/enums/content.ts b/types/enums/content.ts index ad94dbd28..cc2a84e15 100644 --- a/types/enums/content.ts +++ b/types/enums/content.ts @@ -1,6 +1,7 @@ export namespace ContentEnum { export const enum blocks { AccountPage = "AccountPage", + CollectionPage = "CollectionPage", ContentPage = "ContentPage", HotelPage = "HotelPage", ImageContainer = "ImageContainer", diff --git a/types/enums/scriptedCard.ts b/types/enums/scriptedCard.ts new file mode 100644 index 000000000..658a84621 --- /dev/null +++ b/types/enums/scriptedCard.ts @@ -0,0 +1,9 @@ +export enum scriptedCardThemeEnum { + one = "one", + two = "two", + three = "three", + primaryDim = "primaryDim", + primaryDark = "primaryDark", + primaryInverted = "primaryInverted", + primaryStrong = "primaryStrong", +} diff --git a/types/params.ts b/types/params.ts index fff91effc..ed2706c37 100644 --- a/types/params.ts +++ b/types/params.ts @@ -17,7 +17,11 @@ export type StatusParams = { } export type ContentTypeParams = { - contentType: "loyalty-page" | "content-page" | "hotel-page" + contentType: + | "loyalty-page" + | "content-page" + | "hotel-page" + | "collection-page" } export type ContentTypeWebviewParams = { diff --git a/types/requests/contentType.ts b/types/requests/contentType.ts index 605c96c9b..1744af9a0 100644 --- a/types/requests/contentType.ts +++ b/types/requests/contentType.ts @@ -2,6 +2,7 @@ export enum ContentTypeEnum { accountPage = "account_page", loyaltyPage = "loyalty_page", hotelPage = "hotel_page", + collectionPage = "collection_page", contentPage = "content_page", currentBlocksPage = "current_blocks_page", } diff --git a/types/requests/entry.ts b/types/requests/entry.ts index e86b1a4ca..6429fee68 100644 --- a/types/requests/entry.ts +++ b/types/requests/entry.ts @@ -14,6 +14,7 @@ const entryResolveSchema = z.object({ export const validateEntryResolveSchema = z.object({ all_account_page: entryResolveSchema, + all_collection_page: entryResolveSchema, all_content_page: entryResolveSchema, all_loyalty_page: entryResolveSchema, all_current_blocks_page: entryResolveSchema, diff --git a/types/requests/pageType.ts b/types/requests/pageType.ts index 001e6a486..6ac02e9f4 100644 --- a/types/requests/pageType.ts +++ b/types/requests/pageType.ts @@ -3,5 +3,6 @@ export enum PageTypeEnum { loyaltyPage = "loyalty-page", hotelPage = "hotel-page", contentPage = "content-page", + collectionPage = "collection-page", currentBlocksPage = "current-blocks-page", } diff --git a/types/trpc/routers/contentstack/collectionPage.ts b/types/trpc/routers/contentstack/collectionPage.ts new file mode 100644 index 000000000..f1936fac9 --- /dev/null +++ b/types/trpc/routers/contentstack/collectionPage.ts @@ -0,0 +1,20 @@ +import { z } from "zod" + +import { + blocksSchema, + collectionPageRefsSchema, + collectionPageSchema, +} from "@/server/routers/contentstack/collectionPage/output" + +export interface GetCollectionPageRefsSchema + extends z.input {} + +export interface CollectionPageRefs + extends z.output {} + +export interface GetCollectionPageSchema + extends z.input {} + +export interface CollectionPage extends z.output {} + +export type Block = z.output