Merged in revert-pr-1925 (pull request #1927)
Revert "Feat/sw 2323 find booking (pull request #1925)" Approved-by: Anton Gunnarsson
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
.main {
|
||||
background-color: var(--Base-Surface-Primary-light-Normal);
|
||||
display: grid;
|
||||
gap: var(--Spacing-x5);
|
||||
grid-template-areas: "header" "booking";
|
||||
margin: 0 auto;
|
||||
min-height: 100dvh;
|
||||
padding-top: var(--Spacing-x5);
|
||||
width: var(--max-width-page);
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1367px) {
|
||||
.main {
|
||||
grid-template-areas:
|
||||
"header receipt"
|
||||
"booking receipt";
|
||||
grid-template-columns: 1fr 340px;
|
||||
grid-template-rows: auto 1fr;
|
||||
padding-top: var(--Spacing-x9);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
"use client"
|
||||
import { useRef } from "react"
|
||||
|
||||
import Header from "@/components/HotelReservation/BookingConfirmation/Header"
|
||||
|
||||
import styles from "./confirmation.module.css"
|
||||
|
||||
import type { ConfirmationProps } from "@/types/components/hotelReservation/bookingConfirmation/bookingConfirmation"
|
||||
|
||||
export default function Confirmation({
|
||||
booking,
|
||||
hotel,
|
||||
children,
|
||||
refId,
|
||||
}: React.PropsWithChildren<ConfirmationProps>) {
|
||||
const mainRef = useRef<HTMLElement | null>(null)
|
||||
|
||||
return (
|
||||
<main className={styles.main} ref={mainRef}>
|
||||
<Header booking={booking} hotel={hotel} mainRef={mainRef} refId={refId} />
|
||||
{children}
|
||||
</main>
|
||||
)
|
||||
}
|
||||
@@ -1,22 +1,15 @@
|
||||
"use client"
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
|
||||
import { myStay } from "@/constants/routes/myStay"
|
||||
|
||||
import Button from "@/components/TempDesignSystem/Button"
|
||||
import Link from "@/components/TempDesignSystem/Link"
|
||||
import useLang from "@/hooks/useLang"
|
||||
|
||||
import type { ManageBookingProps } from "@/types/components/hotelReservation/bookingConfirmation/actions/manageBooking"
|
||||
|
||||
export default function ManageBooking({ refId }: ManageBookingProps) {
|
||||
export default function ManageBooking({ bookingUrl }: ManageBookingProps) {
|
||||
const intl = useIntl()
|
||||
const lang = useLang()
|
||||
|
||||
const bookingUrl = `${myStay[lang]}?RefId=${refId}`
|
||||
|
||||
return (
|
||||
<Button
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
"use client"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { myStay } from "@/constants/routes/myStay"
|
||||
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
import Title from "@/components/TempDesignSystem/Text/Title"
|
||||
import useLang from "@/hooks/useLang"
|
||||
|
||||
import AddToCalendar from "../../AddToCalendar"
|
||||
import AddToCalendarButton from "./Actions/AddToCalendarButton"
|
||||
// import DownloadInvoice from "./Actions/DownloadInvoice"
|
||||
import { generateDateTime } from "./Actions/helpers"
|
||||
import ManageBooking from "./Actions/ManageBooking"
|
||||
|
||||
@@ -18,9 +22,11 @@ import type { BookingConfirmationHeaderProps } from "@/types/components/hotelRes
|
||||
export default function Header({
|
||||
booking,
|
||||
hotel,
|
||||
// mainRef,
|
||||
refId,
|
||||
}: BookingConfirmationHeaderProps) {
|
||||
const intl = useIntl()
|
||||
const lang = useLang()
|
||||
|
||||
const text = intl.formatMessage({
|
||||
defaultMessage:
|
||||
@@ -46,6 +52,8 @@ export default function Header({
|
||||
url: hotel.contactInformation.websiteUrl,
|
||||
}
|
||||
|
||||
const bookingUrlPath = `${myStay[lang]}?RefId=${refId}`
|
||||
|
||||
return (
|
||||
<header className={styles.header}>
|
||||
<hgroup className={styles.hgroup}>
|
||||
@@ -66,7 +74,9 @@ export default function Header({
|
||||
hotelName={hotel.name}
|
||||
renderButton={(onPress) => <AddToCalendarButton onPress={onPress} />}
|
||||
/>
|
||||
<ManageBooking refId={refId} />
|
||||
<ManageBooking bookingUrl={bookingUrlPath} />
|
||||
{/* Download Invoice will be added later (currently available on My Stay) */}
|
||||
{/* <DownloadInvoice mainRef={mainRef} /> */}
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
"use client"
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { myStay } from "@/constants/routes/myStay"
|
||||
import { homeHrefs } from "@/constants/homeHrefs"
|
||||
import { myBooking } from "@/constants/myBooking"
|
||||
import { env } from "@/env/client"
|
||||
|
||||
import useLang from "@/hooks/useLang"
|
||||
|
||||
@@ -12,17 +13,22 @@ import styles from "./promos.module.css"
|
||||
|
||||
import type { PromosProps } from "@/types/components/hotelReservation/bookingConfirmation/promos"
|
||||
|
||||
export default function Promos({ refId, hotelId }: PromosProps) {
|
||||
export default function Promos({
|
||||
confirmationNumber,
|
||||
hotelId,
|
||||
lastName,
|
||||
}: PromosProps) {
|
||||
const intl = useIntl()
|
||||
const lang = useLang()
|
||||
|
||||
const homeUrl = homeHrefs[env.NEXT_PUBLIC_NODE_ENV][lang]
|
||||
const myBookingUrl = myBooking[env.NEXT_PUBLIC_NODE_ENV][lang]
|
||||
return (
|
||||
<div className={styles.promos}>
|
||||
<Promo
|
||||
buttonText={intl.formatMessage({
|
||||
defaultMessage: "View and buy add-ons",
|
||||
})}
|
||||
href={`${myStay[lang]}?RefId=${refId}`}
|
||||
href={`${myBookingUrl}?bookingId=${confirmationNumber}&lastName=${lastName}`}
|
||||
text={intl.formatMessage({
|
||||
defaultMessage:
|
||||
"Discover the little extra touches to make your upcoming stay even more unforgettable.",
|
||||
@@ -35,7 +41,7 @@ export default function Promos({ refId, hotelId }: PromosProps) {
|
||||
buttonText={intl.formatMessage({
|
||||
defaultMessage: "Book another stay",
|
||||
})}
|
||||
href={`/${lang}?hotel=${hotelId}`}
|
||||
href={`${homeUrl}?hotel=${hotelId}`}
|
||||
text={intl.formatMessage({
|
||||
defaultMessage:
|
||||
"Get inspired and start dreaming beyond your next trip. Explore more Scandic destinations.",
|
||||
|
||||
@@ -20,16 +20,14 @@ import { CurrencyEnum } from "@/types/enums/currency"
|
||||
export function LinkedReservation({
|
||||
checkInTime,
|
||||
checkOutTime,
|
||||
refId,
|
||||
confirmationNumber,
|
||||
roomIndex,
|
||||
}: LinkedReservationProps) {
|
||||
const lang = useLang()
|
||||
|
||||
const { data, refetch, isLoading } = trpc.booking.confirmation.useQuery({
|
||||
refId,
|
||||
const { data, refetch, isLoading } = trpc.booking.get.useQuery({
|
||||
confirmationNumber,
|
||||
lang,
|
||||
})
|
||||
|
||||
const {
|
||||
setRoom,
|
||||
setFormattedTotalCost,
|
||||
@@ -43,7 +41,6 @@ export function LinkedReservation({
|
||||
totalBookingPrice: state.totalBookingPrice,
|
||||
totalBookingCheques: state.totalBookingCheques,
|
||||
}))
|
||||
|
||||
const intl = useIntl()
|
||||
|
||||
useEffect(() => {
|
||||
@@ -82,20 +79,13 @@ export function LinkedReservation({
|
||||
return <Retry handleRefetch={refetch} />
|
||||
}
|
||||
|
||||
const { booking, room } = data
|
||||
|
||||
return (
|
||||
<Room
|
||||
checkInDate={booking.checkInDate}
|
||||
checkOutDate={booking.checkOutDate}
|
||||
booking={data.booking}
|
||||
checkInTime={checkInTime}
|
||||
checkOutTime={checkOutTime}
|
||||
confirmationNumber={booking.confirmationNumber}
|
||||
guaranteeInfo={booking.guaranteeInfo}
|
||||
guest={booking.guest}
|
||||
img={room.images[0]}
|
||||
rateDefinition={booking.rateDefinition}
|
||||
roomName={room.name}
|
||||
img={data.room.images[0]}
|
||||
roomName={data.room.name}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -20,28 +20,24 @@ import styles from "./room.module.css"
|
||||
import type { RoomProps } from "@/types/components/hotelReservation/bookingConfirmation/rooms/room"
|
||||
|
||||
export default function Room({
|
||||
checkInDate,
|
||||
checkOutDate,
|
||||
booking,
|
||||
checkInTime,
|
||||
checkOutTime,
|
||||
confirmationNumber,
|
||||
guaranteeInfo,
|
||||
guest,
|
||||
img,
|
||||
rateDefinition,
|
||||
roomName,
|
||||
}: RoomProps) {
|
||||
const intl = useIntl()
|
||||
const lang = useLang()
|
||||
|
||||
const guestName = `${guest.firstName} ${guest.lastName}`
|
||||
const fromDate = dt(checkInDate).locale(lang)
|
||||
const toDate = dt(checkOutDate).locale(lang)
|
||||
const guestName = `${booking.guest.firstName} ${booking.guest.lastName}`
|
||||
const fromDate = dt(booking.checkInDate).locale(lang)
|
||||
const toDate = dt(booking.checkOutDate).locale(lang)
|
||||
|
||||
const isFlexBooking =
|
||||
rateDefinition.cancellationRule ===
|
||||
booking.rateDefinition.cancellationRule ===
|
||||
CancellationRuleEnum.CancellableBefore6PM
|
||||
const isChangeBooking =
|
||||
rateDefinition.cancellationRule === CancellationRuleEnum.Changeable
|
||||
booking.rateDefinition.cancellationRule === CancellationRuleEnum.Changeable
|
||||
return (
|
||||
<article className={styles.room}>
|
||||
<header className={styles.header}>
|
||||
@@ -51,11 +47,11 @@ export default function Room({
|
||||
{
|
||||
defaultMessage: "Booking number {value}",
|
||||
},
|
||||
{ value: confirmationNumber }
|
||||
{ value: booking.confirmationNumber }
|
||||
)}
|
||||
</h2>
|
||||
</Typography>
|
||||
{rateDefinition.isMemberRate ? (
|
||||
{booking.rateDefinition.isMemberRate ? (
|
||||
<div className={styles.benefits}>
|
||||
<>
|
||||
<MaterialIcon
|
||||
@@ -71,7 +67,7 @@ export default function Room({
|
||||
</>
|
||||
</div>
|
||||
) : null}
|
||||
{guaranteeInfo && (
|
||||
{booking.guaranteeInfo && (
|
||||
<div className={styles.benefits}>
|
||||
<MaterialIcon
|
||||
icon="check_circle"
|
||||
@@ -172,7 +168,7 @@ export default function Room({
|
||||
})}
|
||||
</Body>
|
||||
<Body color="uiTextHighContrast">
|
||||
{rateDefinition.cancellationText}
|
||||
{booking.rateDefinition.cancellationText}
|
||||
</Body>
|
||||
</li>
|
||||
{isFlexBooking || isChangeBooking ? (
|
||||
@@ -200,23 +196,25 @@ export default function Room({
|
||||
})}
|
||||
</Body>
|
||||
<Body color="uiTextHighContrast">{guestName}</Body>
|
||||
{guest.membershipNumber ? (
|
||||
{booking.guest.membershipNumber ? (
|
||||
<Body color="uiTextHighContrast">
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Friend no. {value}",
|
||||
},
|
||||
{
|
||||
value: guest.membershipNumber,
|
||||
value: booking.guest.membershipNumber,
|
||||
}
|
||||
)}
|
||||
</Body>
|
||||
) : null}
|
||||
{guest.phoneNumber ? (
|
||||
<Body color="uiTextHighContrast">{guest.phoneNumber}</Body>
|
||||
{booking.guest.phoneNumber ? (
|
||||
<Body color="uiTextHighContrast">
|
||||
{booking.guest.phoneNumber}
|
||||
</Body>
|
||||
) : null}
|
||||
{guest.email ? (
|
||||
<Body color="uiTextHighContrast">{guest.email}</Body>
|
||||
{booking.guest.email ? (
|
||||
<Body color="uiTextHighContrast">{booking.guest.email}</Body>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,56 +9,55 @@ import styles from "./rooms.module.css"
|
||||
|
||||
import type { BookingConfirmationRoomsProps } from "@/types/components/hotelReservation/bookingConfirmation/rooms"
|
||||
|
||||
async function RoomTitle({ nr }: { nr: number }) {
|
||||
const intl = await getIntl()
|
||||
|
||||
return (
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<h2 className={styles.roomTitle}>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Room {roomIndex}",
|
||||
},
|
||||
{ roomIndex: nr }
|
||||
)}
|
||||
</h2>
|
||||
</Typography>
|
||||
)
|
||||
}
|
||||
|
||||
export default async function Rooms({
|
||||
booking,
|
||||
checkInTime,
|
||||
checkOutTime,
|
||||
mainRoom,
|
||||
linkedReservations,
|
||||
}: BookingConfirmationRoomsProps) {
|
||||
const { linkedReservations } = booking
|
||||
const intl = await getIntl()
|
||||
|
||||
return (
|
||||
<section className={styles.rooms}>
|
||||
<div className={styles.room}>
|
||||
{linkedReservations.length ? <RoomTitle nr={1} /> : null}
|
||||
{linkedReservations.length ? (
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<h2 className={styles.roomTitle}>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Room {roomIndex}",
|
||||
},
|
||||
{ roomIndex: 1 }
|
||||
)}
|
||||
</h2>
|
||||
</Typography>
|
||||
) : null}
|
||||
<Room
|
||||
checkInDate={booking.checkInDate}
|
||||
checkOutDate={booking.checkOutDate}
|
||||
booking={booking}
|
||||
checkInTime={checkInTime}
|
||||
checkOutTime={checkOutTime}
|
||||
confirmationNumber={booking.confirmationNumber}
|
||||
guaranteeInfo={booking.guaranteeInfo}
|
||||
guest={booking.guest}
|
||||
img={mainRoom.images[0]}
|
||||
rateDefinition={booking.rateDefinition}
|
||||
roomName={mainRoom.name}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{linkedReservations.map((reservation, idx) => (
|
||||
<div className={styles.room} key={reservation.confirmationNumber}>
|
||||
<RoomTitle nr={idx + 2} />
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<h2 className={styles.roomTitle}>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Room {roomIndex}",
|
||||
},
|
||||
{ roomIndex: idx + 2 }
|
||||
)}
|
||||
</h2>
|
||||
</Typography>
|
||||
<LinkedReservation
|
||||
checkInTime={checkInTime}
|
||||
checkOutTime={checkOutTime}
|
||||
refId={reservation.refId}
|
||||
confirmationNumber={reservation.confirmationNumber}
|
||||
roomIndex={idx + 1}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -27,7 +27,7 @@ export default function Tracking({
|
||||
getTracking(
|
||||
lang,
|
||||
bookingConfirmation.booking,
|
||||
bookingConfirmation.hotelData.hotel,
|
||||
bookingConfirmation.hotel,
|
||||
rooms
|
||||
)
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ function mapAncillaryPackage(
|
||||
export function getTracking(
|
||||
lang: Lang,
|
||||
booking: BookingConfirmation["booking"],
|
||||
hotel: BookingConfirmation["hotelData"]["hotel"],
|
||||
hotel: BookingConfirmation["hotel"],
|
||||
rooms: Room[]
|
||||
) {
|
||||
const arrivalDate = new Date(booking.checkInDate)
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
.booking {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Spacing-x5);
|
||||
grid-area: booking;
|
||||
padding-bottom: var(--Spacing-x9);
|
||||
}
|
||||
|
||||
.aside {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1367px) {
|
||||
.mobileReceipt {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.aside {
|
||||
display: grid;
|
||||
grid-area: receipt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
import { notFound } from "next/navigation"
|
||||
|
||||
import { getBookingConfirmation } from "@/lib/trpc/memoizedRequests"
|
||||
import { encrypt } from "@/server/routers/utils/encryption"
|
||||
|
||||
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 Divider from "@/components/TempDesignSystem/Divider"
|
||||
import { getIntl } from "@/i18n"
|
||||
import BookingConfirmationProvider from "@/providers/BookingConfirmationProvider"
|
||||
|
||||
import Alerts from "./Alerts"
|
||||
import Confirmation from "./Confirmation"
|
||||
import Tracking from "./Tracking"
|
||||
import { mapRoomState } from "./utils"
|
||||
|
||||
import styles from "./bookingConfirmation.module.css"
|
||||
|
||||
import type { BookingConfirmationProps } from "@/types/components/hotelReservation/bookingConfirmation/bookingConfirmation"
|
||||
|
||||
export default async function BookingConfirmation({
|
||||
confirmationNumber,
|
||||
}: BookingConfirmationProps) {
|
||||
const bookingConfirmation = await getBookingConfirmation(confirmationNumber)
|
||||
|
||||
if (!bookingConfirmation) {
|
||||
return notFound()
|
||||
}
|
||||
const { booking, hotel, room } = bookingConfirmation
|
||||
if (!room) {
|
||||
return notFound()
|
||||
}
|
||||
|
||||
const refId = encrypt(
|
||||
`${booking.confirmationNumber},${booking.guest.lastName}`
|
||||
)
|
||||
|
||||
const intl = await getIntl()
|
||||
return (
|
||||
<BookingConfirmationProvider
|
||||
bookingCode={booking.bookingCode}
|
||||
currencyCode={booking.currencyCode}
|
||||
fromDate={booking.checkInDate}
|
||||
toDate={booking.checkOutDate}
|
||||
rooms={[
|
||||
mapRoomState(booking, room, intl),
|
||||
// null represents "known but not yet fetched rooms" and is used to render placeholders correctly
|
||||
...Array(booking.linkedReservations.length).fill(null),
|
||||
]}
|
||||
vat={booking.vatPercentage}
|
||||
>
|
||||
<Confirmation booking={booking} hotel={hotel} room={room} refId={refId}>
|
||||
<div className={styles.booking}>
|
||||
<Alerts booking={booking} />
|
||||
<Rooms
|
||||
booking={booking}
|
||||
checkInTime={hotel.hotelFacts.checkin.checkInTime}
|
||||
checkOutTime={hotel.hotelFacts.checkin.checkOutTime}
|
||||
mainRoom={room}
|
||||
linkedReservations={booking.linkedReservations}
|
||||
/>
|
||||
<PaymentDetails />
|
||||
<Divider color="primaryLightSubtle" />
|
||||
<HotelDetails hotel={hotel} />
|
||||
<Promos
|
||||
confirmationNumber={booking.confirmationNumber}
|
||||
hotelId={hotel.operaId}
|
||||
lastName={booking.guest.lastName}
|
||||
/>
|
||||
<div className={styles.mobileReceipt}>
|
||||
<Receipt />
|
||||
</div>
|
||||
</div>
|
||||
<aside className={styles.aside}>
|
||||
<SidePanel variant="receipt">
|
||||
<Receipt />
|
||||
</SidePanel>
|
||||
</aside>
|
||||
</Confirmation>
|
||||
<Tracking bookingConfirmation={bookingConfirmation} />
|
||||
</BookingConfirmationProvider>
|
||||
)
|
||||
}
|
||||
@@ -5,10 +5,10 @@ import type { IntlShape } from "react-intl"
|
||||
import type { BookingConfirmationRoom } from "@/types/components/hotelReservation/bookingConfirmation/bookingConfirmation"
|
||||
import { BreakfastPackageEnum } from "@/types/enums/breakfast"
|
||||
import { CurrencyEnum } from "@/types/enums/currency"
|
||||
import type { BookingSchema } from "@/types/trpc/routers/booking/confirmation"
|
||||
import type { BookingConfirmationSchema } from "@/types/trpc/routers/booking/confirmation"
|
||||
|
||||
export function mapRoomState(
|
||||
booking: BookingSchema,
|
||||
booking: BookingConfirmationSchema,
|
||||
room: BookingConfirmationRoom,
|
||||
intl: IntlShape
|
||||
) {
|
||||
|
||||
Reference in New Issue
Block a user