Merged in fix/sw-3551-rsc-bookingflowconfig (pull request #2988)

fix(SW-3551): Fix issue with BookingConfigProvider in RSC

* wip move config to pages

* Move config providing to pages
This commit is contained in:
Anton Gunnarsson
2025-10-22 07:04:21 +00:00
parent 2a28681259
commit c435cdba68
44 changed files with 398 additions and 237 deletions

View File

@@ -1,6 +1,8 @@
import { BookingWidget } from "@scandic-hotels/booking-flow/BookingWidget"
import { parseBookingWidgetSearchParams } from "@scandic-hotels/booking-flow/utils/url"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import { getLang } from "@/i18n/serverContext"
import type { LangParams, PageArgs } from "@/types/params"
@@ -12,5 +14,7 @@ export default async function BookingWidgetPage(props: PageArgs<LangParams>) {
const lang = await getLang()
return <BookingWidget booking={booking} lang={lang} />
return (
<BookingWidget booking={booking} lang={lang} config={bookingFlowConfig} />
)
}

View File

@@ -1,5 +1,7 @@
import { BookingWidgetSkeleton } from "@scandic-hotels/booking-flow/BookingWidget"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
// This file is crucial for displaying a loading
// state immediately in the booking flow.
// Next doesn't recognize manually added Suspense
@@ -7,5 +9,5 @@ import { BookingWidgetSkeleton } from "@scandic-hotels/booking-flow/BookingWidge
// thus making it seem as the page is frozen during
// the time it takes for `BookingWidget` to resolve.
export default function BookingWidgetLoading() {
return <BookingWidgetSkeleton />
return <BookingWidgetSkeleton config={bookingFlowConfig} />
}

View File

@@ -2,6 +2,7 @@ import { BookingWidget } from "@scandic-hotels/booking-flow/BookingWidget"
import { parseBookingWidgetSearchParams } from "@scandic-hotels/booking-flow/utils/url"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import { serverClient } from "@/lib/trpc"
import { getIntl } from "@/i18n"
@@ -33,7 +34,7 @@ export default async function Debug(props: SearchParams) {
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
<p>from booking-flow package:</p>
</Typography>
<BookingWidget booking={booking} lang={lang} />
<BookingWidget booking={booking} lang={lang} config={bookingFlowConfig} />
<hr />
<Typography variant="Title/Decorative/lg">
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}

View File

@@ -1,5 +1,7 @@
import { BookingConfirmationPage as BookingConfirmationPagePrimitive } from "@scandic-hotels/booking-flow/pages/BookingConfirmationPage"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import { getIntl } from "@/i18n"
import { getLang } from "@/i18n/serverContext"
@@ -17,6 +19,7 @@ export default async function BookingConfirmationPage(
intl={intl}
lang={lang}
searchParams={searchParams}
config={bookingFlowConfig}
/>
)
}

View File

@@ -1,6 +1,8 @@
import { PaymentCallbackPage as PaymentCallbackPagePrimitive } from "@scandic-hotels/booking-flow/pages/PaymentCallbackPage"
import { logger } from "@scandic-hotels/common/logger"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import type { PaymentCallbackStatusEnum } from "@scandic-hotels/common/constants/paymentCallbackStatusEnum"
import type { LangParams, PageArgs } from "@/types/params"
@@ -26,6 +28,7 @@ export default async function PaymentCallbackPage(
userAccessToken={userAccessToken}
searchParams={searchParams}
status={params.status as PaymentCallbackStatusEnum}
config={bookingFlowConfig}
/>
)
}

View File

@@ -1,5 +1,6 @@
import { AlternativeHotelsMapPage as AlternativeHotelsMapPagePrimitive } from "@scandic-hotels/booking-flow/pages/AlternativeHotelsMapPage"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import { getHotel } from "@/lib/trpc/memoizedRequests/getHotel"
import { getIntl } from "@/i18n"
@@ -56,6 +57,7 @@ export default async function AlternativeHotelsMapPage(
<AlternativeHotelsMapPagePrimitive
lang={lang}
searchParams={searchParams}
config={bookingFlowConfig}
/>
</div>
)

View File

@@ -1,5 +1,6 @@
import { AlternativeHotelsPage as AlternativeHotelsPagePrimitive } from "@scandic-hotels/booking-flow/pages/AlternativeHotelsPage"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import { getHotel } from "@/lib/trpc/memoizedRequests/getHotel"
import { getIntl } from "@/i18n"
@@ -52,6 +53,10 @@ export default async function AlternativeHotelsPage(
const lang = await getLang()
return (
<AlternativeHotelsPagePrimitive lang={lang} searchParams={searchParams} />
<AlternativeHotelsPagePrimitive
lang={lang}
searchParams={searchParams}
config={bookingFlowConfig}
/>
)
}

View File

@@ -1,10 +1,18 @@
import { EnterDetailsPage as EnterDetailsPagePrimitive } from "@scandic-hotels/booking-flow/pages/EnterDetailsPage"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import type { LangParams, PageArgs } from "@/types/params"
export default async function DetailsPage(props: PageArgs<LangParams>) {
const { lang } = await props.params
const searchParams = await props.searchParams
return <EnterDetailsPagePrimitive lang={lang} searchParams={searchParams} />
return (
<EnterDetailsPagePrimitive
lang={lang}
searchParams={searchParams}
config={bookingFlowConfig}
/>
)
}

View File

