Merged in feat/sw-2874-move-select-rate (pull request #2750)
Approved-by: Joakim Jäderberg
This commit is contained in:
@@ -1,4 +1,24 @@
|
|||||||
export default async function SelectRatePage() {
|
import { SelectRatePage as SelectRatePagePrimitive } from "@scandic-hotels/booking-flow/pages/SelectRatePage"
|
||||||
// eslint-disable-next-line formatjs/no-literal-string-in-jsx
|
|
||||||
return <div>select-rate</div>
|
import TrackingSDK from "@/components/TrackingSDK"
|
||||||
|
import { getLang } from "@/i18n/serverContext"
|
||||||
|
|
||||||
|
import { type LangParams, type PageArgs } from "@/types/params"
|
||||||
|
|
||||||
|
export default async function SelectRatePage(props: PageArgs<LangParams>) {
|
||||||
|
const searchParams = await props.searchParams
|
||||||
|
const lang = await getLang()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SelectRatePagePrimitive
|
||||||
|
lang={lang}
|
||||||
|
searchParams={searchParams}
|
||||||
|
renderTracking={(props) => (
|
||||||
|
<TrackingSDK
|
||||||
|
hotelInfo={props.hotelsTrackingData}
|
||||||
|
pageData={props.pageTrackingData}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import "../../globals.css"
|
|||||||
|
|
||||||
import { BookingFlowContextProvider } from "@scandic-hotels/booking-flow/BookingFlowContextProvider"
|
import { BookingFlowContextProvider } from "@scandic-hotels/booking-flow/BookingFlowContextProvider"
|
||||||
import { BookingFlowTrackingProvider } from "@scandic-hotels/booking-flow/BookingFlowTrackingProvider"
|
import { BookingFlowTrackingProvider } from "@scandic-hotels/booking-flow/BookingFlowTrackingProvider"
|
||||||
|
import { NuqsAdapter } from "@scandic-hotels/booking-flow/utils/nuqs"
|
||||||
import { Lang } from "@scandic-hotels/common/constants/language"
|
import { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
import { TrpcProvider } from "@scandic-hotels/trpc/Provider"
|
import { TrpcProvider } from "@scandic-hotels/trpc/Provider"
|
||||||
|
|
||||||
@@ -62,6 +63,7 @@ export default async function RootLayout(props: RootLayoutProps) {
|
|||||||
locale={lang}
|
locale={lang}
|
||||||
messages={messages}
|
messages={messages}
|
||||||
>
|
>
|
||||||
|
<NuqsAdapter>
|
||||||
{/* TODO handle onError */}
|
{/* TODO handle onError */}
|
||||||
<TrpcProvider>
|
<TrpcProvider>
|
||||||
<BookingFlowContextProvider
|
<BookingFlowContextProvider
|
||||||
@@ -96,6 +98,7 @@ export default async function RootLayout(props: RootLayoutProps) {
|
|||||||
</BookingFlowTrackingProvider>
|
</BookingFlowTrackingProvider>
|
||||||
</BookingFlowContextProvider>
|
</BookingFlowContextProvider>
|
||||||
</TrpcProvider>
|
</TrpcProvider>
|
||||||
|
</NuqsAdapter>
|
||||||
</ClientIntlProvider>
|
</ClientIntlProvider>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// import { BedTypeEnum } from "@/constants/booking"
|
// import { BedTypeEnum } from "@/constants/booking"
|
||||||
|
|
||||||
// import { ChildBedMapEnum } from "@/types/components/bookingWidget/enums"
|
// import { ChildBedMapEnum } from "@/types/components/bookingWidget/enums"
|
||||||
// import type { BreakfastPackage } from "@/types/components/hotelReservation/breakfast"
|
// import type { BreakfastPackage } from "@scandic-hotels/trpc/routers/hotels/schemas/packages"
|
||||||
// import type { BedTypeSelection } from "@/types/components/hotelReservation/enterDetails/bedType"
|
// import type { BedTypeSelection } from "@/types/components/hotelReservation/enterDetails/bedType"
|
||||||
// import type {
|
// import type {
|
||||||
// DetailsSchema,
|
// DetailsSchema,
|
||||||
|
|||||||
@@ -1,12 +1,5 @@
|
|||||||
import { HotelInfoCardSkeleton } from "@scandic-hotels/design-system/HotelInfoCard"
|
import { SelectRateSkeleton } from "@scandic-hotels/booking-flow/components/SelectRate"
|
||||||
|
|
||||||
import { RoomsContainerSkeleton } from "@/components/HotelReservation/SelectRate/RoomsContainer/RoomsContainerSkeleton"
|
|
||||||
|
|
||||||
export default function LoadingSelectRate() {
|
export default function LoadingSelectRate() {
|
||||||
return (
|
return <SelectRateSkeleton />
|
||||||
<>
|
|
||||||
<HotelInfoCardSkeleton />
|
|
||||||
<RoomsContainerSkeleton />
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,68 +1,30 @@
|
|||||||
import { notFound } from "next/navigation"
|
import { SelectRatePage as SelectRatePagePrimitive } from "@scandic-hotels/booking-flow/pages/SelectRatePage"
|
||||||
|
|
||||||
import { SelectRateProvider } from "@scandic-hotels/booking-flow/contexts/SelectRate/SelectRateContext"
|
import TrackingSDK from "@/components/TrackingSDK"
|
||||||
import { parseSelectRateSearchParams } from "@scandic-hotels/booking-flow/utils/url"
|
import { getLang } from "@/i18n/serverContext"
|
||||||
import { logger } from "@scandic-hotels/common/logger"
|
|
||||||
import { SEARCH_TYPE_REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
|
|
||||||
|
|
||||||
import { combineRegExps, rateTypeRegex } from "@/constants/booking"
|
import {
|
||||||
import { getHotel } from "@/lib/trpc/memoizedRequests"
|
type LangParams,
|
||||||
|
type NextSearchParams,
|
||||||
import SelectRate from "@/components/HotelReservation/SelectRate"
|
type PageArgs,
|
||||||
|
} from "@/types/params"
|
||||||
import type { LangParams, NextSearchParams, PageArgs } from "@/types/params"
|
|
||||||
|
|
||||||
const singleRoomRateTypes = combineRegExps(
|
|
||||||
[rateTypeRegex.ARB, rateTypeRegex.VOUCHER],
|
|
||||||
"i"
|
|
||||||
)
|
|
||||||
|
|
||||||
export default async function SelectRatePage(
|
export default async function SelectRatePage(
|
||||||
props: PageArgs<LangParams & { section: string }, NextSearchParams>
|
props: PageArgs<LangParams, NextSearchParams>
|
||||||
) {
|
) {
|
||||||
const params = await props.params
|
|
||||||
const searchParams = await props.searchParams
|
const searchParams = await props.searchParams
|
||||||
const booking = parseSelectRateSearchParams(searchParams)
|
const lang = await getLang()
|
||||||
|
|
||||||
if (!booking) {
|
|
||||||
logger.debug("Invalid search params", searchParams)
|
|
||||||
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)) {
|
|
||||||
logger.debug(
|
|
||||||
"Invalid search params, can't have multiroom and redemption/voucher",
|
|
||||||
{ isMultiRoom, isRedemption, isArbOrVoucher }
|
|
||||||
)
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
const hotelData = await getHotel({
|
|
||||||
hotelId: booking.hotelId,
|
|
||||||
isCardOnlyPayment: false,
|
|
||||||
language: params.lang,
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!hotelData) {
|
|
||||||
logger.debug("Unable to find hotel data")
|
|
||||||
notFound()
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SelectRateProvider hotelData={hotelData}>
|
<SelectRatePagePrimitive
|
||||||
<SelectRate hotelData={hotelData} booking={booking} />
|
lang={lang}
|
||||||
</SelectRateProvider>
|
searchParams={searchParams}
|
||||||
|
renderTracking={(props) => (
|
||||||
|
<TrackingSDK
|
||||||
|
hotelInfo={props.hotelsTrackingData}
|
||||||
|
pageData={props.pageTrackingData}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import "@scandic-hotels/design-system/style.css"
|
|||||||
import { ReactQueryDevtools } from "@tanstack/react-query-devtools"
|
import { ReactQueryDevtools } from "@tanstack/react-query-devtools"
|
||||||
import Script from "next/script"
|
import Script from "next/script"
|
||||||
import { SessionProvider } from "next-auth/react"
|
import { SessionProvider } from "next-auth/react"
|
||||||
import { NuqsAdapter } from "nuqs/adapters/next/app"
|
|
||||||
|
|
||||||
|
import { NuqsAdapter } from "@scandic-hotels/booking-flow/utils/nuqs"
|
||||||
import { Lang } from "@scandic-hotels/common/constants/language"
|
import { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
import { ToastHandler } from "@scandic-hotels/design-system/ToastHandler"
|
import { ToastHandler } from "@scandic-hotels/design-system/ToastHandler"
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import "@scandic-hotels/design-system/style.css"
|
|||||||
import { ReactQueryDevtools } from "@tanstack/react-query-devtools"
|
import { ReactQueryDevtools } from "@tanstack/react-query-devtools"
|
||||||
import Script from "next/script"
|
import Script from "next/script"
|
||||||
import { SessionProvider } from "next-auth/react"
|
import { SessionProvider } from "next-auth/react"
|
||||||
import { NuqsAdapter } from "nuqs/adapters/next/app"
|
|
||||||
|
|
||||||
|
import { NuqsAdapter } from "@scandic-hotels/booking-flow/utils/nuqs"
|
||||||
import { Lang } from "@scandic-hotels/common/constants/language"
|
import { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
import { ToastHandler } from "@scandic-hotels/design-system/ToastHandler"
|
import { ToastHandler } from "@scandic-hotels/design-system/ToastHandler"
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import "@scandic-hotels/design-system/style.css"
|
|||||||
|
|
||||||
import { ReactQueryDevtools } from "@tanstack/react-query-devtools"
|
import { ReactQueryDevtools } from "@tanstack/react-query-devtools"
|
||||||
import Script from "next/script"
|
import Script from "next/script"
|
||||||
import { NuqsAdapter } from "nuqs/adapters/next/app"
|
|
||||||
|
|
||||||
|
import { NuqsAdapter } from "@scandic-hotels/booking-flow/utils/nuqs"
|
||||||
import { Lang } from "@scandic-hotels/common/constants/language"
|
import { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
import { ToastHandler } from "@scandic-hotels/design-system/ToastHandler"
|
import { ToastHandler } from "@scandic-hotels/design-system/ToastHandler"
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import "@scandic-hotels/design-system/style.css"
|
|||||||
import "@scandic-hotels/design-system/design-system-new-deprecated.css"
|
import "@scandic-hotels/design-system/design-system-new-deprecated.css"
|
||||||
|
|
||||||
import Script from "next/script"
|
import Script from "next/script"
|
||||||
import { NuqsAdapter } from "nuqs/adapters/next/app"
|
|
||||||
|
|
||||||
|
import { NuqsAdapter } from "@scandic-hotels/booking-flow/utils/nuqs"
|
||||||
import { Lang } from "@scandic-hotels/common/constants/language"
|
import { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
import { ToastHandler } from "@scandic-hotels/design-system/ToastHandler"
|
import { ToastHandler } from "@scandic-hotels/design-system/ToastHandler"
|
||||||
|
|
||||||
|
|||||||
@@ -46,8 +46,6 @@ export class ErrorBoundary extends React.Component<
|
|||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
||||||
return this.props.fallback
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.props.children
|
return this.props.children
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
import PriceDetailsModal from "@scandic-hotels/booking-flow/components/PriceDetailsModal"
|
||||||
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||||
import { dt } from "@scandic-hotels/common/dt"
|
import { dt } from "@scandic-hotels/common/dt"
|
||||||
|
|
||||||
import { useBookingConfirmationStore } from "@/stores/booking-confirmation"
|
import { useBookingConfirmationStore } from "@/stores/booking-confirmation"
|
||||||
|
|
||||||
import PriceDetailsModal from "@/components/HotelReservation/PriceDetailsModal"
|
|
||||||
|
|
||||||
import { mapToPrice } from "./mapToPrice"
|
import { mapToPrice } from "./mapToPrice"
|
||||||
|
|
||||||
import type { Price } from "@/types/components/hotelReservation/price"
|
import type { Price } from "@/types/components/hotelReservation/price"
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ import { BreakfastPackageEnum } from "@scandic-hotels/trpc/enums/breakfast"
|
|||||||
import { ChildBedMapEnum } from "@scandic-hotels/trpc/enums/childBedMapEnum"
|
import { ChildBedMapEnum } from "@scandic-hotels/trpc/enums/childBedMapEnum"
|
||||||
import { PackageTypeEnum } from "@scandic-hotels/trpc/enums/packages"
|
import { PackageTypeEnum } from "@scandic-hotels/trpc/enums/packages"
|
||||||
import {
|
import {
|
||||||
|
type BreakfastPackage,
|
||||||
breakfastPackageSchema,
|
breakfastPackageSchema,
|
||||||
packageSchema,
|
packageSchema,
|
||||||
} from "@scandic-hotels/trpc/routers/hotels/schemas/packages"
|
} from "@scandic-hotels/trpc/routers/hotels/schemas/packages"
|
||||||
|
|
||||||
import type { Package } from "@scandic-hotels/trpc/types/packages"
|
import type { Package } from "@scandic-hotels/trpc/types/packages"
|
||||||
|
|
||||||
import type { BreakfastPackage } from "@/types/components/hotelReservation/breakfast"
|
|
||||||
import type { Room } from "@/types/stores/booking-confirmation"
|
import type { Room } from "@/types/stores/booking-confirmation"
|
||||||
|
|
||||||
export function mapToPrice(rooms: (Room | null)[], nights: number) {
|
export function mapToPrice(rooms: (Room | null)[], nights: number) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import { RoomDetailsSidePeek } from "@scandic-hotels/booking-flow/components/RoomDetailsSidePeek"
|
||||||
import {
|
import {
|
||||||
changeOrCancelDateFormat,
|
changeOrCancelDateFormat,
|
||||||
longDateFormat,
|
longDateFormat,
|
||||||
@@ -16,7 +17,6 @@ import { getHotelRoom } from "@scandic-hotels/trpc/routers/booking/helpers"
|
|||||||
import { CancellationRuleEnum } from "@/constants/booking"
|
import { CancellationRuleEnum } from "@/constants/booking"
|
||||||
import { useBookingConfirmationStore } from "@/stores/booking-confirmation"
|
import { useBookingConfirmationStore } from "@/stores/booking-confirmation"
|
||||||
|
|
||||||
import RoomDetailsSidePeek from "@/components/SidePeeks/RoomDetailsSidePeek"
|
|
||||||
import useLang from "@/hooks/useLang"
|
import useLang from "@/hooks/useLang"
|
||||||
|
|
||||||
import styles from "./room.module.css"
|
import styles from "./room.module.css"
|
||||||
|
|||||||
@@ -1,12 +1,5 @@
|
|||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
export const bedTypeSchema = z.object({
|
|
||||||
bedType: z.object({
|
|
||||||
description: z.string(),
|
|
||||||
roomTypeCode: z.string(),
|
|
||||||
type: z.string(),
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
export const bedTypeFormSchema = z.object({
|
export const bedTypeFormSchema = z.object({
|
||||||
bedType: z.string(),
|
bedType: z.string(),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { useRouter } from "next/navigation"
|
|||||||
import { useTransition } from "react"
|
import { useTransition } from "react"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import { RoomDetailsSidePeek } from "@scandic-hotels/booking-flow/components/RoomDetailsSidePeek"
|
||||||
import { selectRate } from "@scandic-hotels/common/constants/routes/hotelReservation"
|
import { selectRate } from "@scandic-hotels/common/constants/routes/hotelReservation"
|
||||||
import { Button } from "@scandic-hotels/design-system/Button"
|
import { Button } from "@scandic-hotels/design-system/Button"
|
||||||
import Footnote from "@scandic-hotels/design-system/Footnote"
|
import Footnote from "@scandic-hotels/design-system/Footnote"
|
||||||
@@ -13,7 +14,6 @@ import { getHotelRoom } from "@scandic-hotels/trpc/routers/booking/helpers"
|
|||||||
|
|
||||||
import { useEnterDetailsStore } from "@/stores/enter-details"
|
import { useEnterDetailsStore } from "@/stores/enter-details"
|
||||||
|
|
||||||
import RoomDetailsSidePeek from "@/components/SidePeeks/RoomDetailsSidePeek"
|
|
||||||
import { useRoomContext } from "@/contexts/Details/Room"
|
import { useRoomContext } from "@/contexts/Details/Room"
|
||||||
import useLang from "@/hooks/useLang"
|
import useLang from "@/hooks/useLang"
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { type PropsWithChildren, useEffect, useRef } from "react"
|
|||||||
import { Button as ButtonRAC } from "react-aria-components"
|
import { Button as ButtonRAC } from "react-aria-components"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import { isBookingCodeRate } from "@scandic-hotels/booking-flow/components/SelectRate/RoomsContainer/RateSummary/utils"
|
||||||
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
|
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
|
||||||
import { Button } from "@scandic-hotels/design-system/Button"
|
import { Button } from "@scandic-hotels/design-system/Button"
|
||||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||||
@@ -14,7 +15,6 @@ import { Typography } from "@scandic-hotels/design-system/Typography"
|
|||||||
import { useEnterDetailsStore } from "@/stores/enter-details"
|
import { useEnterDetailsStore } from "@/stores/enter-details"
|
||||||
|
|
||||||
import { formId } from "@/components/HotelReservation/EnterDetails/Payment/PaymentClient"
|
import { formId } from "@/components/HotelReservation/EnterDetails/Payment/PaymentClient"
|
||||||
import { isBookingCodeRate } from "@/components/HotelReservation/SelectRate/RoomsContainer/RateSummary/utils"
|
|
||||||
|
|
||||||
import styles from "./bottomSheet.module.css"
|
import styles from "./bottomSheet.module.css"
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { useEnterDetailsStore } from "@/stores/enter-details"
|
import SignupPromoMobile from "@scandic-hotels/booking-flow/components/SignupPromoMobile"
|
||||||
|
|
||||||
import SignupPromoMobile from "@/components/HotelReservation/SignupPromo/Mobile"
|
import { useEnterDetailsStore } from "@/stores/enter-details"
|
||||||
|
|
||||||
import SummaryUI from "../UI"
|
import SummaryUI from "../UI"
|
||||||
import SummaryBottomSheet from "./BottomSheet"
|
import SummaryBottomSheet from "./BottomSheet"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { Typography } from "@scandic-hotels/design-system/Typography"
|
|||||||
|
|
||||||
import styles from "./breakfast.module.css"
|
import styles from "./breakfast.module.css"
|
||||||
|
|
||||||
import type { BreakfastPackage } from "@/types/components/hotelReservation/breakfast"
|
import type { BreakfastPackage } from "@scandic-hotels/trpc/routers/hotels/schemas/packages"
|
||||||
|
|
||||||
interface BreakfastProps {
|
interface BreakfastProps {
|
||||||
adults: number
|
adults: number
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ import { cx } from "class-variance-authority"
|
|||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
import { useMediaQuery } from "usehooks-ts"
|
import { useMediaQuery } from "usehooks-ts"
|
||||||
|
|
||||||
|
import PriceDetailsModal from "@scandic-hotels/booking-flow/components/PriceDetailsModal"
|
||||||
|
import { isBookingCodeRate } from "@scandic-hotels/booking-flow/components/SelectRate/RoomsContainer/RateSummary/utils"
|
||||||
|
import SignupPromoDesktop from "@scandic-hotels/booking-flow/components/SignupPromoDesktop"
|
||||||
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||||
import { longDateFormat } from "@scandic-hotels/common/constants/dateFormats"
|
import { longDateFormat } from "@scandic-hotels/common/constants/dateFormats"
|
||||||
import { dt } from "@scandic-hotels/common/dt"
|
import { dt } from "@scandic-hotels/common/dt"
|
||||||
@@ -15,9 +18,6 @@ import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
|||||||
import Subtitle from "@scandic-hotels/design-system/Subtitle"
|
import Subtitle from "@scandic-hotels/design-system/Subtitle"
|
||||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
|
|
||||||
import PriceDetailsModal from "@/components/HotelReservation/PriceDetailsModal"
|
|
||||||
import { isBookingCodeRate } from "@/components/HotelReservation/SelectRate/RoomsContainer/RateSummary/utils"
|
|
||||||
import SignupPromoDesktop from "@/components/HotelReservation/SignupPromo/Desktop"
|
|
||||||
import useLang from "@/hooks/useLang"
|
import useLang from "@/hooks/useLang"
|
||||||
|
|
||||||
import { mapToPrice } from "./mapToPrice"
|
import { mapToPrice } from "./mapToPrice"
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
|
|||||||
import { getSpecialRoomType } from "@/utils/specialRoomType"
|
import { getSpecialRoomType } from "@/utils/specialRoomType"
|
||||||
|
|
||||||
import type { Lang } from "@scandic-hotels/common/constants/language"
|
import type { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
|
import type { BreakfastPackages } from "@scandic-hotels/trpc/routers/hotels/output"
|
||||||
import type { Hotel } from "@scandic-hotels/trpc/types/hotel"
|
import type { Hotel } from "@scandic-hotels/trpc/types/hotel"
|
||||||
import type { Room } from "@scandic-hotels/trpc/types/room"
|
import type { Room } from "@scandic-hotels/trpc/types/room"
|
||||||
import type {
|
import type {
|
||||||
@@ -23,7 +24,6 @@ import type {
|
|||||||
Product,
|
Product,
|
||||||
} from "@scandic-hotels/trpc/types/roomAvailability"
|
} from "@scandic-hotels/trpc/types/roomAvailability"
|
||||||
|
|
||||||
import type { BreakfastPackages } from "@/types/components/hotelReservation/breakfast"
|
|
||||||
import type {
|
import type {
|
||||||
DetailsBooking,
|
DetailsBooking,
|
||||||
RoomRate,
|
RoomRate,
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
import PriceDetailsModal from "@scandic-hotels/booking-flow/components/PriceDetailsModal"
|
||||||
import { dt } from "@scandic-hotels/common/dt"
|
import { dt } from "@scandic-hotels/common/dt"
|
||||||
|
|
||||||
import { useMyStayStore } from "@/stores/my-stay"
|
import { useMyStayStore } from "@/stores/my-stay"
|
||||||
|
|
||||||
import PriceDetailsModal from "@/components/HotelReservation/PriceDetailsModal"
|
|
||||||
|
|
||||||
import { calculateTotalPrice, mapToPrice } from "./mapToPrice"
|
import { calculateTotalPrice, mapToPrice } from "./mapToPrice"
|
||||||
|
|
||||||
import styles from "./priceDetails.module.css"
|
import styles from "./priceDetails.module.css"
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ import { getPriceType } from "../../utils/getPriceType"
|
|||||||
import { formatChildBedPreferences } from "../utils"
|
import { formatChildBedPreferences } from "../utils"
|
||||||
|
|
||||||
import type { RateEnum } from "@scandic-hotels/common/constants/rate"
|
import type { RateEnum } from "@scandic-hotels/common/constants/rate"
|
||||||
|
import type { BreakfastPackage } from "@scandic-hotels/trpc/routers/hotels/schemas/packages"
|
||||||
import type { BookingConfirmation } from "@scandic-hotels/trpc/types/bookingConfirmation"
|
import type { BookingConfirmation } from "@scandic-hotels/trpc/types/bookingConfirmation"
|
||||||
import type { Room } from "@scandic-hotels/trpc/types/hotel"
|
import type { Room } from "@scandic-hotels/trpc/types/hotel"
|
||||||
|
|
||||||
import type { BreakfastPackage } from "@/types/components/hotelReservation/breakfast"
|
|
||||||
import type { Room as MyStayRoom } from "@/types/stores/my-stay"
|
import type { Room as MyStayRoom } from "@/types/stores/my-stay"
|
||||||
|
|
||||||
interface MapRoomDetailsParams {
|
interface MapRoomDetailsParams {
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
"use client"
|
|
||||||
import { useIntl } from "react-intl"
|
|
||||||
|
|
||||||
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
|
|
||||||
|
|
||||||
import { getFeatureDescription } from "@/components/HotelReservation/utils/getRoomFeatureDescription"
|
|
||||||
|
|
||||||
import RegularRow from "../Regular"
|
|
||||||
|
|
||||||
import type { Packages as PackagesType } from "@scandic-hotels/trpc/types/packages"
|
|
||||||
|
|
||||||
interface PackagesProps {
|
|
||||||
packages: PackagesType | null
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function PackagesRow({ packages }: PackagesProps) {
|
|
||||||
const intl = useIntl()
|
|
||||||
|
|
||||||
if (!packages || !packages.length) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return packages?.map((pkg) => (
|
|
||||||
<RegularRow
|
|
||||||
key={pkg.code}
|
|
||||||
label={getFeatureDescription(pkg.code, pkg.description, intl)}
|
|
||||||
value={formatPrice(
|
|
||||||
intl,
|
|
||||||
+pkg.localPrice.totalPrice,
|
|
||||||
pkg.localPrice.currency
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
import type {
|
|
||||||
Rate,
|
|
||||||
Room as SelectRateRoom,
|
|
||||||
} from "@scandic-hotels/booking-flow/types/components/selectRate/selectRate"
|
|
||||||
|
|
||||||
import type { Room } from "@/components/HotelReservation/PriceDetailsModal/PriceDetailsTable"
|
|
||||||
|
|
||||||
export function mapToPrice(
|
|
||||||
rooms: (Rate | null)[],
|
|
||||||
bookingRooms: SelectRateRoom[],
|
|
||||||
isUserLoggedIn: boolean
|
|
||||||
) {
|
|
||||||
return rooms
|
|
||||||
.map((room, idx) => {
|
|
||||||
if (!room) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
let price = null
|
|
||||||
if ("corporateCheque" in room.product) {
|
|
||||||
price = {
|
|
||||||
corporateCheque: room.product.corporateCheque.localPrice,
|
|
||||||
}
|
|
||||||
} else if ("redemption" in room.product) {
|
|
||||||
price = {
|
|
||||||
redemption: room.product.redemption.localPrice,
|
|
||||||
}
|
|
||||||
} else if ("voucher" in room.product) {
|
|
||||||
price = {
|
|
||||||
voucher: room.product.voucher,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const isMainRoom = idx === 0
|
|
||||||
const memberRate = room.product.member
|
|
||||||
const onlyMemberRate = !room.product.public && memberRate
|
|
||||||
if ((isUserLoggedIn && isMainRoom && memberRate) || onlyMemberRate) {
|
|
||||||
price = {
|
|
||||||
regular: {
|
|
||||||
...memberRate.localPrice,
|
|
||||||
regularPricePerStay:
|
|
||||||
room.product.public?.localPrice.pricePerStay ||
|
|
||||||
memberRate.localPrice.pricePerStay,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
} else if (room.product.public) {
|
|
||||||
price = {
|
|
||||||
regular: room.product.public.localPrice,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const bookingRoom = bookingRooms[idx]
|
|
||||||
return {
|
|
||||||
adults: bookingRoom.adults,
|
|
||||||
bedType: undefined,
|
|
||||||
breakfast: undefined,
|
|
||||||
breakfastIncluded: room.product.rateDefinition.breakfastIncluded,
|
|
||||||
childrenInRoom: bookingRoom.childrenInRoom,
|
|
||||||
packages: room.packages,
|
|
||||||
price,
|
|
||||||
roomType: room.roomType,
|
|
||||||
rateDefinition: room.product.rateDefinition,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.filter((r) => !!(r && r.price)) as Room[]
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import { useSearchParams } from "next/navigation"
|
|
||||||
import React from "react"
|
|
||||||
|
|
||||||
import {
|
|
||||||
parseSelectRateSearchParams,
|
|
||||||
searchParamsToRecord,
|
|
||||||
} from "@scandic-hotels/booking-flow/utils/url"
|
|
||||||
import { SEARCH_TYPE_REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
|
|
||||||
|
|
||||||
import TrackingSDK from "@/components/TrackingSDK"
|
|
||||||
import useLang from "@/hooks/useLang"
|
|
||||||
|
|
||||||
import { getValidDates } from "../getValidDates"
|
|
||||||
import { getSelectRateTracking } from "./tracking"
|
|
||||||
|
|
||||||
export default function Tracking({
|
|
||||||
hotelId,
|
|
||||||
hotelName,
|
|
||||||
country,
|
|
||||||
city,
|
|
||||||
}: {
|
|
||||||
hotelId: string
|
|
||||||
hotelName: string
|
|
||||||
country: string
|
|
||||||
city: string
|
|
||||||
}) {
|
|
||||||
const lang = useLang()
|
|
||||||
const params = useSearchParams()
|
|
||||||
const booking = parseSelectRateSearchParams(searchParamsToRecord(params))
|
|
||||||
|
|
||||||
if (!booking) return null
|
|
||||||
|
|
||||||
const { fromDate, toDate } = getValidDates(booking.fromDate, booking.toDate)
|
|
||||||
|
|
||||||
const { rooms, searchType, bookingCode, city: paramCity } = booking
|
|
||||||
|
|
||||||
const arrivalDate = fromDate.toDate()
|
|
||||||
const departureDate = toDate.toDate()
|
|
||||||
|
|
||||||
const { hotelsTrackingData, pageTrackingData } = getSelectRateTracking({
|
|
||||||
lang,
|
|
||||||
arrivalDate,
|
|
||||||
departureDate,
|
|
||||||
hotelId,
|
|
||||||
hotelName,
|
|
||||||
country,
|
|
||||||
hotelCity: city,
|
|
||||||
paramCity,
|
|
||||||
bookingCode,
|
|
||||||
isRedemption: searchType === SEARCH_TYPE_REDEMPTION,
|
|
||||||
rooms,
|
|
||||||
})
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TrackingSDK pageData={pageTrackingData} hotelInfo={hotelsTrackingData} />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -25,12 +25,12 @@ import RoomDetails from "./RoomDetails"
|
|||||||
|
|
||||||
import styles from "./bookedRoomSidePeek.module.css"
|
import styles from "./bookedRoomSidePeek.module.css"
|
||||||
|
|
||||||
|
import type { BreakfastPackage } from "@scandic-hotels/trpc/routers/hotels/schemas/packages"
|
||||||
import type { BookingConfirmationSchema } from "@scandic-hotels/trpc/types/bookingConfirmation"
|
import type { BookingConfirmationSchema } from "@scandic-hotels/trpc/types/bookingConfirmation"
|
||||||
import type { Child } from "@scandic-hotels/trpc/types/child"
|
import type { Child } from "@scandic-hotels/trpc/types/child"
|
||||||
import type { Room as HotelRoom } from "@scandic-hotels/trpc/types/hotel"
|
import type { Room as HotelRoom } from "@scandic-hotels/trpc/types/hotel"
|
||||||
import type { Packages } from "@scandic-hotels/trpc/types/packages"
|
import type { Packages } from "@scandic-hotels/trpc/types/packages"
|
||||||
|
|
||||||
import type { BreakfastPackage } from "@/types/components/hotelReservation/breakfast"
|
|
||||||
import type { BedTypeSchema } from "@/types/components/hotelReservation/enterDetails/bedType"
|
import type { BedTypeSchema } from "@/types/components/hotelReservation/enterDetails/bedType"
|
||||||
import type { PriceTypeEnum } from "@/types/components/hotelReservation/myStay/myStay"
|
import type { PriceTypeEnum } from "@/types/components/hotelReservation/myStay/myStay"
|
||||||
import type { SafeUser } from "@/types/user"
|
import type { SafeUser } from "@/types/user"
|
||||||
|
|||||||
@@ -65,12 +65,3 @@ export enum PaymentCallbackStatusEnum {
|
|||||||
Error = "error",
|
Error = "error",
|
||||||
Cancel = "cancel",
|
Cancel = "cancel",
|
||||||
}
|
}
|
||||||
|
|
||||||
export function combineRegExps(regexps: RegExp[], flags = "") {
|
|
||||||
return new RegExp(regexps.map((r) => r.source).join("|"), flags)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const rateTypeRegex = {
|
|
||||||
ARB: /(^B[a-z]{3}\d{6}$)/,
|
|
||||||
VOUCHER: /(^VO[0-9a-z]*$)/,
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ const nextConfig = {
|
|||||||
"@scandic-hotels/common",
|
"@scandic-hotels/common",
|
||||||
"@scandic-hotels/trpc",
|
"@scandic-hotels/trpc",
|
||||||
"@scandic-hotels/booking-flow",
|
"@scandic-hotels/booking-flow",
|
||||||
|
"@scandic-hotels/design-system",
|
||||||
],
|
],
|
||||||
experimental: {
|
experimental: {
|
||||||
serverActions: {
|
serverActions: {
|
||||||
|
|||||||
@@ -40,7 +40,10 @@
|
|||||||
"@opentelemetry/sdk-trace-base": "^1.29.0",
|
"@opentelemetry/sdk-trace-base": "^1.29.0",
|
||||||
"@radix-ui/react-slot": "^1.2.2",
|
"@radix-ui/react-slot": "^1.2.2",
|
||||||
"@react-aria/ssr": "^3.9.8",
|
"@react-aria/ssr": "^3.9.8",
|
||||||
|
"@scandic-hotels/booking-flow": "workspace:*",
|
||||||
|
"@scandic-hotels/common": "workspace:*",
|
||||||
"@scandic-hotels/design-system": "workspace:*",
|
"@scandic-hotels/design-system": "workspace:*",
|
||||||
|
"@scandic-hotels/trpc": "workspace:*",
|
||||||
"@sentry/nextjs": "^8.41.0",
|
"@sentry/nextjs": "^8.41.0",
|
||||||
"@swc/plugin-formatjs": "^3.2.2",
|
"@swc/plugin-formatjs": "^3.2.2",
|
||||||
"@t3-oss/env-nextjs": "^0.13.4",
|
"@t3-oss/env-nextjs": "^0.13.4",
|
||||||
@@ -79,9 +82,8 @@
|
|||||||
"md5": "^2.3.0",
|
"md5": "^2.3.0",
|
||||||
"motion": "^12.10.0",
|
"motion": "^12.10.0",
|
||||||
"nanoid": "^5.1.5",
|
"nanoid": "^5.1.5",
|
||||||
"next": "15.3.3",
|
"next": "15.3.4",
|
||||||
"next-auth": "5.0.0-beta.27",
|
"next-auth": "5.0.0-beta.27",
|
||||||
"nuqs": "^2.4.3",
|
|
||||||
"react": "19.1.0",
|
"react": "19.1.0",
|
||||||
"react-aria-components": "^1.8.0",
|
"react-aria-components": "^1.8.0",
|
||||||
"react-day-picker": "^9.6.7",
|
"react-day-picker": "^9.6.7",
|
||||||
@@ -105,7 +107,6 @@
|
|||||||
"@formatjs/cli": "^6.7.1",
|
"@formatjs/cli": "^6.7.1",
|
||||||
"@lokalise/node-api": "^14.0.0",
|
"@lokalise/node-api": "^14.0.0",
|
||||||
"@react-aria/test-utils": "1.0.0-alpha.8",
|
"@react-aria/test-utils": "1.0.0-alpha.8",
|
||||||
"@scandic-hotels/common": "workspace:*",
|
|
||||||
"@scandic-hotels/typescript-config": "workspace:*",
|
"@scandic-hotels/typescript-config": "workspace:*",
|
||||||
"@svgr/webpack": "^8.1.0",
|
"@svgr/webpack": "^8.1.0",
|
||||||
"@testing-library/react": "^16.3.0",
|
"@testing-library/react": "^16.3.0",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { logger } from "@scandic-hotels/common/logger"
|
|||||||
|
|
||||||
import { detailsStorageName } from "."
|
import { detailsStorageName } from "."
|
||||||
|
|
||||||
|
import type { BreakfastPackage } from "@scandic-hotels/trpc/routers/hotels/schemas/packages"
|
||||||
import type { Packages } from "@scandic-hotels/trpc/types/packages"
|
import type { Packages } from "@scandic-hotels/trpc/types/packages"
|
||||||
import type {
|
import type {
|
||||||
CorporateChequeProduct,
|
CorporateChequeProduct,
|
||||||
@@ -18,7 +19,6 @@ import type {
|
|||||||
VoucherProduct,
|
VoucherProduct,
|
||||||
} from "@scandic-hotels/trpc/types/roomAvailability"
|
} from "@scandic-hotels/trpc/types/roomAvailability"
|
||||||
|
|
||||||
import type { BreakfastPackage } from "@/types/components/hotelReservation/breakfast"
|
|
||||||
import { type RoomRate } from "@/types/components/hotelReservation/enterDetails/details"
|
import { type RoomRate } from "@/types/components/hotelReservation/enterDetails/details"
|
||||||
import type { Price } from "@/types/components/hotelReservation/price"
|
import type { Price } from "@/types/components/hotelReservation/price"
|
||||||
import type { PersistedState, RoomState } from "@/types/stores/enter-details"
|
import type { PersistedState, RoomState } from "@/types/stores/enter-details"
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ import {
|
|||||||
} from "./helpers"
|
} from "./helpers"
|
||||||
|
|
||||||
import type { Lang } from "@scandic-hotels/common/constants/language"
|
import type { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
|
import type { BreakfastPackages } from "@scandic-hotels/trpc/routers/hotels/output"
|
||||||
|
|
||||||
import type { BreakfastPackages } from "@/types/components/hotelReservation/breakfast"
|
|
||||||
import type { Price } from "@/types/components/hotelReservation/price"
|
import type { Price } from "@/types/components/hotelReservation/price"
|
||||||
import { StepEnum } from "@/types/enums/step"
|
import { StepEnum } from "@/types/enums/step"
|
||||||
import type {
|
import type {
|
||||||
|
|||||||
@@ -1,14 +1,6 @@
|
|||||||
import type { breakfastPackagesSchema } from "@scandic-hotels/trpc/routers/hotels/output"
|
|
||||||
import type { breakfastPackageSchema } from "@scandic-hotels/trpc/routers/hotels/schemas/packages"
|
|
||||||
import type { z } from "zod"
|
import type { z } from "zod"
|
||||||
|
|
||||||
import type { breakfastFormSchema } from "@/components/HotelReservation/EnterDetails/Breakfast/schema"
|
import type { breakfastFormSchema } from "@/components/HotelReservation/EnterDetails/Breakfast/schema"
|
||||||
|
|
||||||
export interface BreakfastFormSchema
|
export interface BreakfastFormSchema
|
||||||
extends z.output<typeof breakfastFormSchema> {}
|
extends z.output<typeof breakfastFormSchema> {}
|
||||||
|
|
||||||
export interface BreakfastPackages
|
|
||||||
extends z.output<typeof breakfastPackagesSchema> {}
|
|
||||||
|
|
||||||
export interface BreakfastPackage
|
|
||||||
extends z.output<typeof breakfastPackageSchema> {}
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import type { z } from "zod"
|
import type { z } from "zod"
|
||||||
|
|
||||||
import type {
|
import type { bedTypeFormSchema } from "@/components/HotelReservation/EnterDetails/BedType/schema"
|
||||||
bedTypeFormSchema,
|
|
||||||
bedTypeSchema,
|
|
||||||
} from "@/components/HotelReservation/EnterDetails/BedType/schema"
|
|
||||||
|
|
||||||
export interface BedTypeFormSchema extends z.output<typeof bedTypeFormSchema> {}
|
export interface BedTypeFormSchema extends z.output<typeof bedTypeFormSchema> {}
|
||||||
|
|
||||||
export type BedTypeSchema = z.output<typeof bedTypeSchema>["bedType"]
|
export type BedTypeSchema = {
|
||||||
|
description: string
|
||||||
|
type: string
|
||||||
|
roomTypeCode: string
|
||||||
|
}
|
||||||
export type BedTypeInfoProps = {
|
export type BedTypeInfoProps = {
|
||||||
hasMultipleBedTypes: boolean
|
hasMultipleBedTypes: boolean
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,12 +11,3 @@ export type RoomListItemImageProps = Pick<
|
|||||||
> & {
|
> & {
|
||||||
roomPackages: Package[]
|
roomPackages: Package[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RoomSizeProps {
|
|
||||||
roomSize:
|
|
||||||
| {
|
|
||||||
max: number
|
|
||||||
min: number
|
|
||||||
}
|
|
||||||
| undefined
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
import type { HotelData } from "@scandic-hotels/trpc/types/hotel"
|
|
||||||
|
|
||||||
export interface RoomsContainerProps
|
|
||||||
extends Pick<HotelData, "roomCategories">,
|
|
||||||
Pick<HotelData["hotel"], "hotelType" | "vat"> {}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
export interface SignupPromoProps {
|
|
||||||
memberPrice: {
|
|
||||||
amount: number
|
|
||||||
currency: string
|
|
||||||
}
|
|
||||||
badgeContent?: string
|
|
||||||
isEnterDetailsPage?: boolean
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import type { Lang } from "@scandic-hotels/common/constants/language"
|
import type { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
|
import type { BreakfastPackages } from "@scandic-hotels/trpc/routers/hotels/output"
|
||||||
import type { RoomCategories } from "@scandic-hotels/trpc/types/hotel"
|
import type { RoomCategories } from "@scandic-hotels/trpc/types/hotel"
|
||||||
import type { Room } from "@scandic-hotels/trpc/types/room"
|
import type { Room } from "@scandic-hotels/trpc/types/room"
|
||||||
|
|
||||||
import type { SafeUser } from "@/types/user"
|
import type { SafeUser } from "@/types/user"
|
||||||
import type { BreakfastPackages } from "../components/hotelReservation/breakfast"
|
|
||||||
import type { DetailsBooking } from "../components/hotelReservation/enterDetails/details"
|
import type { DetailsBooking } from "../components/hotelReservation/enterDetails/details"
|
||||||
|
|
||||||
export interface DetailsProviderProps extends React.PropsWithChildren {
|
export interface DetailsProviderProps extends React.PropsWithChildren {
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
import type { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
import type { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||||
|
import type { BreakfastPackages } from "@scandic-hotels/trpc/routers/hotels/output"
|
||||||
|
import type { BreakfastPackage } from "@scandic-hotels/trpc/routers/hotels/schemas/packages"
|
||||||
import type { BedTypeSelection } from "@scandic-hotels/trpc/types/bedTypeSelection"
|
import type { BedTypeSelection } from "@scandic-hotels/trpc/types/bedTypeSelection"
|
||||||
import type { Child } from "@scandic-hotels/trpc/types/child"
|
import type { Child } from "@scandic-hotels/trpc/types/child"
|
||||||
import type { RoomCategories } from "@scandic-hotels/trpc/types/hotel"
|
import type { RoomCategories } from "@scandic-hotels/trpc/types/hotel"
|
||||||
import type { Packages } from "@scandic-hotels/trpc/types/packages"
|
import type { Packages } from "@scandic-hotels/trpc/types/packages"
|
||||||
|
|
||||||
import type {
|
|
||||||
BreakfastPackage,
|
|
||||||
BreakfastPackages,
|
|
||||||
} from "@/types/components/hotelReservation/breakfast"
|
|
||||||
import type { BedTypeSchema } from "@/types/components/hotelReservation/enterDetails/bedType"
|
import type { BedTypeSchema } from "@/types/components/hotelReservation/enterDetails/bedType"
|
||||||
import type {
|
import type {
|
||||||
DetailsBooking,
|
DetailsBooking,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import type { BreakfastPackage } from "@scandic-hotels/trpc/routers/hotels/schemas/packages"
|
||||||
import type { BookingConfirmation } from "@scandic-hotels/trpc/types/bookingConfirmation"
|
import type { BookingConfirmation } from "@scandic-hotels/trpc/types/bookingConfirmation"
|
||||||
import type { Child } from "@scandic-hotels/trpc/types/child"
|
import type { Child } from "@scandic-hotels/trpc/types/child"
|
||||||
import type {
|
import type {
|
||||||
@@ -8,7 +9,6 @@ import type {
|
|||||||
import type { CreditCard } from "@scandic-hotels/trpc/types/user"
|
import type { CreditCard } from "@scandic-hotels/trpc/types/user"
|
||||||
import type { IntlShape } from "react-intl"
|
import type { IntlShape } from "react-intl"
|
||||||
|
|
||||||
import type { BreakfastPackage } from "@/types/components/hotelReservation/breakfast"
|
|
||||||
import type { BedTypeSchema } from "@/types/components/hotelReservation/enterDetails/bedType"
|
import type { BedTypeSchema } from "@/types/components/hotelReservation/enterDetails/bedType"
|
||||||
import type { RoomPrice } from "@/types/components/hotelReservation/enterDetails/details"
|
import type { RoomPrice } from "@/types/components/hotelReservation/enterDetails/details"
|
||||||
import type { PriceTypeEnum } from "@/types/components/hotelReservation/myStay/myStay"
|
import type { PriceTypeEnum } from "@/types/components/hotelReservation/myStay/myStay"
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
import { trackEvent } from "@scandic-hotels/common/tracking/base"
|
import { trackEvent } from "@scandic-hotels/common/tracking/base"
|
||||||
|
|
||||||
import type { BreakfastPackages } from "@/types/components/hotelReservation/breakfast"
|
|
||||||
import type { LowestRoomPriceEvent } from "@scandic-hotels/common/tracking/types"
|
import type { LowestRoomPriceEvent } from "@scandic-hotels/common/tracking/types"
|
||||||
|
import type { BreakfastPackages } from "@scandic-hotels/trpc/routers/hotels/output"
|
||||||
|
|
||||||
export function trackLowestRoomPrice(event: LowestRoomPriceEvent) {
|
export function trackLowestRoomPrice(event: LowestRoomPriceEvent) {
|
||||||
trackEvent({
|
trackEvent({
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import * as Sentry from "@sentry/nextjs"
|
||||||
|
import React from "react"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
|
type ErrorBoundaryProps = {
|
||||||
|
children: React.ReactNode
|
||||||
|
fallback?: React.ReactNode
|
||||||
|
}
|
||||||
|
type ErrorBoundaryState = { hasError: boolean; error?: Error }
|
||||||
|
|
||||||
|
export class ErrorBoundary extends React.Component<
|
||||||
|
ErrorBoundaryProps,
|
||||||
|
ErrorBoundaryState
|
||||||
|
> {
|
||||||
|
constructor(props: ErrorBoundaryProps) {
|
||||||
|
super(props)
|
||||||
|
this.state = { hasError: false }
|
||||||
|
}
|
||||||
|
|
||||||
|
static getDerivedStateFromError(error: Error) {
|
||||||
|
return { hasError: true, error }
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
|
||||||
|
logger.error("ErrorBoundary caught an error:", error, errorInfo)
|
||||||
|
Sentry.captureException(error, { extra: { errorInfo } })
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (this.state.hasError) {
|
||||||
|
const hasFallback = !!this.props.fallback
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{hasFallback && this.props.fallback}
|
||||||
|
{!hasFallback && <h2>Something went wrong.</h2>}
|
||||||
|
{process.env.NODE_ENV === "development" && (
|
||||||
|
<button onClick={() => this.setState({ hasError: false })}>
|
||||||
|
Reset
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.props.children
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@ import type {
|
|||||||
Hotel,
|
Hotel,
|
||||||
Restaurant,
|
Restaurant,
|
||||||
} from "@scandic-hotels/trpc/types/hotel"
|
} from "@scandic-hotels/trpc/types/hotel"
|
||||||
|
import type { ReactNode } from "react"
|
||||||
|
|
||||||
enum SidePeekEnum {
|
enum SidePeekEnum {
|
||||||
hotelDetails = "hotel-detail-side-peek",
|
hotelDetails = "hotel-detail-side-peek",
|
||||||
@@ -23,7 +24,7 @@ interface HotelDetailsSidePeekProps {
|
|||||||
hotel: Hotel & { url: string | null }
|
hotel: Hotel & { url: string | null }
|
||||||
restaurants: Restaurant[]
|
restaurants: Restaurant[]
|
||||||
additionalHotelData: AdditionalData | undefined
|
additionalHotelData: AdditionalData | undefined
|
||||||
triggerLabel: string
|
triggerLabel: ReactNode
|
||||||
buttonVariant: "primary" | "secondary"
|
buttonVariant: "primary" | "secondary"
|
||||||
wrapping?: boolean
|
wrapping?: boolean
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,9 @@ import BoldRow from "./Row/Bold"
|
|||||||
import RegularRow from "./Row/Regular"
|
import RegularRow from "./Row/Regular"
|
||||||
import Tbody from "./Tbody"
|
import Tbody from "./Tbody"
|
||||||
|
|
||||||
|
import type { BreakfastPackage } from "@scandic-hotels/trpc/routers/hotels/schemas/packages"
|
||||||
import type { Child } from "@scandic-hotels/trpc/types/child"
|
import type { Child } from "@scandic-hotels/trpc/types/child"
|
||||||
|
|
||||||
import type { BreakfastPackage } from "@/types/components/hotelReservation/breakfast"
|
|
||||||
|
|
||||||
interface BreakfastProps {
|
interface BreakfastProps {
|
||||||
adults: number
|
adults: number
|
||||||
breakfast: Omit<BreakfastPackage, "requestedPrice"> | false | undefined | null
|
breakfast: Omit<BreakfastPackage, "requestedPrice"> | false | undefined | null
|
||||||
@@ -6,7 +6,7 @@ import { Typography } from "@scandic-hotels/design-system/Typography"
|
|||||||
|
|
||||||
import styles from "./row.module.css"
|
import styles from "./row.module.css"
|
||||||
|
|
||||||
import type { Price } from "@/types/components/hotelReservation/price"
|
import type { Price } from "../../../../types/price"
|
||||||
|
|
||||||
interface RowProps {
|
interface RowProps {
|
||||||
allPricesIsDiscounted: boolean
|
allPricesIsDiscounted: boolean
|
||||||
@@ -5,10 +5,12 @@ import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
|
|||||||
|
|
||||||
import RegularRow from "../Regular"
|
import RegularRow from "../Regular"
|
||||||
|
|
||||||
import type { BedTypeSchema } from "@/types/components/hotelReservation/enterDetails/bedType"
|
|
||||||
|
|
||||||
interface BedTypeRowProps {
|
interface BedTypeRowProps {
|
||||||
bedType: BedTypeSchema | undefined
|
bedType:
|
||||||
|
| {
|
||||||
|
description: string
|
||||||
|
}
|
||||||
|
| undefined
|
||||||
currency?: string
|
currency?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
"use client"
|
||||||
|
import { type IntlShape, useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
|
||||||
|
import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
|
||||||
|
|
||||||
|
import RegularRow from "../Regular"
|
||||||
|
|
||||||
|
import type { Packages as PackagesType } from "@scandic-hotels/trpc/types/packages"
|
||||||
|
|
||||||
|
interface PackagesProps {
|
||||||
|
packages: PackagesType | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function PackagesRow({ packages }: PackagesProps) {
|
||||||
|
const intl = useIntl()
|
||||||
|
|
||||||
|
if (!packages || !packages.length) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return packages?.map((pkg) => (
|
||||||
|
<RegularRow
|
||||||
|
key={pkg.code}
|
||||||
|
label={getFeatureDescription(pkg.code, pkg.description, intl)}
|
||||||
|
value={formatPrice(
|
||||||
|
intl,
|
||||||
|
+pkg.localPrice.totalPrice,
|
||||||
|
pkg.localPrice.currency
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO this might be duplicated, check if we can reuse
|
||||||
|
function getFeatureDescription(
|
||||||
|
code: string,
|
||||||
|
description: string,
|
||||||
|
intl: IntlShape
|
||||||
|
): string {
|
||||||
|
const roomFeatureDescriptions: Record<string, string> = {
|
||||||
|
[RoomPackageCodeEnum.ACCESSIBILITY_ROOM]: intl.formatMessage({
|
||||||
|
defaultMessage: "Accessible room",
|
||||||
|
}),
|
||||||
|
[RoomPackageCodeEnum.ALLERGY_ROOM]: intl.formatMessage({
|
||||||
|
defaultMessage: "Allergy-friendly room",
|
||||||
|
}),
|
||||||
|
[RoomPackageCodeEnum.PET_ROOM]: intl.formatMessage({
|
||||||
|
defaultMessage: "Pet-friendly room",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
return roomFeatureDescriptions[code] ?? description
|
||||||
|
}
|
||||||
@@ -1,9 +1,13 @@
|
|||||||
import type { Packages } from "@scandic-hotels/trpc/types/packages"
|
import type { Packages } from "@scandic-hotels/trpc/types/packages"
|
||||||
|
|
||||||
import type { BedTypeSchema } from "@/types/components/hotelReservation/enterDetails/bedType"
|
|
||||||
|
|
||||||
export interface SharedPriceRowProps {
|
export interface SharedPriceRowProps {
|
||||||
bedType: BedTypeSchema | undefined
|
bedType:
|
||||||
|
| {
|
||||||
|
description: string
|
||||||
|
type: string
|
||||||
|
roomTypeCode: string
|
||||||
|
}
|
||||||
|
| undefined
|
||||||
nights: number
|
nights: number
|
||||||
packages: Packages | null
|
packages: Packages | null
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
"use client"
|
"use client"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { calculateVat } from "@scandic-hotels/booking-flow/utils/SelectRate"
|
|
||||||
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||||
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
|
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
|
||||||
|
|
||||||
|
import { calculateVat } from "../../../../utils/SelectRate"
|
||||||
import RegularRow from "./Regular"
|
import RegularRow from "./Regular"
|
||||||
|
|
||||||
import type { Price } from "@/types/components/hotelReservation/price"
|
import type { Price } from "../../../../types/price"
|
||||||
|
|
||||||
interface VatProps {
|
interface VatProps {
|
||||||
totalPrice: Price
|
totalPrice: Price
|
||||||
@@ -6,8 +6,7 @@ import { longDateFormat } from "@scandic-hotels/common/constants/dateFormats"
|
|||||||
import { dt } from "@scandic-hotels/common/dt"
|
import { dt } from "@scandic-hotels/common/dt"
|
||||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
|
|
||||||
import useLang from "@/hooks/useLang"
|
import useLang from "../../../hooks/useLang"
|
||||||
|
|
||||||
import BookingCodeRow from "./Row/BookingCode"
|
import BookingCodeRow from "./Row/BookingCode"
|
||||||
import HeaderRow from "./Row/Header"
|
import HeaderRow from "./Row/Header"
|
||||||
import LargeRow from "./Row/Large"
|
import LargeRow from "./Row/Large"
|
||||||
@@ -26,13 +25,12 @@ import Tbody from "./Tbody"
|
|||||||
import styles from "./priceDetailsTable.module.css"
|
import styles from "./priceDetailsTable.module.css"
|
||||||
|
|
||||||
import type { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
import type { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||||
|
import type { BreakfastPackage } from "@scandic-hotels/trpc/routers/hotels/schemas/packages"
|
||||||
import type { Child } from "@scandic-hotels/trpc/types/child"
|
import type { Child } from "@scandic-hotels/trpc/types/child"
|
||||||
import type { Packages } from "@scandic-hotels/trpc/types/packages"
|
import type { Packages } from "@scandic-hotels/trpc/types/packages"
|
||||||
import type { RateDefinition } from "@scandic-hotels/trpc/types/roomAvailability"
|
import type { RateDefinition } from "@scandic-hotels/trpc/types/roomAvailability"
|
||||||
|
|
||||||
import type { BreakfastPackage } from "@/types/components/hotelReservation/breakfast"
|
import type { Price } from "../../../types/price"
|
||||||
import type { BedTypeSchema } from "@/types/components/hotelReservation/enterDetails/bedType"
|
|
||||||
import type { Price } from "@/types/components/hotelReservation/price"
|
|
||||||
|
|
||||||
type RoomPrice =
|
type RoomPrice =
|
||||||
| CorporateChequePriceType
|
| CorporateChequePriceType
|
||||||
@@ -42,7 +40,13 @@ type RoomPrice =
|
|||||||
|
|
||||||
export interface Room {
|
export interface Room {
|
||||||
adults: number
|
adults: number
|
||||||
bedType: BedTypeSchema | undefined
|
bedType:
|
||||||
|
| {
|
||||||
|
description: string
|
||||||
|
type: string
|
||||||
|
roomTypeCode: string
|
||||||
|
}
|
||||||
|
| undefined
|
||||||
breakfast: Omit<BreakfastPackage, "requestedPrice"> | false | undefined | null
|
breakfast: Omit<BreakfastPackage, "requestedPrice"> | false | undefined | null
|
||||||
breakfastChildren?: Omit<BreakfastPackage, "requestedPrice"> | null
|
breakfastChildren?: Omit<BreakfastPackage, "requestedPrice"> | null
|
||||||
breakfastIncluded: boolean
|
breakfastIncluded: boolean
|
||||||
@@ -1,13 +1,11 @@
|
|||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import {
|
|
||||||
BED_TYPE_ICONS,
|
|
||||||
type BedTypes,
|
|
||||||
} from "@scandic-hotels/booking-flow/bedTypeIcons"
|
|
||||||
import { FacilityIcon } from "@scandic-hotels/design-system/Icons/FacilityIcon"
|
import { FacilityIcon } from "@scandic-hotels/design-system/Icons/FacilityIcon"
|
||||||
import ImageGallery from "@scandic-hotels/design-system/ImageGallery"
|
import ImageGallery from "@scandic-hotels/design-system/ImageGallery"
|
||||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
|
|
||||||
|
import { BED_TYPE_ICONS, type BedTypes } from "../../../misc/bedTypeIcons"
|
||||||
|
|
||||||
import styles from "./roomSidePeekContent.module.css"
|
import styles from "./roomSidePeekContent.module.css"
|
||||||
|
|
||||||
import type { ApiImage, Room } from "@scandic-hotels/trpc/types/hotel"
|
import type { ApiImage, Room } from "@scandic-hotels/trpc/types/hotel"
|
||||||
@@ -6,13 +6,14 @@ import { Button } from "@scandic-hotels/design-system/Button"
|
|||||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||||
import SidePeekSelfControlled from "@scandic-hotels/design-system/SidePeekSelfControlled"
|
import SidePeekSelfControlled from "@scandic-hotels/design-system/SidePeekSelfControlled"
|
||||||
|
|
||||||
import { trackOpenSidePeekEvent } from "@/utils/tracking"
|
import { useTrackingContext } from "../../trackingContext"
|
||||||
|
|
||||||
import { RoomSidePeekContent } from "./RoomSidePeekContent"
|
import { RoomSidePeekContent } from "./RoomSidePeekContent"
|
||||||
|
|
||||||
import type { Room } from "@scandic-hotels/trpc/types/hotel"
|
import type { Room } from "@scandic-hotels/trpc/types/hotel"
|
||||||
|
|
||||||
import { SidePeekEnum } from "@/types/sidepeek"
|
enum SidePeekEnum {
|
||||||
|
roomDetails = "room-detail-side-peek",
|
||||||
|
}
|
||||||
|
|
||||||
interface RoomDetailsSidePeekProps {
|
interface RoomDetailsSidePeekProps {
|
||||||
hotelId: string
|
hotelId: string
|
||||||
@@ -44,7 +45,7 @@ const buttonPropsMap: Record<
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function RoomDetailsSidePeek({
|
export function RoomDetailsSidePeek({
|
||||||
hotelId,
|
hotelId,
|
||||||
room,
|
room,
|
||||||
roomTypeCode,
|
roomTypeCode,
|
||||||
@@ -52,6 +53,7 @@ export default function RoomDetailsSidePeek({
|
|||||||
wrapping = true,
|
wrapping = true,
|
||||||
buttonVariant: variant = "primary",
|
buttonVariant: variant = "primary",
|
||||||
}: RoomDetailsSidePeekProps) {
|
}: RoomDetailsSidePeekProps) {
|
||||||
|
const tracking = useTrackingContext()
|
||||||
const buttonProps = buttonPropsMap[variant]
|
const buttonProps = buttonPropsMap[variant]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -60,7 +62,7 @@ export default function RoomDetailsSidePeek({
|
|||||||
{...buttonProps}
|
{...buttonProps}
|
||||||
wrapping={wrapping}
|
wrapping={wrapping}
|
||||||
onPress={() =>
|
onPress={() =>
|
||||||
trackOpenSidePeekEvent({
|
tracking.trackOpenSidePeek({
|
||||||
name: SidePeekEnum.roomDetails,
|
name: SidePeekEnum.roomDetails,
|
||||||
hotelId,
|
hotelId,
|
||||||
roomTypeCode,
|
roomTypeCode,
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
"use client"
|
||||||
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
export function AmenitiesSidePeekLabel() {
|
||||||
|
const intl = useIntl()
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{intl.formatMessage({
|
||||||
|
defaultMessage: "See all amenities",
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -8,15 +8,14 @@ import Footnote from "@scandic-hotels/design-system/Footnote"
|
|||||||
import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton"
|
import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton"
|
||||||
import Subtitle from "@scandic-hotels/design-system/Subtitle"
|
import Subtitle from "@scandic-hotels/design-system/Subtitle"
|
||||||
|
|
||||||
import SignupPromoDesktop from "@/components/HotelReservation/SignupPromo/Desktop"
|
import { useIsLoggedIn } from "../../../../hooks/useIsLoggedIn"
|
||||||
import { useIsUserLoggedIn } from "@/hooks/useIsUserLoggedIn"
|
import SignupPromoDesktop from "../../../SignupPromo/Desktop"
|
||||||
|
|
||||||
import { isBookingCodeRate } from "./utils"
|
import { isBookingCodeRate } from "./utils"
|
||||||
|
|
||||||
import styles from "./rateSummary.module.css"
|
import styles from "./rateSummary.module.css"
|
||||||
|
|
||||||
import type { useSelectRateContext } from "@scandic-hotels/booking-flow/contexts/SelectRate/SelectRateContext"
|
import type { useSelectRateContext } from "../../../../contexts/SelectRate/SelectRateContext"
|
||||||
import type { SelectedRate } from "@scandic-hotels/booking-flow/contexts/SelectRate/types"
|
import type { SelectedRate } from "../../../../contexts/SelectRate/types"
|
||||||
|
|
||||||
export function DesktopSummary({
|
export function DesktopSummary({
|
||||||
input,
|
input,
|
||||||
@@ -30,7 +29,7 @@ export function DesktopSummary({
|
|||||||
bookingCode: string
|
bookingCode: string
|
||||||
}) {
|
}) {
|
||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
const isUserLoggedIn = useIsUserLoggedIn()
|
const isUserLoggedIn = useIsLoggedIn()
|
||||||
|
|
||||||
if (!selectedRates.totalPrice) {
|
if (!selectedRates.totalPrice) {
|
||||||
return null
|
return null
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
import { cx } from "class-variance-authority"
|
import { cx } from "class-variance-authority"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { useSelectRateContext } from "@scandic-hotels/booking-flow/contexts/SelectRate/SelectRateContext"
|
|
||||||
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||||
import { longDateFormat } from "@scandic-hotels/common/constants/dateFormats"
|
import { longDateFormat } from "@scandic-hotels/common/constants/dateFormats"
|
||||||
import { dt } from "@scandic-hotels/common/dt"
|
import { dt } from "@scandic-hotels/common/dt"
|
||||||
@@ -12,17 +11,17 @@ import { IconButton } from "@scandic-hotels/design-system/IconButton"
|
|||||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
|
|
||||||
import PriceDetailsModal from "@/components/HotelReservation/PriceDetailsModal"
|
import { useSelectRateContext } from "../../../../../../contexts/SelectRate/SelectRateContext"
|
||||||
import SignupPromoDesktop from "@/components/HotelReservation/SignupPromo/Desktop"
|
import useLang from "../../../../../../hooks/useLang"
|
||||||
import useRateTitles from "@/hooks/booking/useRateTitles"
|
import PriceDetailsModal from "../../../../../PriceDetailsModal"
|
||||||
import useLang from "@/hooks/useLang"
|
import SignupPromoDesktop from "../../../../../SignupPromo/Desktop"
|
||||||
|
import { useRateTitles } from "../../../Rooms/RoomsList/RoomListItem/Rates/useRateTitles"
|
||||||
import { isBookingCodeRate } from "../../utils"
|
import { isBookingCodeRate } from "../../utils"
|
||||||
import Room from "../Room"
|
import Room from "../Room"
|
||||||
|
|
||||||
import styles from "./summaryContent.module.css"
|
import styles from "./summaryContent.module.css"
|
||||||
|
|
||||||
import type { Price } from "@scandic-hotels/booking-flow/contexts/SelectRate/getTotalPrice"
|
import type { Price } from "../../../../../../contexts/SelectRate/getTotalPrice"
|
||||||
|
|
||||||
export type SelectRateSummaryProps = {
|
export type SelectRateSummaryProps = {
|
||||||
isMember: boolean
|
isMember: boolean
|
||||||
@@ -100,12 +99,10 @@ export default function SummaryContent({
|
|||||||
.locale(lang)
|
.locale(lang)
|
||||||
.format(longDateFormat[lang])}
|
.format(longDateFormat[lang])}
|
||||||
<MaterialIcon icon="arrow_forward" size={15} color="CurrentColor" />
|
<MaterialIcon icon="arrow_forward" size={15} color="CurrentColor" />
|
||||||
{/* eslint-disable formatjs/no-literal-string-in-jsx */}
|
|
||||||
{dt(input.data?.booking.toDate)
|
{dt(input.data?.booking.toDate)
|
||||||
.locale(lang)
|
.locale(lang)
|
||||||
.format(longDateFormat[lang])}{" "}
|
.format(longDateFormat[lang])}{" "}
|
||||||
({nightsLabel})
|
({nightsLabel})
|
||||||
{/* eslint-enable formatjs/no-literal-string-in-jsx */}
|
|
||||||
</p>
|
</p>
|
||||||
</Typography>
|
</Typography>
|
||||||
</header>
|
</header>
|
||||||
@@ -16,19 +16,20 @@ import styles from "./room.module.css"
|
|||||||
|
|
||||||
import type { Child } from "@scandic-hotels/trpc/types/child"
|
import type { Child } from "@scandic-hotels/trpc/types/child"
|
||||||
import type { Packages } from "@scandic-hotels/trpc/types/packages"
|
import type { Packages } from "@scandic-hotels/trpc/types/packages"
|
||||||
|
import type { Product } from "@scandic-hotels/trpc/types/roomAvailability"
|
||||||
|
|
||||||
import type {
|
import type { Price } from "../../../../../../types/price"
|
||||||
RoomPrice,
|
|
||||||
RoomRate,
|
|
||||||
} from "@/types/components/hotelReservation/enterDetails/details"
|
|
||||||
|
|
||||||
interface RoomProps {
|
interface RoomProps {
|
||||||
room: {
|
room: {
|
||||||
adults: number
|
adults: number
|
||||||
childrenInRoom: Child[] | undefined
|
childrenInRoom: Child[] | undefined
|
||||||
roomType: string
|
roomType: string
|
||||||
roomPrice: RoomPrice
|
roomPrice: {
|
||||||
roomRate: RoomRate
|
perNight: Price
|
||||||
|
perStay: Price
|
||||||
|
}
|
||||||
|
roomRate: Product
|
||||||
rateDetails: string[] | undefined
|
rateDetails: string[] | undefined
|
||||||
cancellationText: string
|
cancellationText: string
|
||||||
packages?: Packages
|
packages?: Packages
|
||||||
@@ -4,14 +4,13 @@ import { useEffect, useRef, useState } from "react"
|
|||||||
import { Button as ButtonRAC } from "react-aria-components"
|
import { Button as ButtonRAC } from "react-aria-components"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { useSelectRateContext } from "@scandic-hotels/booking-flow/contexts/SelectRate/SelectRateContext"
|
|
||||||
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
|
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
|
||||||
import { Button } from "@scandic-hotels/design-system/Button"
|
import { Button } from "@scandic-hotels/design-system/Button"
|
||||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
|
|
||||||
import { useIsUserLoggedIn } from "@/hooks/useIsUserLoggedIn"
|
import { useSelectRateContext } from "../../../../../contexts/SelectRate/SelectRateContext"
|
||||||
|
import { useIsLoggedIn } from "../../../../../hooks/useIsLoggedIn"
|
||||||
import { isBookingCodeRate } from "../utils"
|
import { isBookingCodeRate } from "../utils"
|
||||||
import SummaryContent from "./Content"
|
import SummaryContent from "./Content"
|
||||||
|
|
||||||
@@ -21,7 +20,7 @@ export function MobileSummary() {
|
|||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
const scrollY = useRef(0)
|
const scrollY = useRef(0)
|
||||||
const [isSummaryOpen, setIsSummaryOpen] = useState(false)
|
const [isSummaryOpen, setIsSummaryOpen] = useState(false)
|
||||||
const isUserLoggedIn = useIsUserLoggedIn()
|
const isUserLoggedIn = useIsLoggedIn()
|
||||||
|
|
||||||
const { selectedRates } = useSelectRateContext()
|
const { selectedRates } = useSelectRateContext()
|
||||||
|
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||||
|
|
||||||
|
import type { Packages } from "@scandic-hotels/trpc/types/packages"
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
Rate,
|
Rate,
|
||||||
Room,
|
Room,
|
||||||
} from "@scandic-hotels/booking-flow/types/components/selectRate/selectRate"
|
} from "../../../../../types/components/selectRate/selectRate"
|
||||||
import type { Packages } from "@scandic-hotels/trpc/types/packages"
|
import type { Price } from "../../../../../types/price"
|
||||||
|
|
||||||
import type { Price } from "@/types/components/hotelReservation/price"
|
|
||||||
|
|
||||||
export function mapRate(
|
export function mapRate(
|
||||||
room: Rate,
|
room: Rate,
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { RoomRate } from "@/types/components/hotelReservation/enterDetails/details"
|
import type { Product } from "@scandic-hotels/trpc/types/roomAvailability"
|
||||||
|
|
||||||
export function getMemberPrice(roomRate: RoomRate) {
|
export function getMemberPrice(roomRate: Product) {
|
||||||
if ("member" in roomRate && roomRate.member) {
|
if ("member" in roomRate && roomRate.member) {
|
||||||
return {
|
return {
|
||||||
amount: roomRate.member.localPrice.pricePerStay,
|
amount: roomRate.member.localPrice.pricePerStay,
|
||||||
@@ -3,10 +3,8 @@
|
|||||||
import { useRouter, useSearchParams } from "next/navigation"
|
import { useRouter, useSearchParams } from "next/navigation"
|
||||||
import { useState, useTransition } from "react"
|
import { useState, useTransition } from "react"
|
||||||
|
|
||||||
import { useSelectRateContext } from "@scandic-hotels/booking-flow/contexts/SelectRate/SelectRateContext"
|
import { useSelectRateContext } from "../../../../contexts/SelectRate/SelectRateContext"
|
||||||
|
import { ErrorBoundary } from "../../../ErrorBoundary/ErrorBoundary"
|
||||||
import { ErrorBoundary } from "@/components/ErrorBoundary/ErrorBoundary"
|
|
||||||
|
|
||||||
import { DesktopSummary } from "./DesktopSummary"
|
import { DesktopSummary } from "./DesktopSummary"
|
||||||
import { MobileSummary } from "./MobileSummary"
|
import { MobileSummary } from "./MobileSummary"
|
||||||
|
|
||||||
@@ -14,7 +12,6 @@ import styles from "./rateSummary.module.css"
|
|||||||
|
|
||||||
export function RateSummary() {
|
export function RateSummary() {
|
||||||
return (
|
return (
|
||||||
// eslint-disable-next-line formatjs/no-literal-string-in-jsx
|
|
||||||
<ErrorBoundary fallback={<div>Unable to render summary</div>}>
|
<ErrorBoundary fallback={<div>Unable to render summary</div>}>
|
||||||
<InnerRateSummary />
|
<InnerRateSummary />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
@@ -62,7 +59,6 @@ function InnerRateSummary() {
|
|||||||
>
|
>
|
||||||
<div className={styles.summary}>
|
<div className={styles.summary}>
|
||||||
<div className={styles.content}>
|
<div className={styles.content}>
|
||||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
|
||||||
<ErrorBoundary fallback={<div>Unable to render desktop summary</div>}>
|
<ErrorBoundary fallback={<div>Unable to render desktop summary</div>}>
|
||||||
<DesktopSummary
|
<DesktopSummary
|
||||||
isSubmitting={isSubmitting}
|
isSubmitting={isSubmitting}
|
||||||
@@ -73,7 +69,6 @@ function InnerRateSummary() {
|
|||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.mobileSummary}>
|
<div className={styles.mobileSummary}>
|
||||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
|
||||||
<ErrorBoundary fallback={<div>Unable to render mobile summary</div>}>
|
<ErrorBoundary fallback={<div>Unable to render mobile summary</div>}>
|
||||||
<MobileSummary />
|
<MobileSummary />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
@@ -1,15 +1,16 @@
|
|||||||
import { sumPackages } from "@scandic-hotels/booking-flow/utils/SelectRate"
|
|
||||||
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||||
import { RateTypeEnum } from "@scandic-hotels/common/constants/rateType"
|
import { RateTypeEnum } from "@scandic-hotels/common/constants/rateType"
|
||||||
|
|
||||||
import type { Rate } from "@scandic-hotels/booking-flow/types/components/selectRate/selectRate"
|
import { sumPackages } from "../../../../utils/SelectRate"
|
||||||
|
|
||||||
import type { Packages } from "@scandic-hotels/trpc/types/packages"
|
import type { Packages } from "@scandic-hotels/trpc/types/packages"
|
||||||
import type {
|
import type {
|
||||||
Product,
|
Product,
|
||||||
RedemptionProduct,
|
RedemptionProduct,
|
||||||
} from "@scandic-hotels/trpc/types/roomAvailability"
|
} from "@scandic-hotels/trpc/types/roomAvailability"
|
||||||
|
|
||||||
import type { Price } from "@/types/components/hotelReservation/price"
|
import type { Rate } from "../../../../types/components/selectRate/selectRate"
|
||||||
|
import type { Price } from "../../../../types/price"
|
||||||
|
|
||||||
export function calculateTotalPrice(
|
export function calculateTotalPrice(
|
||||||
selectedRateSummary: Rate[],
|
selectedRateSummary: Rate[],
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
"use client"
|
"use client"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { useSelectRateContext } from "@scandic-hotels/booking-flow/contexts/SelectRate/SelectRateContext"
|
|
||||||
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||||
import { RateEnum } from "@scandic-hotels/common/constants/rate"
|
import { RateEnum } from "@scandic-hotels/common/constants/rate"
|
||||||
import { logger } from "@scandic-hotels/common/logger"
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
@@ -13,7 +12,8 @@ import Image from "@scandic-hotels/design-system/Image"
|
|||||||
import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton"
|
import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton"
|
||||||
import Subtitle from "@scandic-hotels/design-system/Subtitle"
|
import Subtitle from "@scandic-hotels/design-system/Subtitle"
|
||||||
|
|
||||||
import { useIsUserLoggedIn } from "@/hooks/useIsUserLoggedIn"
|
import { useSelectRateContext } from "../../../../../../contexts/SelectRate/SelectRateContext"
|
||||||
|
import { useIsLoggedIn } from "../../../../../../hooks/useIsLoggedIn"
|
||||||
|
|
||||||
import styles from "./selectedRoomPanel.module.css"
|
import styles from "./selectedRoomPanel.module.css"
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ export function SelectedRoomPanel({ roomIndex }: { roomIndex: number }) {
|
|||||||
|
|
||||||
function useSelectedProductTitle({ roomIndex }: { roomIndex: number }) {
|
function useSelectedProductTitle({ roomIndex }: { roomIndex: number }) {
|
||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
const isUserLoggedIn = useIsUserLoggedIn()
|
const isUserLoggedIn = useIsLoggedIn()
|
||||||
const {
|
const {
|
||||||
selectedRates,
|
selectedRates,
|
||||||
input: { nights },
|
input: { nights },
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
import { useEffect } from "react"
|
import { useEffect } from "react"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { useSelectRateContext } from "@scandic-hotels/booking-flow/contexts/SelectRate/SelectRateContext"
|
|
||||||
import useStickyPosition from "@scandic-hotels/common/hooks/useStickyPosition"
|
import useStickyPosition from "@scandic-hotels/common/hooks/useStickyPosition"
|
||||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||||
import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton"
|
import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton"
|
||||||
import Subtitle from "@scandic-hotels/design-system/Subtitle"
|
import Subtitle from "@scandic-hotels/design-system/Subtitle"
|
||||||
|
|
||||||
|
import { useSelectRateContext } from "../../../../../contexts/SelectRate/SelectRateContext"
|
||||||
import { SelectedRoomPanel } from "./SelectedRoomPanel"
|
import { SelectedRoomPanel } from "./SelectedRoomPanel"
|
||||||
import { roomSelectionPanelVariants } from "./variants"
|
import { roomSelectionPanelVariants } from "./variants"
|
||||||
|
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
"use client"
|
"use client"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { useSelectRateContext } from "@scandic-hotels/booking-flow/contexts/SelectRate/SelectRateContext"
|
|
||||||
import { AlertTypeEnum } from "@scandic-hotels/common/constants/alert"
|
import { AlertTypeEnum } from "@scandic-hotels/common/constants/alert"
|
||||||
import { alternativeHotels } from "@scandic-hotels/common/constants/routes/hotelReservation"
|
import { alternativeHotels } from "@scandic-hotels/common/constants/routes/hotelReservation"
|
||||||
import { Alert } from "@scandic-hotels/design-system/Alert"
|
import { Alert } from "@scandic-hotels/design-system/Alert"
|
||||||
import { AvailabilityEnum } from "@scandic-hotels/trpc/enums/selectHotel"
|
import { AvailabilityEnum } from "@scandic-hotels/trpc/enums/selectHotel"
|
||||||
|
|
||||||
import useLang from "@/hooks/useLang"
|
import { useSelectRateContext } from "../../../../../contexts/SelectRate/SelectRateContext"
|
||||||
|
import useLang from "../../../../../hooks/useLang"
|
||||||
|
|
||||||
import styles from "./alert.module.css"
|
import styles from "./alert.module.css"
|
||||||
|
|
||||||
@@ -12,15 +12,15 @@ import {
|
|||||||
} from "react-aria-components"
|
} from "react-aria-components"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { useSelectRateContext } from "@scandic-hotels/booking-flow/contexts/SelectRate/SelectRateContext"
|
|
||||||
import { BookingCodeFilterEnum } from "@scandic-hotels/booking-flow/stores/bookingCode-filter"
|
|
||||||
import { RateTypeEnum } from "@scandic-hotels/common/constants/rateType"
|
import { RateTypeEnum } from "@scandic-hotels/common/constants/rateType"
|
||||||
import { ChipButton } from "@scandic-hotels/design-system/ChipButton"
|
import { ChipButton } from "@scandic-hotels/design-system/ChipButton"
|
||||||
import { IconButton } from "@scandic-hotels/design-system/IconButton"
|
import { IconButton } from "@scandic-hotels/design-system/IconButton"
|
||||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
|
|
||||||
import { useBreakpoint } from "@/hooks/useBreakpoint"
|
import { useSelectRateContext } from "../../../../../../contexts/SelectRate/SelectRateContext"
|
||||||
|
import { useBreakpoint } from "../../../../../../hooks/useBreakpoint"
|
||||||
|
import { BookingCodeFilterEnum } from "../../../../../../stores/bookingCode-filter"
|
||||||
|
|
||||||
import styles from "./bookingCodeFilter.module.css"
|
import styles from "./bookingCodeFilter.module.css"
|
||||||
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useSelectRateContext } from "@scandic-hotels/booking-flow/contexts/SelectRate/SelectRateContext"
|
|
||||||
import { BookingCodeChip } from "@scandic-hotels/design-system/BookingCodeChip"
|
import { BookingCodeChip } from "@scandic-hotels/design-system/BookingCodeChip"
|
||||||
|
|
||||||
|
import { useSelectRateContext } from "../../../../../../contexts/SelectRate/SelectRateContext"
|
||||||
|
|
||||||
export function RemoveBookingCodeButton() {
|
export function RemoveBookingCodeButton() {
|
||||||
const {
|
const {
|
||||||
input: { bookingCode },
|
input: { bookingCode },
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user