Merged in feature/select-rate-vertical-data-flow (pull request #2535)

Feature/select rate vertical data flow

* add fix from SW-2666

* use translations for room packages

* move types to it's own file

* Merge branch 'master' of bitbucket.org:scandic-swap/web into feature/select-rate-vertical-data-flow

* merge

* feature/select-rate: double rate for campaing rates

* revert NODE_ENV check in Cookiebot script

* revert testing values

* fix(SW-3171): fix all filter selected in price details

* fix(SW-3166): multiroom anchoring when changing filter

* fix(SW-3172): check hotelType, show correct breakfast message

* Merge branch 'feature/select-rate-vertical-data-flow' of bitbucket.org:scandic-swap/web into feature/select-rate-vertical-data-flow

* fix: show special needs icons for subsequent roomTypes SW-3167

* fix: Display strike through text when logged in SW-3168

* fix: Reinstate the scrollToView behaviour when selecting a rate SW-3169

* merge

* .

* PR fixes

* fix: don't return notFound()

* .

* always include defaults for room packages

* merge

* merge

* merge

* Remove floating h1 for new select-rate


Approved-by: Anton Gunnarsson
This commit is contained in:
Joakim Jäderberg
2025-08-13 12:45:40 +00:00
parent 706f2d8dfe
commit 68cd061c6d
126 changed files with 8751 additions and 315 deletions

View File

@@ -41,8 +41,8 @@ export default async function DetailsPage(
if (!booking) return notFound()
if (selectRoomParams.has("modifyRateIndex")) {
selectRoomParams.delete("modifyRateIndex")
if (selectRoomParams.has("activeRoomIndex")) {
selectRoomParams.delete("activeRoomIndex")
}
if (

View File

@@ -0,0 +1,16 @@
import { HotelInfoCardSkeleton } from "@/components/HotelReservation/SelectRate/HotelInfoCard"
import { RoomsContainerSkeleton } from "@/components/HotelReservation/SelectRate/RoomsContainer/RoomsContainerSkeleton"
// Select Rate loading doesn't need a layout and wrapper
// to force loading.tsx to show again since refetch of
// availability happens client-side and only the RoomCards
// display a loading state since we already have the hotel
// data
export default function LoadingSelectRate() {
return (
<>
<HotelInfoCardSkeleton />
<RoomsContainerSkeleton />
</>
)
}

View File

@@ -0,0 +1,43 @@
import { notFound } from "next/navigation"
import { parseSelectRateSearchParams } from "@scandic-hotels/booking-flow/utils/url"
import { SEARCH_TYPE_REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
import { combineRegExps, rateTypeRegex } from "@/constants/booking"
import SelectRate from "@/components/HotelReservation/SelectRate"
import type { LangParams, NextSearchParams, PageArgs } from "@/types/params"
const singleRoomRateTypes = combineRegExps(
[rateTypeRegex.ARB, rateTypeRegex.VOUCHER],
"i"
)
export default async function SelectRatePage(
props: PageArgs<LangParams & { section: string }, NextSearchParams>
) {
const params = await props.params
const searchParams = await props.searchParams
const booking = parseSelectRateSearchParams(searchParams)
if (!booking) return notFound()
const isMultiRoom = booking.rooms.length > 1
const isRedemption = booking.searchType === SEARCH_TYPE_REDEMPTION
const isArbOrVoucher = booking.bookingCode
? singleRoomRateTypes.test(booking.bookingCode)
: false
if ((isMultiRoom && isRedemption) || (isMultiRoom && isArbOrVoucher)) {
return notFound()
}
// If someone tries to update the url with
// a bookingCode also, then we need to remove it
if (isRedemption && searchParams.bookingCode) {
delete searchParams.bookingCode
}
return <SelectRate lang={params.lang} booking={booking} />
}

View File

@@ -1,11 +1,14 @@
import { notFound } from "next/navigation"
import { parseSelectRateSearchParams } from "@scandic-hotels/booking-flow/utils/url"
import { logger } from "@scandic-hotels/common/logger"
import { SEARCH_TYPE_REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
import { combineRegExps, rateTypeRegex } from "@/constants/booking"
import { getHotel } from "@/lib/trpc/memoizedRequests"
import SelectRate from "@/components/HotelReservation/SelectRate"
import SelectRate from "@/components/HotelReservation/SelectRate2"
import { SelectRateProvider } from "@/contexts/SelectRate/SelectRateContext"
import type { LangParams, NextSearchParams, PageArgs } from "@/types/params"
@@ -21,7 +24,10 @@ export default async function SelectRatePage(
const searchParams = await props.searchParams
const booking = parseSelectRateSearchParams(searchParams)
if (!booking) return notFound()
if (!booking) {
logger.debug("Invalid search params", searchParams)
notFound()
}
const isMultiRoom = booking.rooms.length > 1
const isRedemption = booking.searchType === SEARCH_TYPE_REDEMPTION
@@ -30,7 +36,11 @@ export default async function SelectRatePage(
: false
if ((isMultiRoom && isRedemption) || (isMultiRoom && isArbOrVoucher)) {
return notFound()
logger.debug(
"Invalid search params, can't have multiroom and redemption/voucher",
{ isMultiRoom, isRedemption, isArbOrVoucher }
)
notFound()
}
// If someone tries to update the url with
@@ -39,5 +49,20 @@ export default async function SelectRatePage(
delete searchParams.bookingCode
}
return <SelectRate lang={params.lang} booking={booking} />
const hotelData = await getHotel({
hotelId: booking.hotelId,
isCardOnlyPayment: false,
language: params.lang,
})
if (!hotelData) {
logger.debug("Unable to find hotel data")
notFound()
}
return (
<SelectRateProvider hotelData={hotelData}>
<SelectRate hotelData={hotelData} booking={booking} />
</SelectRateProvider>
)
}

View File

@@ -6,6 +6,7 @@ import "@scandic-hotels/design-system/style.css"
import { ReactQueryDevtools } from "@tanstack/react-query-devtools"
import Script from "next/script"
import { SessionProvider } from "next-auth/react"
import { NuqsAdapter } from "nuqs/adapters/next/app"
import { BookingFlowTrackingProvider } from "@scandic-hotels/booking-flow/BookingFlowTrackingProvider"
import { Lang } from "@scandic-hotels/common/constants/language"
@@ -65,27 +66,29 @@ export default async function RootLayout(
locale={params.lang}
messages={messages}
>
<TrpcProvider>
<RACRouterProvider>
<BookingFlowTrackingProvider
trackingFunctions={{
trackBookingSearchClick,
}}
>
<RouteChange />
<SitewideAlert />
<Header />
{bookingwidget}
{children}
<Footer />
<ToastHandler />
<SessionRefresher />
<StorageCleaner />
<CookieBotConsent />
<ReactQueryDevtools initialIsOpen={false} />
</BookingFlowTrackingProvider>
</RACRouterProvider>
</TrpcProvider>
<NuqsAdapter>
<TrpcProvider>
<RACRouterProvider>
<BookingFlowTrackingProvider
trackingFunctions={{
trackBookingSearchClick,
}}
>
<RouteChange />
<SitewideAlert />
<Header />
{bookingwidget}
{children}
<Footer />
<ToastHandler />
<SessionRefresher />
<StorageCleaner />
<CookieBotConsent />
<ReactQueryDevtools initialIsOpen={false} />
</BookingFlowTrackingProvider>
</RACRouterProvider>
</TrpcProvider>
</NuqsAdapter>
</ClientIntlProvider>
</SessionProvider>
</div>

View File

@@ -6,6 +6,7 @@ import "@scandic-hotels/design-system/style.css"
import { ReactQueryDevtools } from "@tanstack/react-query-devtools"
import Script from "next/script"
import { SessionProvider } from "next-auth/react"
import { NuqsAdapter } from "nuqs/adapters/next/app"
import { Lang } from "@scandic-hotels/common/constants/language"
@@ -52,15 +53,17 @@ export default async function RootLayout(
locale={params.lang}
messages={messages}
>
<TrpcProvider>
<RouteChange />
{children}
<ToastHandler />
<SessionRefresher />
<StorageCleaner />
<CookieBotConsent />
<ReactQueryDevtools initialIsOpen={false} />
</TrpcProvider>
<NuqsAdapter>
<TrpcProvider>
<RouteChange />
{children}
<ToastHandler />
<SessionRefresher />
<StorageCleaner />
<CookieBotConsent />
<ReactQueryDevtools initialIsOpen={false} />
</TrpcProvider>
</NuqsAdapter>
</ClientIntlProvider>
</SessionProvider>
@@ -71,6 +74,7 @@ export default async function RootLayout(
data-culture={params.lang}
id="Cookiebot"
src="https://consent.cookiebot.com/uc.js"
async={true}
/>
</body>
</html>

View File

@@ -5,6 +5,7 @@ import "@scandic-hotels/design-system/style.css"
import { ReactQueryDevtools } from "@tanstack/react-query-devtools"
import Script from "next/script"
import { NuqsAdapter } from "nuqs/adapters/next/app"
import { Lang } from "@scandic-hotels/common/constants/language"
@@ -52,15 +53,17 @@ export default async function RootLayout(
locale={params.lang}
messages={messages}
>
<TrpcProvider>
<RouteChange />
{children}
<ToastHandler />
<TokenRefresher />
<StorageCleaner />
<CookieBotConsent />
<ReactQueryDevtools initialIsOpen={false} />
</TrpcProvider>
<NuqsAdapter>
<TrpcProvider>
<RouteChange />
{children}
<ToastHandler />
<TokenRefresher />
<StorageCleaner />
<CookieBotConsent />
<ReactQueryDevtools initialIsOpen={false} />
</TrpcProvider>
</NuqsAdapter>
</ClientIntlProvider>
<Script

View File

@@ -4,6 +4,7 @@ import "@/public/_static/css/design-system-new-deprecated.css"
import "@scandic-hotels/design-system/style.css"
import Script from "next/script"
import { NuqsAdapter } from "nuqs/adapters/next/app"
import { Lang } from "@scandic-hotels/common/constants/language"
@@ -56,11 +57,13 @@ export default async function RootLayout(
locale={params.lang}
messages={messages}
>
<TrpcProvider>
<RouteChange />
{children}
<ToastHandler />
</TrpcProvider>
<NuqsAdapter>
<TrpcProvider>
<RouteChange />
{children}
<ToastHandler />
</TrpcProvider>
</NuqsAdapter>
</ClientIntlProvider>
</body>
</html>