@@ -1,6 +1,8 @@
import { SelectHotelMapPage as SelectHotelMapPagePrimitive } from "@scandic-hotels/booking-flow/pages/SelectHotelMapPage"
import { toCapitalCase } from "@scandic-hotels/common/utils/toCapitalCase"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import { getLang } from "@/i18n/serverContext"
import type { Metadata } from "next"
@@ -25,5 +27,11 @@ export default async function SelectHotelMapPage(props: PageArgs<LangParams>) {
const searchParams = await props.searchParams
const lang = await getLang()
return <SelectHotelMapPagePrimitive lang={lang} searchParams={searchParams} />
return (
<SelectHotelMapPagePrimitive
lang={lang}
searchParams={searchParams}
config={bookingFlowConfig}
/>
)
}

View File

@@ -1,6 +1,8 @@
import { SelectHotelPage as SelectHotelPagePrimitive } from "@scandic-hotels/booking-flow/pages/SelectHotelPage"
import { toCapitalCase } from "@scandic-hotels/common/utils/toCapitalCase"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import { getLang } from "@/i18n/serverContext"
import type { Metadata } from "next"
@@ -25,5 +27,11 @@ export default async function SelectHotelPage(props: PageArgs<LangParams>) {
const searchParams = await props.searchParams
const lang = await getLang()
return <SelectHotelPagePrimitive lang={lang} searchParams={searchParams} />
return (
<SelectHotelPagePrimitive
lang={lang}
searchParams={searchParams}
config={bookingFlowConfig}
/>
)
}

View File

@@ -1,5 +1,6 @@
import { SelectRatePage as SelectRatePagePrimitive } from "@scandic-hotels/booking-flow/pages/SelectRatePage"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import { getHotel } from "@/lib/trpc/memoizedRequests/getHotel"
import { getLang } from "@/i18n/serverContext"
@@ -38,5 +39,11 @@ export default async function SelectRatePage(props: PageArgs<LangParams>) {
const searchParams = await props.searchParams
const lang = await getLang()
return <SelectRatePagePrimitive lang={lang} searchParams={searchParams} />
return (
<SelectRatePagePrimitive
lang={lang}
searchParams={searchParams}
config={bookingFlowConfig}
/>
)
}

View File

