Merged in chore/SW-2878-extract-booking-confirmation-pag (pull request #2779)
Chore/SW-2878 extract booking confirmation pag * chore(SW-2878): Moved booking confirmation page to booking-flow package * chore(SW-2878): Fixed promo styles as per design * chore(SW-2878): Kept tiny duplicate function to avoid export from booking-flow package Approved-by: Anton Gunnarsson
This commit is contained in:
@@ -1,12 +1,8 @@
|
||||
import { cookies } from "next/headers"
|
||||
import { notFound, redirect } from "next/navigation"
|
||||
import { BookingConfirmationPage as BookingConfirmationPagePrimitive } from "@scandic-hotels/booking-flow/pages/BookingConfirmationPage"
|
||||
|
||||
import { decrypt } from "@scandic-hotels/trpc/utils/encryption"
|
||||
|
||||
import { MEMBERSHIP_FAILED_ERROR } from "@/constants/booking"
|
||||
import { getBookingConfirmation } from "@/lib/trpc/memoizedRequests"
|
||||
|
||||
import BookingConfirmation from "@/components/HotelReservation/BookingConfirmation"
|
||||
import Tracking from "@/components/HotelReservation/BookingConfirmation/Tracking"
|
||||
import { getIntl } from "@/i18n"
|
||||
import { getLang } from "@/i18n/serverContext"
|
||||
|
||||
import type { LangParams, PageArgs } from "@/types/params"
|
||||
|
||||
@@ -14,35 +10,20 @@ export default async function BookingConfirmationPage(
|
||||
props: PageArgs<LangParams, { RefId?: string }>
|
||||
) {
|
||||
const searchParams = await props.searchParams
|
||||
const params = await props.params
|
||||
const refId = searchParams.RefId
|
||||
|
||||
if (!refId) {
|
||||
notFound()
|
||||
}
|
||||
|
||||
const cookieStore = await cookies()
|
||||
const sig = cookieStore.get("bcsig")?.value
|
||||
|
||||
if (!sig) {
|
||||
redirect(`/${params.lang}`)
|
||||
}
|
||||
|
||||
const expire = Number(decrypt(sig))
|
||||
const now = Math.floor(Date.now() / 1000)
|
||||
if (typeof expire === "number" && !isNaN(expire) && now > expire) {
|
||||
redirect(`/${params.lang}`)
|
||||
}
|
||||
|
||||
void getBookingConfirmation(refId)
|
||||
|
||||
const membershipFailedError =
|
||||
searchParams.errorCode === MEMBERSHIP_FAILED_ERROR
|
||||
const lang = await getLang()
|
||||
const intl = await getIntl()
|
||||
|
||||
return (
|
||||
<BookingConfirmation
|
||||
refId={refId}
|
||||
membershipFailedError={membershipFailedError}
|
||||
<BookingConfirmationPagePrimitive
|
||||
intl={intl}
|
||||
lang={lang}
|
||||
searchParams={searchParams}
|
||||
renderTracking={(props) => (
|
||||
<Tracking
|
||||
bookingConfirmation={props.bookingConfirmation}
|
||||
refId={props.refId}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { notFound } from "next/navigation"
|
||||
|
||||
import { PaymentCallbackStatusEnum } from "@scandic-hotels/common/constants/booking"
|
||||
import { myStay } from "@scandic-hotels/common/constants/routes/myStay"
|
||||
import { logger } from "@scandic-hotels/common/logger"
|
||||
import { LoadingSpinner } from "@scandic-hotels/design-system/LoadingSpinner"
|
||||
import { BookingErrorCodeEnum } from "@scandic-hotels/trpc/enums/bookingErrorCode"
|
||||
|
||||
import { PaymentCallbackStatusEnum } from "@/constants/booking"
|
||||
import { serverClient } from "@/lib/trpc/server"
|
||||
|
||||
import GuaranteeCallback from "@/components/HotelReservation/MyStay/Ancillaries/GuaranteeCallback"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { notFound } from "next/navigation"
|
||||
|
||||
import { PaymentCallbackStatusEnum } from "@scandic-hotels/common/constants/booking"
|
||||
import {
|
||||
bookingConfirmation,
|
||||
details,
|
||||
@@ -11,7 +12,6 @@ import { getBooking } from "@scandic-hotels/trpc/routers/booking/utils"
|
||||
import { encrypt } from "@scandic-hotels/trpc/utils/encryption"
|
||||
import { isValidSession } from "@scandic-hotels/trpc/utils/session"
|
||||
|
||||
import { PaymentCallbackStatusEnum } from "@/constants/booking"
|
||||
import { serverClient } from "@/lib/trpc/server"
|
||||
|
||||
import { auth } from "@/auth"
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import Body from "@scandic-hotels/design-system/Body"
|
||||
import Link from "@scandic-hotels/design-system/Link"
|
||||
import Subtitle from "@scandic-hotels/design-system/Subtitle"
|
||||
|
||||
import styles from "./hotelDetails.module.css"
|
||||
|
||||
import type { BookingConfirmationHotelDetailsProps } from "@/types/components/hotelReservation/bookingConfirmation/hotelDetails"
|
||||
|
||||
export default function HotelDetails({
|
||||
hotel,
|
||||
}: BookingConfirmationHotelDetailsProps) {
|
||||
const intl = useIntl()
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.details}>
|
||||
<Subtitle color="uiTextHighContrast" type="two">
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Hotel details",
|
||||
})}
|
||||
</Subtitle>
|
||||
<div className={styles.hotel}>
|
||||
<Body color="uiTextHighContrast">{hotel.name}</Body>
|
||||
<Body color="uiTextHighContrast">
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "{streetAddress}, {zipCode} {city}",
|
||||
},
|
||||
{
|
||||
streetAddress: hotel.address.streetAddress,
|
||||
zipCode: hotel.address.zipCode,
|
||||
city: hotel.address.city,
|
||||
}
|
||||
)}
|
||||
</Body>
|
||||
<Body asChild color="uiTextHighContrast">
|
||||
<Link
|
||||
className={styles.link}
|
||||
href={`tel:${hotel.contactInformation.phoneNumber}`}
|
||||
>
|
||||
{hotel.contactInformation.phoneNumber}
|
||||
</Link>
|
||||
</Body>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.contact}>
|
||||
<Link
|
||||
className={styles.link}
|
||||
color="Text/Interactive/Secondary"
|
||||
href={`mailto:${hotel.contactInformation.email}`}
|
||||
>
|
||||
{hotel.contactInformation.email}
|
||||
</Link>
|
||||
<Link
|
||||
className={styles.link}
|
||||
color="Text/Interactive/Secondary"
|
||||
href={hotel.contactInformation.websiteUrl}
|
||||
>
|
||||
{hotel.contactInformation.websiteUrl}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { useBookingConfirmationStore } from "@scandic-hotels/booking-flow/stores/booking-confirmation"
|
||||
import Body from "@scandic-hotels/design-system/Body"
|
||||
import SkeletonShimmer from "@scandic-hotels/design-system/SkeletonShimmer"
|
||||
import Subtitle from "@scandic-hotels/design-system/Subtitle"
|
||||
|
||||
import styles from "./paymentDetails.module.css"
|
||||
|
||||
export default function PaymentDetails() {
|
||||
const intl = useIntl()
|
||||
|
||||
const { rooms, formattedTotalCost } = useBookingConfirmationStore(
|
||||
(state) => ({
|
||||
rooms: state.rooms,
|
||||
formattedTotalCost: state.formattedTotalCost,
|
||||
})
|
||||
)
|
||||
|
||||
const hasAllRoomsLoaded = rooms.every((room) => room)
|
||||
return (
|
||||
<div className={styles.details}>
|
||||
<Subtitle color="uiTextHighContrast" type="two">
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Payment details",
|
||||
})}
|
||||
</Subtitle>
|
||||
<div className={styles.payment}>
|
||||
{hasAllRoomsLoaded ? (
|
||||
<Body color="uiTextHighContrast">
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Total cost: {amount}",
|
||||
},
|
||||
{
|
||||
amount: formattedTotalCost,
|
||||
}
|
||||
)}
|
||||
</Body>
|
||||
) : (
|
||||
<SkeletonShimmer width={"100%"} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import Body from "@scandic-hotels/design-system/Body"
|
||||
import Link from "@scandic-hotels/design-system/Link"
|
||||
import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton"
|
||||
import Title from "@scandic-hotels/design-system/Title"
|
||||
|
||||
import styles from "./promo.module.css"
|
||||
|
||||
import type { PromoProps } from "@/types/components/hotelReservation/bookingConfirmation/promo"
|
||||
|
||||
export default function Promo({ buttonText, href, text, title }: PromoProps) {
|
||||
return (
|
||||
<Link className={styles.link} color="none" href={href}>
|
||||
<article className={styles.promo}>
|
||||
<Title color="white" level="h4">
|
||||
{title}
|
||||
</Title>
|
||||
<Body className={styles.text} color="white" textAlign="center">
|
||||
{text}
|
||||
</Body>
|
||||
<Button asChild intent="primary" size="small" theme="primaryStrong">
|
||||
<div>{buttonText}</div>
|
||||
</Button>
|
||||
</article>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import Body from "@scandic-hotels/design-system/Body"
|
||||
import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton"
|
||||
|
||||
import styles from "./retry.module.css"
|
||||
|
||||
import type { RetryProps } from "@/types/components/hotelReservation/bookingConfirmation/rooms/linkedReservation"
|
||||
|
||||
export default function Retry({ handleRefetch }: RetryProps) {
|
||||
const intl = useIntl()
|
||||
return (
|
||||
<div className={styles.retry}>
|
||||
<Body>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Something went wrong!",
|
||||
})}
|
||||
</Body>
|
||||
|
||||
<Button size={"small"} onPress={handleRefetch}>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Try again",
|
||||
})}
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import { createHash } from "crypto"
|
||||
import { differenceInCalendarDays, format, isWeekend } from "date-fns"
|
||||
|
||||
import { invertedBedTypeMap } from "@scandic-hotels/booking-flow/utils/SelectRate"
|
||||
import { CancellationRuleEnum } from "@scandic-hotels/common/constants/booking"
|
||||
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||
import { RateEnum } from "@scandic-hotels/common/constants/rate"
|
||||
import {
|
||||
@@ -14,8 +15,6 @@ import {
|
||||
import { BreakfastPackageEnum } from "@scandic-hotels/trpc/enums/breakfast"
|
||||
import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
|
||||
|
||||
import { CancellationRuleEnum } from "@/constants/booking"
|
||||
|
||||
import { readPaymentInfoFromSessionStorage } from "@/components/HotelReservation/EnterDetails/Payment/helpers"
|
||||
import { getSpecialRoomType } from "@/utils/specialRoomType"
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@ import { useRouter } from "next/navigation"
|
||||
import { useEffect } from "react"
|
||||
|
||||
import { serializeBookingSearchParams } from "@scandic-hotels/booking-flow/utils/url"
|
||||
import { PaymentCallbackStatusEnum } from "@scandic-hotels/common/constants/booking"
|
||||
import { trackEvent } from "@scandic-hotels/common/tracking/base"
|
||||
import { LoadingSpinner } from "@scandic-hotels/design-system/LoadingSpinner"
|
||||
|
||||
import { PaymentCallbackStatusEnum } from "@/constants/booking"
|
||||
import { detailsStorageName } from "@/stores/enter-details"
|
||||
|
||||
import { trackPaymentEvent } from "@/utils/tracking"
|
||||
|
||||
@@ -3,11 +3,10 @@
|
||||
import { useRouter } from "next/navigation"
|
||||
import { useEffect } from "react"
|
||||
|
||||
import { MEMBERSHIP_FAILED_ERROR } from "@scandic-hotels/common/constants/booking"
|
||||
import { LoadingSpinner } from "@scandic-hotels/design-system/LoadingSpinner"
|
||||
import { BookingStatusEnum } from "@scandic-hotels/trpc/enums/bookingStatus"
|
||||
|
||||
import { MEMBERSHIP_FAILED_ERROR } from "@/constants/booking"
|
||||
|
||||
import { useHandleBookingStatus } from "@/hooks/booking/useHandleBookingStatus"
|
||||
|
||||
import TimeoutSpinner from "./TimeoutSpinner"
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
} from "react-aria-components"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { getFeatureDescription } from "@scandic-hotels/booking-flow/utils/getRoomFeatureDescription"
|
||||
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
|
||||
import Body from "@scandic-hotels/design-system/Body"
|
||||
import Caption from "@scandic-hotels/design-system/Caption"
|
||||
@@ -17,8 +18,6 @@ import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton"
|
||||
import Subtitle from "@scandic-hotels/design-system/Subtitle"
|
||||
|
||||
import { getFeatureDescription } from "@/components/HotelReservation/utils/getRoomFeatureDescription"
|
||||
|
||||
import styles from "./priceChangeSummary.module.css"
|
||||
|
||||
import type { RoomState } from "@/types/stores/enter-details"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
"use client"
|
||||
|
||||
import { useEnterDetailsStore } from "@/stores/enter-details"
|
||||
import { SidePanel } from "@scandic-hotels/booking-flow/components/SidePanel"
|
||||
|
||||
import SidePanel from "@/components/HotelReservation/SidePanel"
|
||||
import { useEnterDetailsStore } from "@/stores/enter-details"
|
||||
|
||||
import SummaryUI from "./UI"
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { cx } from "class-variance-authority"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { getFeatureDescription } from "@scandic-hotels/booking-flow/utils/getRoomFeatureDescription"
|
||||
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
|
||||
import { Button } from "@scandic-hotels/design-system/Button"
|
||||
@@ -10,8 +11,6 @@ import Modal from "@scandic-hotels/design-system/Modal"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
import { ChildBedMapEnum } from "@scandic-hotels/trpc/enums/childBedMapEnum"
|
||||
|
||||
import { getFeatureDescription } from "@/components/HotelReservation/utils/getRoomFeatureDescription"
|
||||
|
||||
import Breakfast from "./Breakfast"
|
||||
|
||||
import styles from "./room.module.css"
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import styles from "./promo.module.css"
|
||||
|
||||
import type { PromoProps } from "@/types/components/hotelReservation/bookingConfirmation/promo"
|
||||
import type { PromoProps } from "@scandic-hotels/booking-flow/types/components/promo/promoProps"
|
||||
|
||||
export default function Promo({
|
||||
buttonText,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
"use client"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { CancellationRuleEnum } from "@scandic-hotels/common/constants/booking"
|
||||
import { preliminaryReceipt } from "@scandic-hotels/common/constants/routes/myStay"
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
import Link from "@scandic-hotels/design-system/Link"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import { CancellationRuleEnum } from "@/constants/booking"
|
||||
import { useMyStayStore } from "@/stores/my-stay"
|
||||
|
||||
import useLang from "@/hooks/useLang"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { IconForFeatureCode } from "@scandic-hotels/booking-flow/utils/SelectRate"
|
||||
import { CancellationRuleEnum } from "@scandic-hotels/common/constants/booking"
|
||||
import { changeOrCancelDateFormat } from "@scandic-hotels/common/constants/dateFormats"
|
||||
import { RateEnum } from "@scandic-hotels/common/constants/rate"
|
||||
import { dt } from "@scandic-hotels/common/dt"
|
||||
@@ -15,8 +16,6 @@ import Modal from "@scandic-hotels/design-system/Modal"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
|
||||
|
||||
import { CancellationRuleEnum } from "@/constants/booking"
|
||||
|
||||
import useRateTitles from "@/hooks/booking/useRateTitles"
|
||||
import useLang from "@/hooks/useLang"
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { getFeatureDescription } from "@scandic-hotels/booking-flow/utils/getRoomFeatureDescription"
|
||||
import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
|
||||
|
||||
import { useMyStayStore } from "@/stores/my-stay"
|
||||
|
||||
import { getFeatureDescription } from "@/components/HotelReservation/utils/getRoomFeatureDescription"
|
||||
|
||||
import Row from "./Row"
|
||||
|
||||
export default function Packages() {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { CancellationRuleEnum } from "@scandic-hotels/common/constants/booking"
|
||||
import { RateEnum } from "@scandic-hotels/common/constants/rate"
|
||||
import { IconButton } from "@scandic-hotels/design-system/IconButton"
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
import Modal from "@scandic-hotels/design-system/Modal"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import { CancellationRuleEnum } from "@/constants/booking"
|
||||
import { useMyStayStore } from "@/stores/my-stay"
|
||||
|
||||
import useRateTitles from "@/hooks/booking/useRateTitles"
|
||||
|
||||
@@ -3,11 +3,10 @@
|
||||
import { useRouter } from "next/navigation"
|
||||
import { useEffect } from "react"
|
||||
|
||||
import { PaymentCallbackStatusEnum } from "@scandic-hotels/common/constants/booking"
|
||||
import { trackEvent } from "@scandic-hotels/common/tracking/base"
|
||||
import { LoadingSpinner } from "@scandic-hotels/design-system/LoadingSpinner"
|
||||
|
||||
import { PaymentCallbackStatusEnum } from "@/constants/booking"
|
||||
|
||||
import {
|
||||
clearGlaSessionStorage,
|
||||
readGlaFromSessionStorage,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { CancellationRuleEnum } from "@scandic-hotels/common/constants/booking"
|
||||
import { ChildBedTypeEnum } from "@scandic-hotels/trpc/enums/childBedTypeEnum"
|
||||
|
||||
import { CancellationRuleEnum } from "@/constants/booking"
|
||||
|
||||
export function formatChildBedPreferences({
|
||||
childrenAges,
|
||||
childBedPreferences,
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { CancellationRuleEnum } from "@scandic-hotels/common/constants/booking"
|
||||
import { dt } from "@scandic-hotels/common/dt"
|
||||
import { BookingStatusEnum } from "@scandic-hotels/trpc/enums/bookingStatus"
|
||||
import { BreakfastPackageEnum } from "@scandic-hotels/trpc/enums/breakfast"
|
||||
import { PackageTypeEnum } from "@scandic-hotels/trpc/enums/packages"
|
||||
import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
|
||||
|
||||
import { CancellationRuleEnum } from "@/constants/booking"
|
||||
|
||||
import { convertToChildType } from "../../utils/convertToChildType"
|
||||
import { getPriceType } from "../../utils/getPriceType"
|
||||
import { formatChildBedPreferences } from "../utils"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { getFeatureDescription } from "@scandic-hotels/booking-flow/utils/getRoomFeatureDescription"
|
||||
import { sumPackages } from "@scandic-hotels/booking-flow/utils/SelectRate"
|
||||
import { changeOrCancelDateFormat } from "@scandic-hotels/common/constants/dateFormats"
|
||||
import { dt } from "@scandic-hotels/common/dt"
|
||||
@@ -17,7 +18,6 @@ import { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
|
||||
import GuestDetails from "@/components/HotelReservation/MyStay/GuestDetails"
|
||||
import PriceType from "@/components/HotelReservation/MyStay/PriceType"
|
||||
import { hasModifiableRate } from "@/components/HotelReservation/MyStay/utils"
|
||||
import { getFeatureDescription } from "@/components/HotelReservation/utils/getRoomFeatureDescription"
|
||||
import useLang from "@/hooks/useLang"
|
||||
import { mapApiImagesToGalleryImages } from "@/utils/imageGallery"
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { type NextMiddleware, NextResponse } from "next/server"
|
||||
|
||||
import { SEARCHTYPE } from "@scandic-hotels/common/constants/booking"
|
||||
import { login } from "@scandic-hotels/common/constants/routes/handleAuth"
|
||||
import { findLang } from "@scandic-hotels/common/utils/languages"
|
||||
import { SEARCH_TYPE_REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
|
||||
import { isValidSession } from "@scandic-hotels/trpc/utils/session"
|
||||
|
||||
import { SEARCHTYPE } from "@/constants/booking"
|
||||
import { getPublicNextURL } from "@/server/utils"
|
||||
|
||||
import { auth } from "@/auth"
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
import type { BookingConfirmation } from "@scandic-hotels/trpc/types/bookingConfirmation"
|
||||
|
||||
export interface BookingConfirmationHotelDetailsProps {
|
||||
hotel: BookingConfirmation["hotel"]
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
import type { BookingConfirmation } from "@scandic-hotels/trpc/types/bookingConfirmation"
|
||||
|
||||
export interface PromosProps extends Pick<BookingConfirmation, "booking"> {}
|
||||
@@ -1,7 +0,0 @@
|
||||
import type { Room } from "@scandic-hotels/booking-flow/types/stores/booking-confirmation"
|
||||
|
||||
export interface BookingConfirmationReceiptRoomProps {
|
||||
room: Room
|
||||
roomNumber: number
|
||||
roomCount: number
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import type { BookingConfirmation } from "@scandic-hotels/trpc/types/bookingConfirmation"
|
||||
import type { Room } from "@scandic-hotels/trpc/types/hotel"
|
||||
|
||||
export interface BookingConfirmationRoomsProps
|
||||
extends Pick<BookingConfirmation, "booking"> {
|
||||
mainRoom: Room & {
|
||||
bedType: Room["roomTypes"][number]
|
||||
}
|
||||
checkInTime: string
|
||||
checkOutTime: string
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
export interface LinkedReservationProps {
|
||||
checkInTime: string
|
||||
checkOutTime: string
|
||||
refId: string
|
||||
roomIndex: number
|
||||
}
|
||||
|
||||
export interface RetryProps {
|
||||
handleRefetch: () => void
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
import type { BookingConfirmation } from "@scandic-hotels/trpc/types/bookingConfirmation"
|
||||
|
||||
export interface RoomProps {
|
||||
booking: BookingConfirmation["booking"]
|
||||
checkInTime: string
|
||||
checkOutTime: string
|
||||
img?: NonNullable<BookingConfirmation["room"]>["images"][number]
|
||||
roomName: NonNullable<BookingConfirmation["room"]>["name"]
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
import type { VariantProps } from "class-variance-authority"
|
||||
|
||||
import type { sidePanelVariants } from "@/components/HotelReservation/SidePanel/variants"
|
||||
|
||||
export interface SidePanelProps
|
||||
extends VariantProps<typeof sidePanelVariants> {}
|
||||
@@ -0,0 +1,74 @@
|
||||
"use client"
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import Link from "@scandic-hotels/design-system/Link"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import styles from "./hotelDetails.module.css"
|
||||
|
||||
import type { BookingConfirmation } from "@scandic-hotels/trpc/types/bookingConfirmation"
|
||||
|
||||
export function HotelDetails({
|
||||
hotel,
|
||||
}: {
|
||||
hotel: BookingConfirmation["hotel"]
|
||||
}) {
|
||||
const intl = useIntl()
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.details}>
|
||||
<Typography variant={"Title/Subtitle/md"}>
|
||||
<h3>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Hotel details",
|
||||
})}
|
||||
</h3>
|
||||
</Typography>
|
||||
<Typography variant={"Body/Paragraph/mdRegular"}>
|
||||
<div className={styles.hotel}>
|
||||
<p>{hotel.name}</p>
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "{streetAddress}, {zipCode} {city}",
|
||||
},
|
||||
{
|
||||
streetAddress: hotel.address.streetAddress,
|
||||
zipCode: hotel.address.zipCode,
|
||||
city: hotel.address.city,
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
<Link
|
||||
className={styles.link}
|
||||
href={`tel:${hotel.contactInformation.phoneNumber}`}
|
||||
>
|
||||
{hotel.contactInformation.phoneNumber}
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</Typography>
|
||||
</div>
|
||||
<div className={styles.contact}>
|
||||
<Link
|
||||
className={styles.link}
|
||||
color="Text/Interactive/Secondary"
|
||||
href={`mailto:${hotel.contactInformation.email}`}
|
||||
textDecoration={"underline"}
|
||||
>
|
||||
{hotel.contactInformation.email}
|
||||
</Link>
|
||||
<Link
|
||||
className={styles.link}
|
||||
color="Text/Interactive/Secondary"
|
||||
href={hotel.contactInformation.websiteUrl}
|
||||
textDecoration={"underline"}
|
||||
>
|
||||
{hotel.contactInformation.websiteUrl}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
"use client"
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import SkeletonShimmer from "@scandic-hotels/design-system/SkeletonShimmer"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import { useBookingConfirmationStore } from "../../../stores/booking-confirmation"
|
||||
|
||||
import styles from "./paymentDetails.module.css"
|
||||
|
||||
export function PaymentDetails() {
|
||||
const intl = useIntl()
|
||||
|
||||
const { rooms, formattedTotalCost } = useBookingConfirmationStore(
|
||||
(state) => ({
|
||||
rooms: state.rooms,
|
||||
formattedTotalCost: state.formattedTotalCost,
|
||||
})
|
||||
)
|
||||
|
||||
const hasAllRoomsLoaded = rooms.every((room) => room)
|
||||
return (
|
||||
<div className={styles.details}>
|
||||
<Typography variant={"Title/Subtitle/md"}>
|
||||
<h2>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Payment details",
|
||||
})}
|
||||
</h2>
|
||||
</Typography>
|
||||
<div className={styles.payment}>
|
||||
{hasAllRoomsLoaded ? (
|
||||
<Typography variant={"Body/Paragraph/mdRegular"}>
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Total cost: {amount}",
|
||||
},
|
||||
{
|
||||
amount: formattedTotalCost,
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</Typography>
|
||||
) : (
|
||||
<SkeletonShimmer width={"100%"} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
"use client"
|
||||
import PriceDetailsModal from "@scandic-hotels/booking-flow/components/PriceDetailsModal"
|
||||
import { useBookingConfirmationStore } from "@scandic-hotels/booking-flow/stores/booking-confirmation"
|
||||
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||
import { dt } from "@scandic-hotels/common/dt"
|
||||
|
||||
import PriceDetailsModal from "../../../components/PriceDetailsModal"
|
||||
import { useBookingConfirmationStore } from "../../../stores/booking-confirmation"
|
||||
import { mapToPrice } from "./mapToPrice"
|
||||
|
||||
import type { Price } from "@/types/components/hotelReservation/price"
|
||||
import type { Price } from "../../../types/price"
|
||||
|
||||
export default function PriceDetails() {
|
||||
const { bookingCode, currency, fromDate, rooms, vat, toDate } =
|
||||
@@ -7,9 +7,10 @@ import {
|
||||
packageSchema,
|
||||
} from "@scandic-hotels/trpc/routers/hotels/schemas/packages"
|
||||
|
||||
import type { Room } from "@scandic-hotels/booking-flow/types/stores/booking-confirmation"
|
||||
import type { Package } from "@scandic-hotels/trpc/types/packages"
|
||||
|
||||
import type { Room } from "../../../types/stores/booking-confirmation"
|
||||
|
||||
export function mapToPrice(rooms: (Room | null)[], nights: number) {
|
||||
return rooms
|
||||
.filter((room): room is Room => !!room)
|
||||
@@ -0,0 +1,25 @@
|
||||
import { Button } from "@scandic-hotels/design-system/Button"
|
||||
import Link from "@scandic-hotels/design-system/Link"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import styles from "./promo.module.css"
|
||||
|
||||
import type { PromoProps } from "../../../../types/components/promo/promoProps"
|
||||
|
||||
export function Promo({ buttonText, href, text, title }: PromoProps) {
|
||||
return (
|
||||
<Link className={styles.link} color="none" href={href}>
|
||||
<article className={styles.promo}>
|
||||
<Typography variant={"Title/smLowCase"}>
|
||||
<h4>{title}</h4>
|
||||
</Typography>
|
||||
<Typography variant={"Body/Paragraph/mdRegular"}>
|
||||
<p className={styles.text}>{text}</p>
|
||||
</Typography>
|
||||
<Button size="Small" variant={"Secondary"} color={"Inverted"} wrapping>
|
||||
<div>{buttonText}</div>
|
||||
</Button>
|
||||
</article>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
border-radius: var(--Medium, 8px);
|
||||
color: var(--Text-Brand-OnPrimary-2-Heading);
|
||||
display: flex;
|
||||
flex: 1 0 320px;
|
||||
flex-direction: column;
|
||||
@@ -37,4 +38,5 @@
|
||||
|
||||
.text {
|
||||
max-width: 400px;
|
||||
text-align: center;
|
||||
}
|
||||
@@ -4,17 +4,18 @@ import { useIntl } from "react-intl"
|
||||
|
||||
import { myStay } from "@scandic-hotels/common/constants/routes/myStay"
|
||||
|
||||
import useLang from "@/hooks/useLang"
|
||||
|
||||
import Promo from "./Promo"
|
||||
import useLang from "../../../hooks/useLang"
|
||||
import { Promo } from "./Promo"
|
||||
|
||||
import styles from "./promos.module.css"
|
||||
|
||||
import type { AdditionalInfoCookieValue } from "@scandic-hotels/booking-flow/types/components/findMyBooking/additionalInfoCookieValue"
|
||||
import type { BookingConfirmation } from "@scandic-hotels/trpc/types/bookingConfirmation"
|
||||
|
||||
import type { PromosProps } from "@/types/components/hotelReservation/bookingConfirmation/promos"
|
||||
import type { AdditionalInfoCookieValue } from "../../../types/components/findMyBooking/additionalInfoCookieValue"
|
||||
|
||||
export default function Promos({ booking }: PromosProps) {
|
||||
export interface PromosProps extends Pick<BookingConfirmation, "booking"> {}
|
||||
|
||||
export function Promos({ booking }: PromosProps) {
|
||||
const intl = useIntl()
|
||||
const lang = useLang()
|
||||
const { refId, confirmationNumber, hotelId } = booking
|
||||
@@ -3,7 +3,7 @@
|
||||
import { cx } from "class-variance-authority"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { useBookingConfirmationStore } from "@scandic-hotels/booking-flow/stores/booking-confirmation"
|
||||
import { CancellationRuleEnum } from "@scandic-hotels/common/constants/booking"
|
||||
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
|
||||
import { Button } from "@scandic-hotels/design-system/Button"
|
||||
import { Divider } from "@scandic-hotels/design-system/Divider"
|
||||
@@ -12,18 +12,22 @@ import Modal from "@scandic-hotels/design-system/Modal"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
import { ChildBedTypeEnum } from "@scandic-hotels/trpc/enums/childBedTypeEnum"
|
||||
|
||||
import { CancellationRuleEnum } from "@/constants/booking"
|
||||
|
||||
import { getFeatureDescription } from "@/components/HotelReservation/utils/getRoomFeatureDescription"
|
||||
|
||||
import { useBookingConfirmationStore } from "../../../../stores/booking-confirmation"
|
||||
import { getFeatureDescription } from "../../../../utils/getRoomFeatureDescription"
|
||||
import Breakfast from "./Breakfast"
|
||||
import RoomSkeletonLoader from "./RoomSkeletonLoader"
|
||||
|
||||
import styles from "./room.module.css"
|
||||
|
||||
import type { BookingConfirmationReceiptRoomProps } from "@/types/components/hotelReservation/bookingConfirmation/receipt"
|
||||
import type { Room } from "../../../../types/stores/booking-confirmation"
|
||||
|
||||
export default function ReceiptRoom({
|
||||
type BookingConfirmationReceiptRoomProps = {
|
||||
room: Room
|
||||
roomNumber: number
|
||||
roomCount: number
|
||||
}
|
||||
|
||||
export function ReceiptRoom({
|
||||
room,
|
||||
roomNumber,
|
||||
roomCount,
|
||||
@@ -3,12 +3,12 @@
|
||||
import { cx } from "class-variance-authority"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { useBookingConfirmationStore } from "@scandic-hotels/booking-flow/stores/booking-confirmation"
|
||||
import { BookingCodeChip } from "@scandic-hotels/design-system/BookingCodeChip"
|
||||
import { Divider } from "@scandic-hotels/design-system/Divider"
|
||||
import SkeletonShimmer from "@scandic-hotels/design-system/SkeletonShimmer"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import { useBookingConfirmationStore } from "../../../../stores/booking-confirmation"
|
||||
import PriceDetails from "../../PriceDetails"
|
||||
|
||||
import styles from "./totalPrice.module.css"
|
||||
@@ -2,21 +2,20 @@
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { useBookingConfirmationStore } from "@scandic-hotels/booking-flow/stores/booking-confirmation"
|
||||
import { longDateFormat } from "@scandic-hotels/common/constants/dateFormats"
|
||||
import { dt } from "@scandic-hotels/common/dt"
|
||||
import { Divider } from "@scandic-hotels/design-system/Divider"
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import useLang from "@/hooks/useLang"
|
||||
|
||||
import Room from "./Room"
|
||||
import useLang from "../../../hooks/useLang"
|
||||
import { useBookingConfirmationStore } from "../../../stores/booking-confirmation"
|
||||
import { ReceiptRoom as Room } from "./Room"
|
||||
import TotalPrice from "./TotalPrice"
|
||||
|
||||
import styles from "./receipt.module.css"
|
||||
|
||||
export default function Receipt() {
|
||||
export function Receipt() {
|
||||
const lang = useLang()
|
||||
const intl = useIntl()
|
||||
const { rooms, fromDate, toDate } = useBookingConfirmationStore((state) => ({
|
||||
@@ -0,0 +1,33 @@
|
||||
"use client"
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { Button } from "@scandic-hotels/design-system/Button"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import styles from "./retry.module.css"
|
||||
|
||||
export interface RetryProps {
|
||||
handleRefetch: () => void
|
||||
}
|
||||
|
||||
export default function Retry({ handleRefetch }: RetryProps) {
|
||||
const intl = useIntl()
|
||||
return (
|
||||
<div className={styles.retry}>
|
||||
<Typography variant={"Body/Paragraph/mdRegular"}>
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Something went wrong!",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
|
||||
<Button size={"Small"} onPress={handleRefetch}>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Try again",
|
||||
})}
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -3,19 +3,23 @@
|
||||
import { useEffect } from "react"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { useBookingConfirmationStore } from "@scandic-hotels/booking-flow/stores/booking-confirmation"
|
||||
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
|
||||
import { trpc } from "@scandic-hotels/trpc/client"
|
||||
|
||||
import useLang from "@/hooks/useLang"
|
||||
|
||||
import useLang from "../../../../hooks/useLang"
|
||||
import { useBookingConfirmationStore } from "../../../../stores/booking-confirmation"
|
||||
import { mapRoomState } from "../../utils"
|
||||
import Room from "../Room"
|
||||
import { Room } from "../Room"
|
||||
import { LinkedReservationCardSkeleton } from "./LinkedReservationCardSkeleton"
|
||||
import Retry from "./Retry"
|
||||
|
||||
import type { LinkedReservationProps } from "@/types/components/hotelReservation/bookingConfirmation/rooms/linkedReservation"
|
||||
export interface LinkedReservationProps {
|
||||
checkInTime: string
|
||||
checkOutTime: string
|
||||
refId: string
|
||||
roomIndex: number
|
||||
}
|
||||
|
||||
export function LinkedReservation({
|
||||
checkInTime,
|
||||
@@ -2,28 +2,34 @@
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { RoomDetailsSidePeek } from "@scandic-hotels/booking-flow/components/RoomDetailsSidePeek"
|
||||
import { useBookingConfirmationStore } from "@scandic-hotels/booking-flow/stores/booking-confirmation"
|
||||
import { CancellationRuleEnum } from "@scandic-hotels/common/constants/booking"
|
||||
import {
|
||||
changeOrCancelDateFormat,
|
||||
longDateFormat,
|
||||
} from "@scandic-hotels/common/constants/dateFormats"
|
||||
import { dt } from "@scandic-hotels/common/dt"
|
||||
import Caption from "@scandic-hotels/design-system/Caption"
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
import Image from "@scandic-hotels/design-system/Image"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
import { getHotelRoom } from "@scandic-hotels/trpc/routers/booking/helpers"
|
||||
|
||||
import { CancellationRuleEnum } from "@/constants/booking"
|
||||
|
||||
import useLang from "@/hooks/useLang"
|
||||
import { RoomDetailsSidePeek } from "../../../../components/RoomDetailsSidePeek"
|
||||
import useLang from "../../../../hooks/useLang"
|
||||
import { useBookingConfirmationStore } from "../../../../stores/booking-confirmation"
|
||||
|
||||
import styles from "./room.module.css"
|
||||
|
||||
import type { RoomProps } from "@/types/components/hotelReservation/bookingConfirmation/rooms/room"
|
||||
import type { BookingConfirmation } from "@scandic-hotels/trpc/types/bookingConfirmation"
|
||||
|
||||
export default function Room({
|
||||
export interface RoomProps {
|
||||
booking: BookingConfirmation["booking"]
|
||||
checkInTime: string
|
||||
checkOutTime: string
|
||||
img?: NonNullable<BookingConfirmation["room"]>["images"][number]
|
||||
roomName: NonNullable<BookingConfirmation["room"]>["name"]
|
||||
}
|
||||
|
||||
export function Room({
|
||||
booking,
|
||||
checkInTime,
|
||||
checkOutTime,
|
||||
@@ -67,11 +73,13 @@ export default function Room({
|
||||
icon="check_circle"
|
||||
size={20}
|
||||
/>
|
||||
<Caption>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Membership benefits applied",
|
||||
})}
|
||||
</Caption>
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
defaultMessage: "Membership benefits applied",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
</>
|
||||
</div>
|
||||
) : null}
|
||||
@@ -1,21 +1,33 @@
|
||||
"use client"
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
|
||||
import { getIntl } from "@/i18n"
|
||||
|
||||
import { LinkedReservation } from "./LinkedReservation"
|
||||
import Room from "./Room"
|
||||
import { Room } from "./Room"
|
||||
|
||||
import styles from "./rooms.module.css"
|
||||
|
||||
import type { BookingConfirmationRoomsProps } from "@/types/components/hotelReservation/bookingConfirmation/rooms"
|
||||
import type { BookingConfirmation } from "@scandic-hotels/trpc/types/bookingConfirmation"
|
||||
import type { Room as RoomProp } from "@scandic-hotels/trpc/types/hotel"
|
||||
|
||||
export default async function Rooms({
|
||||
export interface BookingConfirmationRoomsProps
|
||||
extends Pick<BookingConfirmation, "booking"> {
|
||||
mainRoom: RoomProp & {
|
||||
bedType: RoomProp["roomTypes"][number]
|
||||
}
|
||||
checkInTime: string
|
||||
checkOutTime: string
|
||||
}
|
||||
|
||||
export function Rooms({
|
||||
booking,
|
||||
checkInTime,
|
||||
checkOutTime,
|
||||
mainRoom,
|
||||
}: BookingConfirmationRoomsProps) {
|
||||
const intl = await getIntl()
|
||||
const intl = useIntl()
|
||||
|
||||
return (
|
||||
<section className={styles.rooms}>
|
||||
@@ -1,36 +1,42 @@
|
||||
import { notFound } from "next/navigation"
|
||||
|
||||
import { Confirmation } from "@scandic-hotels/booking-flow/components/BookingConfirmation/Confirmation"
|
||||
import BookingConfirmationProvider from "@scandic-hotels/booking-flow/providers/BookingConfirmationProvider"
|
||||
import { filterOverlappingDates } from "@scandic-hotels/booking-flow/utils/SelectRate"
|
||||
import { AlertTypeEnum } from "@scandic-hotels/common/constants/alert"
|
||||
import { dt } from "@scandic-hotels/common/dt"
|
||||
import { Alert } from "@scandic-hotels/design-system/Alert"
|
||||
import { Divider } from "@scandic-hotels/design-system/Divider"
|
||||
|
||||
import { getBookingConfirmation } from "@/lib/trpc/memoizedRequests"
|
||||
|
||||
import HotelDetails from "@/components/HotelReservation/BookingConfirmation/HotelDetails"
|
||||
import PaymentDetails from "@/components/HotelReservation/BookingConfirmation/PaymentDetails"
|
||||
import Promos from "@/components/HotelReservation/BookingConfirmation/Promos"
|
||||
import Receipt from "@/components/HotelReservation/BookingConfirmation/Receipt"
|
||||
import Rooms from "@/components/HotelReservation/BookingConfirmation/Rooms"
|
||||
import SidePanel from "@/components/HotelReservation/SidePanel"
|
||||
import { getIntl } from "@/i18n"
|
||||
|
||||
import Tracking from "./Tracking"
|
||||
import { BookingConfirmationProvider } from "../../providers/BookingConfirmationProvider"
|
||||
import { getBookingConfirmation } from "../../trpc/memoizedRequests/getBookingConfirmation"
|
||||
import { filterOverlappingDates } from "../../utils/SelectRate"
|
||||
import { SidePanel } from "../SidePanel"
|
||||
import { Confirmation } from "./Confirmation"
|
||||
import { HotelDetails } from "./HotelDetails"
|
||||
import { PaymentDetails } from "./PaymentDetails"
|
||||
import { Promos } from "./Promos"
|
||||
import { Receipt } from "./Receipt"
|
||||
import { Rooms } from "./Rooms"
|
||||
import { mapRoomState } from "./utils"
|
||||
|
||||
import styles from "./bookingConfirmation.module.css"
|
||||
|
||||
import type { BookingConfirmation } from "@scandic-hotels/trpc/types/bookingConfirmation"
|
||||
import type { IntlShape } from "react-intl"
|
||||
|
||||
type BookingConfirmationProps = {
|
||||
intl: IntlShape
|
||||
refId: string
|
||||
membershipFailedError: boolean
|
||||
renderTracking: (trackingProps: {
|
||||
bookingConfirmation: BookingConfirmation
|
||||
refId: string
|
||||
}) => React.ReactNode
|
||||
}
|
||||
|
||||
export default async function BookingConfirmation({
|
||||
export async function BookingConfirmation({
|
||||
intl,
|
||||
refId,
|
||||
membershipFailedError,
|
||||
renderTracking,
|
||||
}: BookingConfirmationProps) {
|
||||
const bookingConfirmation = await getBookingConfirmation(refId)
|
||||
|
||||
@@ -44,7 +50,6 @@ export default async function BookingConfirmation({
|
||||
return notFound()
|
||||
}
|
||||
|
||||
const intl = await getIntl()
|
||||
return (
|
||||
<BookingConfirmationProvider
|
||||
bookingCode={booking.bookingCode}
|
||||
@@ -106,7 +111,8 @@ export default async function BookingConfirmation({
|
||||
</SidePanel>
|
||||
</aside>
|
||||
</Confirmation>
|
||||
<Tracking bookingConfirmation={bookingConfirmation} refId={refId} />
|
||||
|
||||
{renderTracking({ bookingConfirmation, refId })}
|
||||
</BookingConfirmationProvider>
|
||||
)
|
||||
}
|
||||
@@ -4,12 +4,13 @@ import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
|
||||
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
|
||||
import { BreakfastPackageEnum } from "@scandic-hotels/trpc/enums/breakfast"
|
||||
|
||||
import type { BookingConfirmationRoom } from "@scandic-hotels/booking-flow/types/components/bookingConfirmation/bookingConfirmation"
|
||||
import type {
|
||||
BookingConfirmationSchema,
|
||||
PackageSchema,
|
||||
} from "@scandic-hotels/trpc/types/bookingConfirmation"
|
||||
|
||||
import type { BookingConfirmationRoom } from "../../types/components/bookingConfirmation/bookingConfirmation"
|
||||
|
||||
export function mapRoomState(
|
||||
booking: BookingConfirmationSchema,
|
||||
room: BookingConfirmationRoom,
|
||||
@@ -21,7 +21,7 @@ import Room from "../Room"
|
||||
|
||||
import styles from "./summaryContent.module.css"
|
||||
|
||||
import type { Price } from "../../../../../../contexts/SelectRate/getTotalPrice"
|
||||
import type { Price } from "../../../../../../types/price"
|
||||
|
||||
export type SelectRateSummaryProps = {
|
||||
isUserLoggedIn: boolean
|
||||
|
||||
@@ -2,9 +2,11 @@ import { sidePanelVariants } from "./variants"
|
||||
|
||||
import styles from "./sidePanel.module.css"
|
||||
|
||||
import type { SidePanelProps } from "@/types/components/hotelReservation/sidePanel"
|
||||
import type { VariantProps } from "class-variance-authority"
|
||||
|
||||
export default function SidePanel({
|
||||
interface SidePanelProps extends VariantProps<typeof sidePanelVariants> {}
|
||||
|
||||
export function SidePanel({
|
||||
children,
|
||||
variant,
|
||||
}: React.PropsWithChildren<SidePanelProps>) {
|
||||
@@ -31,13 +31,14 @@ import { clearRooms } from "./clearRooms"
|
||||
import { DebugButton } from "./DebugButton"
|
||||
import { findUnavailableSelectedRooms } from "./findUnavailableSelectedRooms"
|
||||
import { getSelectedPackages } from "./getSelectedPackages"
|
||||
import { getTotalPrice, type Price } from "./getTotalPrice"
|
||||
import { getTotalPrice } from "./getTotalPrice"
|
||||
import { includeRoomInfo } from "./includeRoomInfo"
|
||||
import { isRateSelected as isRateSelected_Inner } from "./isRateSelected"
|
||||
|
||||
import type { BreakfastPackageEnum } from "@scandic-hotels/trpc/enums/breakfast"
|
||||
|
||||
import type { SelectRateBooking } from "../../types/components/selectRate/selectRate"
|
||||
import type { Price } from "../../types/price"
|
||||
import type {
|
||||
AvailabilityWithRoomInfo,
|
||||
DefaultRoomPackage,
|
||||
|
||||
@@ -5,21 +5,9 @@ import { sumPackages, sumPackagesRequestedPrice } from "../../utils/SelectRate"
|
||||
|
||||
import type { RedemptionProduct } from "@scandic-hotels/trpc/types/roomAvailability"
|
||||
|
||||
import type { Price } from "../../types/price"
|
||||
import type { AvailabilityWithRoomInfo, Rate, RoomPackage } from "./types"
|
||||
|
||||
type TPrice = {
|
||||
additionalPrice?: number
|
||||
additionalPriceCurrency?: CurrencyEnum
|
||||
currency: CurrencyEnum
|
||||
price: number
|
||||
regularPrice?: number
|
||||
}
|
||||
|
||||
export type Price = {
|
||||
requested?: TPrice
|
||||
local: TPrice
|
||||
}
|
||||
|
||||
type SelectedRate = {
|
||||
roomConfiguration: AvailabilityWithRoomInfo | null
|
||||
rate: Rate | undefined
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { type RouterOutput } from "@scandic-hotels/trpc/client"
|
||||
|
||||
import { type Price } from "./getTotalPrice"
|
||||
|
||||
import type { RoomPackageCodeEnum } from "@scandic-hotels/trpc/enums/roomFilter"
|
||||
import type { RoomsAvailabilityOutputSchema } from "@scandic-hotels/trpc/types/availability"
|
||||
import type { PackageEnum } from "@scandic-hotels/trpc/types/packages"
|
||||
import type { RoomConfiguration } from "@scandic-hotels/trpc/types/roomAvailability"
|
||||
|
||||
import type { BookingCodeFilterEnum } from "../../stores/bookingCode-filter"
|
||||
import type { Price } from "../../types/price"
|
||||
|
||||
export type SelectRateContext = {
|
||||
hotel: QueryData<RouterOutput["hotel"]["get"]>
|
||||
|
||||
62
packages/booking-flow/lib/pages/BookingConfirmationPage.tsx
Normal file
62
packages/booking-flow/lib/pages/BookingConfirmationPage.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
import { cookies } from "next/headers"
|
||||
import { notFound, redirect } from "next/navigation"
|
||||
|
||||
import { MEMBERSHIP_FAILED_ERROR } from "@scandic-hotels/common/constants/booking"
|
||||
import { decrypt } from "@scandic-hotels/trpc/utils/encryption"
|
||||
|
||||
import { BookingConfirmation } from "../components/BookingConfirmation"
|
||||
import { getBookingConfirmation } from "../trpc/memoizedRequests/getBookingConfirmation"
|
||||
|
||||
import type { Lang } from "@scandic-hotels/common/constants/language"
|
||||
import type { BookingConfirmation as BookingConfirmationType } from "@scandic-hotels/trpc/types/bookingConfirmation"
|
||||
import type { IntlShape } from "react-intl"
|
||||
|
||||
import type { NextSearchParams } from "../types"
|
||||
|
||||
export async function BookingConfirmationPage({
|
||||
intl,
|
||||
lang,
|
||||
searchParams,
|
||||
renderTracking,
|
||||
}: {
|
||||
intl: IntlShape
|
||||
lang: Lang
|
||||
searchParams: NextSearchParams
|
||||
renderTracking: (trackingProps: {
|
||||
bookingConfirmation: BookingConfirmationType
|
||||
refId: string
|
||||
}) => React.ReactNode
|
||||
}) {
|
||||
const refId = searchParams.RefId?.toString()
|
||||
|
||||
if (!refId) {
|
||||
notFound()
|
||||
}
|
||||
|
||||
const cookieStore = await cookies()
|
||||
const sig = cookieStore.get("bcsig")?.value
|
||||
|
||||
if (!sig) {
|
||||
redirect(`/${lang}`)
|
||||
}
|
||||
|
||||
const expire = Number(decrypt(sig))
|
||||
const now = Math.floor(Date.now() / 1000)
|
||||
if (typeof expire === "number" && !isNaN(expire) && now > expire) {
|
||||
redirect(`/${lang}`)
|
||||
}
|
||||
|
||||
void getBookingConfirmation(refId)
|
||||
|
||||
const membershipFailedError =
|
||||
searchParams.errorCode === MEMBERSHIP_FAILED_ERROR
|
||||
|
||||
return (
|
||||
<BookingConfirmation
|
||||
intl={intl}
|
||||
refId={refId}
|
||||
membershipFailedError={membershipFailedError}
|
||||
renderTracking={renderTracking}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import { createBookingConfirmationStore } from "../stores/booking-confirmation"
|
||||
import type { BookingConfirmationStore } from "../types/contexts/booking-confirmation"
|
||||
import type { BookingConfirmationProviderProps } from "../types/providers/booking-confirmation"
|
||||
|
||||
export default function BookingConfirmationProvider({
|
||||
export function BookingConfirmationProvider({
|
||||
bookingCode,
|
||||
children,
|
||||
currencyCode,
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import { cache } from "react"
|
||||
|
||||
import { serverClient } from "../../trpc"
|
||||
|
||||
export const getBookingConfirmation = cache(
|
||||
async function getMemoizedBookingConfirmation(refId: string) {
|
||||
const caller = await serverClient()
|
||||
return caller.booking.get({ refId })
|
||||
}
|
||||
)
|
||||
@@ -1,4 +1,4 @@
|
||||
export interface PromoProps {
|
||||
export type PromoProps = {
|
||||
buttonText: string
|
||||
href: string
|
||||
text: string
|
||||
@@ -37,6 +37,7 @@
|
||||
"./components/SelectHotelMap": "./lib/components/SelectHotel/SelectHotelMap/index.tsx",
|
||||
"./components/SelectRate": "./lib/components/SelectRate/index.tsx",
|
||||
"./components/SelectRate/RoomsContainer/RateSummary/utils": "./lib/components/SelectRate/RoomsContainer/RateSummary/utils.ts",
|
||||
"./components/SidePanel": "./lib/components/SidePanel/index.tsx",
|
||||
"./components/SidePeekAccordions/BreakfastAccordionItem": "./lib/components/SidePeekAccordions/BreakfastAccordionItem.tsx",
|
||||
"./components/SidePeekAccordions/CheckInCheckOutAccordionItem": "./lib/components/SidePeekAccordions/CheckInCheckOutAccordionItem.tsx",
|
||||
"./components/SidePeekAccordions/ParkingAccordionItem": "./lib/components/SidePeekAccordions/ParkingAccordionItem.tsx",
|
||||
@@ -54,11 +55,13 @@
|
||||
"./stores/bookingCode-filter": "./lib/stores/bookingCode-filter.ts",
|
||||
"./stores/hotels-map": "./lib/stores/hotels-map.ts",
|
||||
"./stores/booking-confirmation": "./lib/stores/booking-confirmation/index.ts",
|
||||
"./types/components/selectRate/selectRate": "./lib/types/components/selectRate/selectRate.ts",
|
||||
"./types/components/bookingConfirmation/bookingConfirmation": "./lib/types/components/bookingConfirmation/bookingConfirmation.ts",
|
||||
"./types/components/findMyBooking/additionalInfoCookieValue": "./lib/types/components/findMyBooking/additionalInfoCookieValue.ts",
|
||||
"./types/components/promo/promoProps": "./lib/types/components/promo/promoProps.ts",
|
||||
"./types/components/selectRate/selectRate": "./lib/types/components/selectRate/selectRate.ts",
|
||||
"./types/stores/rates": "./lib/types/stores/rates.ts",
|
||||
"./types/stores/booking-confirmation": "./lib/types/stores/booking-confirmation.ts",
|
||||
"./utils/getRoomFeatureDescription": "./lib/utils/getRoomFeatureDescription.ts",
|
||||
"./utils/isSameBooking": "./lib/utils/isSameBooking.ts",
|
||||
"./utils/url": "./lib/utils/url.ts",
|
||||
"./utils/SelectRate": "./lib/utils/SelectRate/index.tsx",
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
},
|
||||
"exports": {
|
||||
"./constants/alert": "./constants/alert.ts",
|
||||
"./constants/booking": "./constants/booking.ts",
|
||||
"./constants/currency": "./constants/currency.ts",
|
||||
"./constants/dateFormats": "./constants/dateFormats.ts",
|
||||
"./constants/facilities": "./constants/facilities.ts",
|
||||
|
||||
Reference in New Issue
Block a user