@@ -8,13 +8,8 @@ import { ReactQueryDevtools } from "@tanstack/react-query-devtools"
import Script from "next/script"
import { SessionProvider } from "next-auth/react"
import { BookingFlowConfig } from "@scandic-hotels/booking-flow/BookingFlowConfig"
import { NuqsAdapter } from "@scandic-hotels/booking-flow/utils/nuqs"
import { Lang } from "@scandic-hotels/common/constants/language"
import { bookingTermsAndConditionsRoutes } from "@scandic-hotels/common/constants/routes/bookingTermsAndConditionsRoutes"
import { customerService } from "@scandic-hotels/common/constants/routes/customerService"
import { myStay } from "@scandic-hotels/common/constants/routes/myStay"
import { privacyPolicyRoutes } from "@scandic-hotels/common/constants/routes/privacyPolicyRoutes"
import { ToastHandler } from "@scandic-hotels/design-system/ToastHandler"
import AdobeSDKScript from "@/components/AdobeSDKScript"
@@ -34,8 +29,6 @@ import { Footer } from "../../components/Footer/Footer"
import { Header } from "../../components/Header/Header"
import { SocialLoginProvider } from "./(auth)/SocialLogin"
import type { LangRoute } from "@scandic-hotels/common/constants/routes/langRoute"
type LangParams = {
lang: Lang
}
@@ -55,20 +48,6 @@ export default async function RootLayout(props: RootLayoutProps) {
const parsedLanguage = setLang(lang)
const messages = await getMessages(parsedLanguage)
const bookingFlowConfig: BookingFlowConfig = {
bookingCodeEnabled: false,
enterDetailsMembershipIdInputLocation: "join-card",
variant: "partner-sas",
routes: {
myStay: routeToScandicWeb(myStay),
bookingTermsAndConditions: routeToScandicWeb(
bookingTermsAndConditionsRoutes
),
customerService: routeToScandicWeb(customerService),
privacyPolicy: routeToScandicWeb(privacyPolicyRoutes),
},
}
return (
<html lang={lang}>
<head>
@@ -93,7 +72,6 @@ export default async function RootLayout(props: RootLayoutProps) {
<TrpcProvider>
<SocialLoginProvider>
<RACRouterProvider>
<BookingFlowConfig config={bookingFlowConfig}>
<BookingFlowProviders>
<RouteChange />
<SiteWideAlert />
@@ -105,7 +83,6 @@ export default async function RootLayout(props: RootLayoutProps) {
<CookieBotConsent />
<ReactQueryDevtools initialIsOpen={false} />
</BookingFlowProviders>
</BookingFlowConfig>
</RACRouterProvider>
</SocialLoginProvider>
</TrpcProvider>
@@ -127,11 +104,3 @@ export default async function RootLayout(props: RootLayoutProps) {
</html>
)
}
function routeToScandicWeb(route: LangRoute) {
const url = `https://www.scandichotels.com`
return Object.entries(route).reduce((acc, [key, value]) => {
acc[key as Lang] = `${url}${value}`
return acc
}, {} as LangRoute)
}

View File

@@ -3,6 +3,8 @@ import { parseBookingWidgetSearchParams } from "@scandic-hotels/booking-flow/uti
import Image from "@scandic-hotels/design-system/Image"
import { TrackingSDK } from "@scandic-hotels/tracking/TrackingSDK"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import { getLang } from "@/i18n/serverContext"
import LandingPageHeroImage from "@/public/_static/img/landing-page-hero.png"
@@ -30,7 +32,11 @@ export default async function Home(props: PageArgs<LangParams>) {
<>
<section className={styles.mainContent}>
<div className={styles.bookingWidgetWrapper}>
<FloatingBookingWidget booking={booking} lang={lang} />
<FloatingBookingWidget
booking={booking}
lang={lang}
config={bookingFlowConfig}
/>
</div>
<Image
alt="Hero Image"

View File

@@ -0,0 +1,30 @@
import { bookingTermsAndConditionsRoutes } from "@scandic-hotels/common/constants/routes/bookingTermsAndConditionsRoutes"
import { customerService } from "@scandic-hotels/common/constants/routes/customerService"
import { myStay } from "@scandic-hotels/common/constants/routes/myStay"
import { privacyPolicyRoutes } from "@scandic-hotels/common/constants/routes/privacyPolicyRoutes"
import type { BookingFlowConfig } from "@scandic-hotels/booking-flow/BookingFlowConfig"
import type { Lang } from "@scandic-hotels/common/constants/language"
import type { LangRoute } from "@scandic-hotels/common/constants/routes/langRoute"
export const bookingFlowConfig: BookingFlowConfig = {
bookingCodeEnabled: false,
enterDetailsMembershipIdInputLocation: "join-card",
variant: "partner-sas",
routes: {
myStay: routeToScandicWeb(myStay),
bookingTermsAndConditions: routeToScandicWeb(
bookingTermsAndConditionsRoutes
),
customerService: routeToScandicWeb(customerService),
privacyPolicy: routeToScandicWeb(privacyPolicyRoutes),
},
}
function routeToScandicWeb(route: LangRoute) {
const url = `https://www.scandichotels.com`
return Object.entries(route).reduce((acc, [key, value]) => {
acc[key as Lang] = `${url}${value}`
return acc
}, {} as LangRoute)
}

View File

@@ -1,5 +1,7 @@
import { BookingConfirmationPage as BookingConfirmationPagePrimitive } from "@scandic-hotels/booking-flow/pages/BookingConfirmationPage"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import { getIntl } from "@/i18n"
import { getLang } from "@/i18n/serverContext"
@@ -17,6 +19,7 @@ export default async function BookingConfirmationPage(
intl={intl}
lang={lang}
searchParams={searchParams}
config={bookingFlowConfig}
/>
)
}

View File

@@ -2,6 +2,8 @@ import { PaymentCallbackPage as PaymentCallbackPagePrimitive } from "@scandic-ho
import { logger } from "@scandic-hotels/common/logger"
import { isValidSession } from "@scandic-hotels/trpc/utils/session"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import { auth } from "@/auth"
import type { PaymentCallbackStatusEnum } from "@scandic-hotels/common/constants/paymentCallbackStatusEnum"
@@ -35,6 +37,7 @@ export default async function PaymentCallbackPage(
searchParams={searchParams}
// TODO refactor this route to get this from params instead of rewriting in next.config
status={searchParams.status as PaymentCallbackStatusEnum}
config={bookingFlowConfig}
/>
)
}

View File

@@ -1,5 +1,6 @@
import { AlternativeHotelsMapPage as AlternativeHotelsMapPagePrimitive } from "@scandic-hotels/booking-flow/pages/AlternativeHotelsMapPage"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import { getHotel } from "@/lib/trpc/memoizedRequests"
import { getIntl } from "@/i18n"
@@ -58,6 +59,7 @@ export default async function AlternativeHotelsMapPage(
<AlternativeHotelsMapPagePrimitive
lang={lang}
searchParams={searchParams}
config={bookingFlowConfig}
/>
</div>
)

View File

@@ -1,5 +1,6 @@
import { AlternativeHotelsPage as AlternativeHotelsPagePrimitive } from "@scandic-hotels/booking-flow/pages/AlternativeHotelsPage"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import { getHotel } from "@/lib/trpc/memoizedRequests"
import { getIntl } from "@/i18n"
@@ -55,6 +56,10 @@ export default async function AlternativeHotelsPage(
const searchParams = await props.searchParams
const lang = await getLang()
return (
<AlternativeHotelsPagePrimitive lang={lang} searchParams={searchParams} />
<AlternativeHotelsPagePrimitive
lang={lang}
searchParams={searchParams}
config={bookingFlowConfig}
/>
)
}

View File

@@ -1,5 +1,7 @@
import { EnterDetailsPage as EnterDetailsPagePrimitive } from "@scandic-hotels/booking-flow/pages/EnterDetailsPage"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import type { LangParams, NextSearchParams, PageArgs } from "@/types/params"
export default async function DetailsPage(
@@ -8,5 +10,11 @@ export default async function DetailsPage(
const { lang } = await props.params
const searchParams = await props.searchParams
return <EnterDetailsPagePrimitive lang={lang} searchParams={searchParams} />
return (
<EnterDetailsPagePrimitive
lang={lang}
searchParams={searchParams}
config={bookingFlowConfig}
/>
)
}

View File

@@ -1,6 +1,8 @@
import { SelectHotelMapPage as SelectHotelMapPagePrimitive } from "@scandic-hotels/booking-flow/pages/SelectHotelMapPage"
import { toCapitalCase } from "@scandic-hotels/common/utils/toCapitalCase"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import { getLang } from "@/i18n/serverContext"
import styles from "./page.module.css"
@@ -27,7 +29,11 @@ export default async function SelectHotelMapPage(
return (
<div className={styles.main}>
<SelectHotelMapPagePrimitive lang={lang} searchParams={searchParams} />
<SelectHotelMapPagePrimitive
lang={lang}
searchParams={searchParams}
config={bookingFlowConfig}
/>
</div>
)
}

View File

@@ -1,6 +1,8 @@
import { SelectHotelPage as SelectHotelPagePrimitive } from "@scandic-hotels/booking-flow/pages/SelectHotelPage"
import { toCapitalCase } from "@scandic-hotels/common/utils/toCapitalCase"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import { getLang } from "@/i18n/serverContext"
import type { Metadata } from "next"
@@ -23,5 +25,11 @@ export default async function SelectHotelPage(
const searchParams = await props.searchParams
const lang = await getLang()
return <SelectHotelPagePrimitive lang={lang} searchParams={searchParams} />
return (
<SelectHotelPagePrimitive
lang={lang}
searchParams={searchParams}
config={bookingFlowConfig}
/>
)
}

View File

@@ -1,5 +1,6 @@
import { SelectRatePage as SelectRatePagePrimitive } from "@scandic-hotels/booking-flow/pages/SelectRatePage"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import { getHotel } from "@/lib/trpc/memoizedRequests"
import { getLang } from "@/i18n/serverContext"
@@ -40,5 +41,11 @@ export default async function SelectRatePage(
const searchParams = await props.searchParams
const lang = await getLang()
return <SelectRatePagePrimitive lang={lang} searchParams={searchParams} />
return (
<SelectRatePagePrimitive
lang={lang}
searchParams={searchParams}
config={bookingFlowConfig}
/>
)
}

View File

@@ -1,6 +1,7 @@
import { BookingWidget } from "@scandic-hotels/booking-flow/BookingWidget"
import { parseBookingWidgetSearchParams } from "@scandic-hotels/booking-flow/utils/url"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import { getDestinationCityPage } from "@/lib/trpc/memoizedRequests"
import { getLang } from "@/i18n/serverContext"
@@ -24,5 +25,7 @@ export default async function BookingWidgetDestinationCityPage(
const lang = await getLang()
return <BookingWidget booking={booking} lang={lang} />
return (
<BookingWidget booking={booking} lang={lang} config={bookingFlowConfig} />
)
}

View File

@@ -1,6 +1,7 @@
import { BookingWidget } from "@scandic-hotels/booking-flow/BookingWidget"
import { parseBookingWidgetSearchParams } from "@scandic-hotels/booking-flow/utils/url"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import { getHotel, getHotelPage } from "@/lib/trpc/memoizedRequests"
import { getLang } from "@/i18n/serverContext"
@@ -36,5 +37,7 @@ export default async function BookingWidgetHotelPage(
const booking = parseBookingWidgetSearchParams(bookingWidgetSearchParams)
return <BookingWidget booking={booking} lang={lang} />
return (
<BookingWidget booking={booking} lang={lang} config={bookingFlowConfig} />
)
}

View File

@@ -1,5 +1,7 @@
import { BookingWidgetSkeleton } from "@scandic-hotels/booking-flow/BookingWidget"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
// This file is crucial for displaying a loading
// state immediately in the booking flow.
// Next doesn't recognize manually added Suspense
@@ -7,5 +9,5 @@ import { BookingWidgetSkeleton } from "@scandic-hotels/booking-flow/BookingWidge
// thus making it seem as the page is frozen during
// the time it takes for `BookingWidget` to resolve.
export default function BookingWidgetLoading() {
return <BookingWidgetSkeleton />
return <BookingWidgetSkeleton config={bookingFlowConfig} />
}

View File

@@ -1,6 +1,8 @@
import { BookingWidget } from "@scandic-hotels/booking-flow/BookingWidget"
import { parseBookingWidgetSearchParams } from "@scandic-hotels/booking-flow/utils/url"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import { getLang } from "@/i18n/serverContext"
import type { LangParams, NextSearchParams, PageArgs } from "@/types/params"
@@ -14,5 +16,7 @@ export default async function BookingWidgetPage(
const lang = await getLang()
return <BookingWidget booking={booking} lang={lang} />
return (
<BookingWidget booking={booking} lang={lang} config={bookingFlowConfig} />
)
}

View File

@@ -1,6 +1,8 @@
import { BookingWidget } from "@scandic-hotels/booking-flow/BookingWidget"
import { parseBookingWidgetSearchParams } from "@scandic-hotels/booking-flow/utils/url"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import { getLang } from "@/i18n/serverContext"
import type { LangParams, NextSearchParams, PageArgs } from "@/types/params"
@@ -14,5 +16,7 @@ export default async function BookingWidgetPage(
const lang = await getLang()
return <BookingWidget booking={booking} lang={lang} />
return (
<BookingWidget booking={booking} lang={lang} config={bookingFlowConfig} />
)
}

View File

@@ -9,13 +9,11 @@ import { ReactQueryDevtools } from "@tanstack/react-query-devtools"
import Script from "next/script"
import { SessionProvider } from "next-auth/react"
import { BookingFlowConfig } from "@scandic-hotels/booking-flow/BookingFlowConfig"
import StorageCleaner from "@scandic-hotels/booking-flow/components/EnterDetails/StorageCleaner"
import { NuqsAdapter } from "@scandic-hotels/booking-flow/utils/nuqs"
import { Lang } from "@scandic-hotels/common/constants/language"
import { ToastHandler } from "@scandic-hotels/design-system/ToastHandler"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import TrpcProvider from "@/lib/trpc/Provider"
import { SessionRefresher } from "@/components/Auth/TokenRefresher"
@@ -75,7 +73,6 @@ export default async function RootLayout(
<NuqsAdapter>
<TrpcProvider>
<RACRouterProvider>
<BookingFlowConfig config={bookingFlowConfig}>
<BookingFlowProviders>
<RouteChange />
<SitewideAlert />
@@ -90,7 +87,6 @@ export default async function RootLayout(
<UserExists />
<ReactQueryDevtools initialIsOpen={false} />
</BookingFlowProviders>
</BookingFlowConfig>
</RACRouterProvider>
</TrpcProvider>
</NuqsAdapter>

View File

@@ -9,13 +9,11 @@ import { ReactQueryDevtools } from "@tanstack/react-query-devtools"
import Script from "next/script"
import { SessionProvider } from "next-auth/react"
import { BookingFlowConfig } from "@scandic-hotels/booking-flow/BookingFlowConfig"
import StorageCleaner from "@scandic-hotels/booking-flow/components/EnterDetails/StorageCleaner"
import { NuqsAdapter } from "@scandic-hotels/booking-flow/utils/nuqs"
import { Lang } from "@scandic-hotels/common/constants/language"
import { ToastHandler } from "@scandic-hotels/design-system/ToastHandler"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import TrpcProvider from "@/lib/trpc/Provider"
import { SessionRefresher } from "@/components/Auth/TokenRefresher"
@@ -59,7 +57,6 @@ export default async function RootLayout(
>
<NuqsAdapter>
<TrpcProvider>
<BookingFlowConfig config={bookingFlowConfig}>
<RouteChange />
{children}
<ToastHandler />
@@ -67,7 +64,6 @@ export default async function RootLayout(
<StorageCleaner />
<CookieBotConsent />
<ReactQueryDevtools initialIsOpen={false} />
</BookingFlowConfig>
</TrpcProvider>
</NuqsAdapter>
</ClientIntlProvider>

View File

@@ -8,13 +8,11 @@ import "@scandic-hotels/common/polyfills"
import { ReactQueryDevtools } from "@tanstack/react-query-devtools"
import Script from "next/script"
import { BookingFlowConfig } from "@scandic-hotels/booking-flow/BookingFlowConfig"
import StorageCleaner from "@scandic-hotels/booking-flow/components/EnterDetails/StorageCleaner"
import { NuqsAdapter } from "@scandic-hotels/booking-flow/utils/nuqs"
import { Lang } from "@scandic-hotels/common/constants/language"
import { ToastHandler } from "@scandic-hotels/design-system/ToastHandler"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import TrpcProvider from "@/lib/trpc/Provider"
import TokenRefresher from "@/components/Auth/TokenRefresher"
@@ -59,7 +57,6 @@ export default async function RootLayout(
>
<NuqsAdapter>
<TrpcProvider>
<BookingFlowConfig config={bookingFlowConfig}>
<RouteChange />
{children}
<ToastHandler />
@@ -67,7 +64,6 @@ export default async function RootLayout(
<StorageCleaner />
<CookieBotConsent />
<ReactQueryDevtools initialIsOpen={false} />
</BookingFlowConfig>
</TrpcProvider>
</NuqsAdapter>
</ClientIntlProvider>

View File

@@ -4,6 +4,7 @@ import { Typography } from "@scandic-hotels/design-system/Typography"
import { TrackingSDK } from "@scandic-hotels/tracking/TrackingSDK"
import { BlocksEnums } from "@scandic-hotels/trpc/types/blocksEnum"
import { bookingFlowConfig } from "@/constants/bookingFlowConfig"
import { getStartPage } from "@/lib/trpc/memoizedRequests"
import Blocks from "@/components/Blocks"
@@ -36,7 +37,11 @@ export default async function StartPage({
<h1>{header.heading}</h1>
</Typography>
) : null}
<FloatingBookingWidget booking={booking} lang={lang} />
<FloatingBookingWidget
booking={booking}
lang={lang}
config={bookingFlowConfig}
/>
</div>
{header.hero_image ? (
<Image

View File

@@ -54,7 +54,7 @@ export default function BookingWidgetClient({
const [originalOverflowY, setOriginalOverflowY] = useState<string | null>(
null
)
const { bookingCodeEnabled } = useBookingFlowConfig()
const bookingFlowConfig = useBookingFlowConfig()
const storedBookingWidgetState = useBookingWidgetState()
const shouldFetchAutoComplete = !!data.hotelId || !!data.city
@@ -128,7 +128,7 @@ export default function BookingWidgetClient({
toDate: toDate.format("YYYY-MM-DD"),
},
bookingCode: {
value: bookingCodeEnabled ? selectedBookingCode : "",
value: bookingFlowConfig.bookingCodeEnabled ? selectedBookingCode : "",
remember: false,
},
redemption: data.searchType === SEARCH_TYPE_REDEMPTION,
@@ -228,7 +228,7 @@ export default function BookingWidgetClient({
}, [data, methods, storedBookingWidgetState])
if (shouldShowSkeleton) {
return <BookingWidgetSkeleton type={type} />
return <BookingWidgetSkeleton type={type} config={bookingFlowConfig} />
}
const classNames = bookingWidgetContainerVariants({

View File

@@ -1,3 +1,4 @@
import { BookingFlowConfig } from "../../../bookingFlowConfig/bookingFlowConfig"
import {
getPageSettingsBookingCode,
isBookingWidgetHidden,
@@ -9,6 +10,7 @@ import type { BookingWidgetProps } from ".."
export async function FloatingBookingWidget({
booking,
lang,
config,
}: Omit<BookingWidgetProps, "type">) {
const isHidden = await isBookingWidgetHidden(lang)
@@ -22,9 +24,11 @@ export async function FloatingBookingWidget({
}
return (
<BookingFlowConfig config={config}>
<FloatingBookingWidgetClient
data={booking}
pageSettingsBookingCodePromise={pageSettingsBookingCodePromise}
/>
</BookingFlowConfig>
)
}

View File

@@ -1,30 +1,34 @@
"use client"
import { BookingFlowConfigContextProvider } from "../../bookingFlowConfig/bookingFlowConfigContext"
import { BookingWidgetFormSkeleton } from "./BookingWidgetForm"
import { MobileToggleButtonSkeleton } from "./MobileToggleButton"
import { bookingWidgetContainerVariants } from "./variant"
import styles from "./bookingWidget.module.css"
import type { BookingFlowConfig } from "../../bookingFlowConfig/bookingFlowConfig"
import type { BookingWidgetClientProps } from "./Client"
export function BookingWidgetSkeleton({
type = "full",
config,
}: {
type?: BookingWidgetClientProps["type"]
config: BookingFlowConfig
}) {
const classNames = bookingWidgetContainerVariants({
type,
})
return (
<>
<BookingFlowConfigContextProvider config={config}>
<section className={classNames} style={{ top: 0 }}>
<MobileToggleButtonSkeleton />
<div className={styles.formContainer}>
<BookingWidgetFormSkeleton type={type} />
</div>
</section>
</>
</BookingFlowConfigContextProvider>
)
}

View File

@@ -1,5 +1,6 @@
import { Suspense } from "react"
import { BookingFlowConfig } from "../../bookingFlowConfig/bookingFlowConfig"
import {
getPageSettingsBookingCode,
isBookingWidgetHidden,
@@ -39,13 +40,16 @@ export type BookingWidgetProps = {
type?: BookingWidgetType
booking: BookingWidgetSearchData
lang: Lang
config: BookingFlowConfig
}
export async function BookingWidget(props: BookingWidgetProps) {
export async function BookingWidget({ config, ...props }: BookingWidgetProps) {
return (
<Suspense fallback={<BookingWidgetSkeleton />}>
<BookingFlowConfig config={config}>
<Suspense fallback={<BookingWidgetSkeleton config={config} />}>
<InternalBookingWidget {...props} />
</Suspense>
</BookingFlowConfig>
)
}
@@ -53,7 +57,7 @@ async function InternalBookingWidget({
lang,
type,
booking,
}: BookingWidgetProps) {
}: Omit<BookingWidgetProps, "config">) {
const isHidden = await isBookingWidgetHidden(lang)
if (isHidden) {

View File

@@ -5,7 +5,7 @@ import { safeTry } from "@scandic-hotels/common/utils/safeTry"
import { TrackingSDK } from "@scandic-hotels/tracking/TrackingSDK"
import { env } from "../../env/server"
import { getBookingFlowConfig } from "../bookingFlowConfig/bookingFlowConfig"
import { BookingFlowConfig } from "../bookingFlowConfig/bookingFlowConfig"
import { MapContainer } from "../components/MapContainer"
import {
getFiltersFromHotels,
@@ -27,9 +27,11 @@ import type { NextSearchParams } from "../types"
export async function AlternativeHotelsMapPage({
lang,
searchParams,
config,
}: {
lang: Lang
searchParams: NextSearchParams
config: BookingFlowConfig
}) {
const googleMapId = env.GOOGLE_DYNAMIC_MAP_ID
const googleMapsApiKey = env.GOOGLE_STATIC_MAP_KEY
@@ -103,12 +105,13 @@ export async function AlternativeHotelsMapPage({
isBookingCodeRateAvailable,
isRedemption: redemption,
isRedemptionAvailable: isRedemptionAvailability,
config: getBookingFlowConfig(),
config,
})
const filterList = getFiltersFromHotels(hotels, isBookingCodeRateAvailable)
return (
<BookingFlowConfig config={config}>
<MapContainer>
<Suspense key={booking.hotelId} fallback={<SelectHotelMapSkeleton />}>
<SelectHotelMap
@@ -127,5 +130,6 @@ export async function AlternativeHotelsMapPage({
/>
</Suspense>
</MapContainer>
</BookingFlowConfig>
)
}

View File

@@ -7,7 +7,7 @@ import { FamilyAndFriendsCodes } from "@scandic-hotels/common/constants/familyAn
import { NoAvailabilityTracking } from "@scandic-hotels/tracking/NoAvailabilityTracking"
import { TrackingSDK } from "@scandic-hotels/tracking/TrackingSDK"
import { getBookingFlowConfig } from "../bookingFlowConfig/bookingFlowConfig"
import { BookingFlowConfig } from "../bookingFlowConfig/bookingFlowConfig"
import { AlternativeHotelsPageTitle } from "../components/AlternativeHotelsPageTitle"
import FnFNotAllowedAlert from "../components/FnFNotAllowedAlert"
import { SelectHotel } from "../components/SelectHotel"
@@ -25,9 +25,11 @@ export { SelectHotelSkeleton as AlternativeHotelsPageSkeleton } from "../compone
export async function AlternativeHotelsPage({
lang,
searchParams,
config,
}: {
lang: Lang
searchParams: NextSearchParams
config: BookingFlowConfig
}) {
const booking = parseSelectHotelSearchParams(searchParams)
@@ -108,7 +110,7 @@ export async function AlternativeHotelsPage({
isBookingCodeRateAvailable,
isRedemption: searchDetails.redemption,
isRedemptionAvailable: isRedemptionAvailability,
config: getBookingFlowConfig(),
config,
})
const suspenseKey = stringify(searchParams)
@@ -118,7 +120,7 @@ export async function AlternativeHotelsPage({
(booking.bookingCode && hotels.length > 0 && !isBookingCodeRateAvailable)
)
return (
<>
<BookingFlowConfig config={config}>
<SelectHotel
bookingCode={booking.bookingCode}
city={searchDetails.city}
@@ -142,6 +144,6 @@ export async function AlternativeHotelsPage({
shouldTrackNoAvailability={shouldTrackNoAvailability}
/>
</Suspense>
</>
</BookingFlowConfig>
)
}

View File

@@ -3,6 +3,7 @@ import { notFound, redirect } from "next/navigation"
import { decrypt } from "@scandic-hotels/trpc/utils/encryption"
import { BookingFlowConfig } from "../bookingFlowConfig/bookingFlowConfig"
import { BookingConfirmation } from "../components/BookingConfirmation"
import { getBookingConfirmation } from "../trpc/memoizedRequests/getBookingConfirmation"
import { MEMBERSHIP_FAILED_ERROR } from "../types/membershipFailedError"
@@ -16,10 +17,12 @@ export async function BookingConfirmationPage({
intl,
lang,
searchParams,
config,
}: {
intl: IntlShape
lang: Lang
searchParams: NextSearchParams
config: BookingFlowConfig
}) {
const refId = searchParams.RefId?.toString()
@@ -46,10 +49,12 @@ export async function BookingConfirmationPage({
searchParams.errorCode === MEMBERSHIP_FAILED_ERROR
return (
<BookingFlowConfig config={config}>
<BookingConfirmation
intl={intl}
refId={refId}
membershipFailedError={membershipFailedError}
/>
</BookingFlowConfig>
)
}

View File

@@ -4,6 +4,7 @@ import { Suspense } from "react"
import { FamilyAndFriendsCodes } from "@scandic-hotels/common/constants/familyAndFriends"
import { BookingFlowConfig } from "../bookingFlowConfig/bookingFlowConfig"
import HotelHeader from "../components/EnterDetails/Header"
import Payment from "../components/EnterDetails/Payment"
import Multiroom from "../components/EnterDetails/Room/Multiroom"
@@ -29,9 +30,11 @@ import type { NextSearchParams } from "../types"
export async function EnterDetailsPage({
lang,
searchParams,
config,
}: {
lang: Lang
searchParams: NextSearchParams
config: BookingFlowConfig
}) {
const selectRoomParams = new URLSearchParams(
searchParams as Record<string, string>
@@ -116,6 +119,7 @@ export async function EnterDetailsPage({
// beneath footer to be able to show entire footer upon
// scrolling down to the bottom of the page
return (
<BookingFlowConfig config={config}>
<main data-footer-spacing>
<EnterDetailsProvider
booking={booking}
@@ -164,5 +168,6 @@ export async function EnterDetailsPage({
/>
</EnterDetailsProvider>
</main>
</BookingFlowConfig>
)
}

View File

@@ -11,6 +11,7 @@ import { BookingErrorCodeEnum } from "@scandic-hotels/trpc/enums/bookingErrorCod
import { getBooking } from "@scandic-hotels/trpc/routers/booking/utils"
import { encrypt } from "@scandic-hotels/trpc/utils/encryption"
import { BookingFlowConfig } from "../bookingFlowConfig/bookingFlowConfig"
import { HandleErrorCallback } from "../components/EnterDetails/Payment/PaymentCallback/HandleErrorCallback"
import { HandleSuccessCallback } from "../components/EnterDetails/Payment/PaymentCallback/HandleSuccessCallback"
import { serverClient } from "../trpc"
@@ -24,12 +25,14 @@ type PaymentCallbackPageProps = {
searchParams: NextSearchParams
userAccessToken: string | null
status: PaymentCallbackStatusEnum
config: BookingFlowConfig
}
export async function PaymentCallbackPage({
lang,
userAccessToken,
searchParams,
status,
config,
}: PaymentCallbackPageProps) {
const { confirmationNumber } = searchParams
@@ -51,12 +54,14 @@ export async function PaymentCallbackPage({
if (status === PaymentCallbackStatusEnum.Cancel) {
searchObject.set("errorCode", BookingErrorCodeEnum.TransactionCancelled)
return (
<BookingFlowConfig config={config}>
<HandleErrorCallback
returnUrl={returnUrl.toString()}
searchObject={searchObject}
status={status}
errorMessage={errorMessage}
/>
</BookingFlowConfig>
)
}
@@ -92,12 +97,14 @@ export async function PaymentCallbackPage({
)
return (
<BookingFlowConfig config={config}>
<HandleSuccessCallback
refId={refId}
sig={sig}
successRedirectUrl={confirmationUrl}
cardType={booking.guaranteeInfo?.cardType}
/>
</BookingFlowConfig>
)
}
@@ -141,11 +148,13 @@ export async function PaymentCallbackPage({
}
return (
<BookingFlowConfig config={config}>
<HandleErrorCallback
returnUrl={returnUrl.toString()}
searchObject={searchObject}
status={status}
errorMessage={errorMessage}
/>
</BookingFlowConfig>
)
}

View File

@@ -6,7 +6,7 @@ import { safeTry } from "@scandic-hotels/common/utils/safeTry"
import { TrackingSDK } from "@scandic-hotels/tracking/TrackingSDK"
import { env } from "../../env/server"
import { getBookingFlowConfig } from "../bookingFlowConfig/bookingFlowConfig"
import { BookingFlowConfig } from "../bookingFlowConfig/bookingFlowConfig"
import { MapContainer } from "../components/MapContainer"
import {
getFiltersFromHotels,
@@ -28,9 +28,11 @@ import type { NextSearchParams } from "../types"
export async function SelectHotelMapPage({
lang,
searchParams,
config,
}: {
lang: Lang
searchParams: NextSearchParams
config: BookingFlowConfig
}) {
const googleMapId = env.GOOGLE_DYNAMIC_MAP_ID
const googleMapsApiKey = env.GOOGLE_STATIC_MAP_KEY
@@ -104,7 +106,7 @@ export async function SelectHotelMapPage({
isBookingCodeRateAvailable,
isRedemption: redemption,
isRedemptionAvailable: isRedemptionAvailability,
config: getBookingFlowConfig(),
config,
})
const filterList = getFiltersFromHotels(hotels, isBookingCodeRateAvailable)
@@ -112,6 +114,7 @@ export async function SelectHotelMapPage({
const suspenseKey = stringify(searchParams)
return (
<BookingFlowConfig config={config}>
<MapContainer>
<Suspense key={suspenseKey} fallback={<SelectHotelMapSkeleton />}>
<SelectHotelMap
@@ -129,5 +132,6 @@ export async function SelectHotelMapPage({
/>
</Suspense>
</MapContainer>
</BookingFlowConfig>
)
}

View File

@@ -7,7 +7,7 @@ import { FamilyAndFriendsCodes } from "@scandic-hotels/common/constants/familyAn
import { NoAvailabilityTracking } from "@scandic-hotels/tracking/NoAvailabilityTracking"
import { TrackingSDK } from "@scandic-hotels/tracking/TrackingSDK"
import { getBookingFlowConfig } from "../bookingFlowConfig/bookingFlowConfig"
import { BookingFlowConfig } from "../bookingFlowConfig/bookingFlowConfig"
import FnFNotAllowedAlert from "../components/FnFNotAllowedAlert"
import { SelectHotel } from "../components/SelectHotel"
import { getHotels } from "../components/SelectHotel/helpers"
@@ -24,9 +24,11 @@ export { SelectHotelSkeleton as SelectHotelPageSkeleton } from "../components/Se
export async function SelectHotelPage({
lang,
searchParams,
config,
}: {
lang: Lang
searchParams: NextSearchParams
config: BookingFlowConfig
}) {
const booking = parseSelectHotelSearchParams(searchParams)
@@ -94,7 +96,7 @@ export async function SelectHotelPage({
isBookingCodeRateAvailable,
isRedemption: redemption,
isRedemptionAvailable: isRedemptionAvailability,
config: getBookingFlowConfig(),
config,
})
const suspenseKey = stringify(searchParams)
@@ -105,7 +107,7 @@ export async function SelectHotelPage({
)
return (
<>
<BookingFlowConfig config={config}>
<SelectHotel
bookingCode={booking.bookingCode}
isBookingCodeRateAvailable={isBookingCodeRateAvailable}
@@ -126,6 +128,6 @@ export async function SelectHotelPage({
shouldTrackNoAvailability={shouldTrackNoAvailability}
/>
</Suspense>
</>
</BookingFlowConfig>
)
}

View File

@@ -3,6 +3,7 @@ import { notFound } from "next/navigation"
import { logger } from "@scandic-hotels/common/logger"
import { SEARCH_TYPE_REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
import { BookingFlowConfig } from "../bookingFlowConfig/bookingFlowConfig"
import { SelectRate } from "../components/SelectRate"
import { SelectRateTracking } from "../components/SelectRate/Tracking/SelectRateTracking"
import { SelectRateProvider } from "../contexts/SelectRate/SelectRateContext"
@@ -28,9 +29,11 @@ const singleRoomRateTypes = combineRegExps(
export async function SelectRatePage({
lang,
searchParams,
config,
}: {
lang: Lang
searchParams: NextSearchParams
config: BookingFlowConfig
}) {
const booking = parseSelectRateSearchParams(searchParams)
@@ -71,12 +74,12 @@ export async function SelectRatePage({
}
return (
<>
<BookingFlowConfig config={config}>
<SelectRateProvider hotelData={hotelData}>
<SelectRate hotelData={hotelData} booking={booking} />
<SelectRateTracking hotelData={hotelData} booking={booking} />
</SelectRateProvider>
</>
</BookingFlowConfig>
)
}

View File

@@ -11,10 +11,7 @@ export async function getUserPointsBalance(
const verifiedUser =
session.token.loginType === "eurobonus"
? await getEuroBonusProfileData({
accessToken: session.token.access_token,
loginType: session.token.loginType,
})
? await getEuroBonusProfileSafely(session)
: await getVerifiedUser({ session })
if (!verifiedUser || "error" in verifiedUser) {
@@ -28,3 +25,14 @@ export async function getUserPointsBalance(
return points ?? 0
}
async function getEuroBonusProfileSafely(session: Session) {
try {
return await getEuroBonusProfileData({
accessToken: session.token.access_token,
loginType: session.token.loginType,
})
} catch (_error) {
return undefined
}
}