Merged in feat/confirmation-page-initial-multiroom-display (pull request #1334)
feat: initial display of linkedReservations on confirmation page * feat: initial display of linkedReservations on confirmation page * refactor: move notFound Approved-by: Tobias Johansson
This commit is contained in:
@@ -43,7 +43,11 @@ export default function Confirmation({
|
|||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Rooms booking={booking} room={room} />
|
<Rooms
|
||||||
|
booking={booking}
|
||||||
|
mainRoom={room}
|
||||||
|
linkedReservations={booking.linkedReservations}
|
||||||
|
/>
|
||||||
<PaymentDetails booking={booking} />
|
<PaymentDetails booking={booking} />
|
||||||
<Divider color="primaryLightSubtle" />
|
<Divider color="primaryLightSubtle" />
|
||||||
<HotelDetails hotel={hotel} />
|
<HotelDetails hotel={hotel} />
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
"use client "
|
||||||
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
|
import { dt } from "@/lib/dt"
|
||||||
|
|
||||||
|
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||||
|
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||||
|
import useLang from "@/hooks/useLang"
|
||||||
|
|
||||||
|
import styles from "./linkedReservation.module.css"
|
||||||
|
|
||||||
|
import type { LinkedReservationSchema } from "@/types/components/hotelReservation/bookingConfirmation/rooms"
|
||||||
|
|
||||||
|
interface LinkedReservationProps {
|
||||||
|
linkedReservation: LinkedReservationSchema
|
||||||
|
roomIndex: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export function LinkedReservation({
|
||||||
|
linkedReservation,
|
||||||
|
roomIndex,
|
||||||
|
}: LinkedReservationProps) {
|
||||||
|
const intl = useIntl()
|
||||||
|
const lang = useLang()
|
||||||
|
const {
|
||||||
|
checkinDate,
|
||||||
|
checkoutDate,
|
||||||
|
confirmationNumber,
|
||||||
|
roomTypeCode,
|
||||||
|
adults,
|
||||||
|
children,
|
||||||
|
} = linkedReservation
|
||||||
|
|
||||||
|
const fromDate = dt(checkinDate).locale(lang)
|
||||||
|
const toDate = dt(checkoutDate).locale(lang)
|
||||||
|
return (
|
||||||
|
<div className={styles.reservation}>
|
||||||
|
<Subtitle color="uiTextHighContrast" type="two">
|
||||||
|
{intl.formatMessage(
|
||||||
|
{
|
||||||
|
id: "Room {roomIndex}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
roomIndex: roomIndex + 2,
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</Subtitle>
|
||||||
|
<ul className={styles.details}>
|
||||||
|
<li className={styles.listItem}>
|
||||||
|
<Body color="uiTextPlaceholder">
|
||||||
|
{intl.formatMessage({ id: "Booking number" })}
|
||||||
|
</Body>
|
||||||
|
<Body color="uiTextHighContrast">{confirmationNumber}</Body>
|
||||||
|
</li>
|
||||||
|
<li className={styles.listItem}>
|
||||||
|
<Body color="uiTextPlaceholder">
|
||||||
|
{intl.formatMessage({ id: "Check-in" })}
|
||||||
|
</Body>
|
||||||
|
<Body color="uiTextHighContrast">
|
||||||
|
{intl.formatMessage(
|
||||||
|
{ id: "{checkInDate} from {checkInTime}" },
|
||||||
|
{
|
||||||
|
checkInDate: fromDate.format("ddd, D MMM"),
|
||||||
|
checkInTime: fromDate.format("HH:mm"),
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</Body>
|
||||||
|
</li>
|
||||||
|
<li className={styles.listItem}>
|
||||||
|
<Body color="uiTextPlaceholder">
|
||||||
|
{intl.formatMessage({ id: "Check-out" })}
|
||||||
|
</Body>
|
||||||
|
<Body color="uiTextHighContrast">
|
||||||
|
{intl.formatMessage(
|
||||||
|
{ id: "{checkOutDate} from {checkOutTime}" },
|
||||||
|
{
|
||||||
|
checkOutDate: toDate.format("ddd, D MMM"),
|
||||||
|
checkOutTime: toDate.format("HH:mm"),
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</Body>
|
||||||
|
</li>
|
||||||
|
<li className={styles.listItem}>
|
||||||
|
<Body color="uiTextPlaceholder">
|
||||||
|
{intl.formatMessage({ id: "Adults" })}
|
||||||
|
</Body>
|
||||||
|
<Body color="uiTextHighContrast">{adults}</Body>
|
||||||
|
</li>
|
||||||
|
<li className={styles.listItem}>
|
||||||
|
<Body color="uiTextPlaceholder">
|
||||||
|
{intl.formatMessage({ id: "Children" })}
|
||||||
|
</Body>
|
||||||
|
<Body color="uiTextHighContrast">{children}</Body>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
.reservation {
|
||||||
|
background-color: var(--Base-Background-Primary-Normal);
|
||||||
|
border-radius: var(--Corner-radius-Large);
|
||||||
|
display: grid;
|
||||||
|
gap: var(--Spacing-x2);
|
||||||
|
padding: var(--Spacing-x2) var(--Spacing-x2) var(--Spacing-x3)
|
||||||
|
var(--Spacing-x2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.details {
|
||||||
|
display: grid;
|
||||||
|
gap: var(--Spacing-x-half) var(--Spacing-x3);
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.listItem {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--Spacing-x1);
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { notFound } from "next/navigation"
|
import { LinkedReservation } from "./LinkedReservation"
|
||||||
|
|
||||||
import Room from "./Room"
|
import Room from "./Room"
|
||||||
|
|
||||||
import styles from "./rooms.module.css"
|
import styles from "./rooms.module.css"
|
||||||
@@ -10,14 +9,23 @@ import type { BookingConfirmationRoomsProps } from "@/types/components/hotelRese
|
|||||||
|
|
||||||
export default function Rooms({
|
export default function Rooms({
|
||||||
booking,
|
booking,
|
||||||
room,
|
mainRoom,
|
||||||
|
linkedReservations,
|
||||||
}: BookingConfirmationRoomsProps) {
|
}: BookingConfirmationRoomsProps) {
|
||||||
if (!room) {
|
|
||||||
return notFound()
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<section className={styles.rooms}>
|
<section className={styles.rooms}>
|
||||||
<Room booking={booking} img={room.images[0]} roomName={room.name} />
|
<Room
|
||||||
|
booking={booking}
|
||||||
|
img={mainRoom.images[0]}
|
||||||
|
roomName={mainRoom.name}
|
||||||
|
/>
|
||||||
|
{linkedReservations?.map((reservation, idx) => (
|
||||||
|
<LinkedReservation
|
||||||
|
key={reservation.confirmationNumber}
|
||||||
|
linkedReservation={reservation}
|
||||||
|
roomIndex={idx}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { differenceInCalendarDays, format, isWeekend } from "date-fns"
|
import { differenceInCalendarDays, format, isWeekend } from "date-fns"
|
||||||
|
import { notFound } from "next/navigation"
|
||||||
import { Suspense } from "react"
|
import { Suspense } from "react"
|
||||||
|
|
||||||
import { getBookingConfirmation } from "@/lib/trpc/memoizedRequests"
|
import { getBookingConfirmation } from "@/lib/trpc/memoizedRequests"
|
||||||
@@ -24,7 +25,9 @@ export default async function BookingConfirmation({
|
|||||||
const lang = getLang()
|
const lang = getLang()
|
||||||
const { booking, hotel, room } =
|
const { booking, hotel, room } =
|
||||||
await getBookingConfirmation(confirmationNumber)
|
await getBookingConfirmation(confirmationNumber)
|
||||||
|
if (!room) {
|
||||||
|
return notFound()
|
||||||
|
}
|
||||||
const arrivalDate = new Date(booking.checkInDate)
|
const arrivalDate = new Date(booking.checkInDate)
|
||||||
const departureDate = new Date(booking.checkOutDate)
|
const departureDate = new Date(booking.checkOutDate)
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export async function MyStay({ reservationId }: { reservationId: string }) {
|
|||||||
<main className={styles.main}>
|
<main className={styles.main}>
|
||||||
<Header booking={booking} hotel={hotel} />
|
<Header booking={booking} hotel={hotel} />
|
||||||
<BookingActions />
|
<BookingActions />
|
||||||
<Rooms booking={booking} room={room} />
|
{room && <Rooms booking={booking} mainRoom={room} />}
|
||||||
<Ancillaries />
|
<Ancillaries />
|
||||||
<Divider color="primaryLightSubtle" />
|
<Divider color="primaryLightSubtle" />
|
||||||
<PaymentDetails booking={booking} />
|
<PaymentDetails booking={booking} />
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ const rateDefinitionSchema = z.object({
|
|||||||
title: z.string().nullable().default(""),
|
title: z.string().nullable().default(""),
|
||||||
})
|
})
|
||||||
|
|
||||||
const linkedReservationsSchema = z.object({
|
export const linkedReservationsSchema = z.object({
|
||||||
confirmationNumber: z.string().default(""),
|
confirmationNumber: z.string().default(""),
|
||||||
hotelId: z.string().default(""),
|
hotelId: z.string().default(""),
|
||||||
checkinDate: z.string(),
|
checkinDate: z.string(),
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
|
import type { Room } from "@/types/hotel"
|
||||||
import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation"
|
import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation"
|
||||||
|
|
||||||
export interface BookingConfirmationProps {
|
export interface BookingConfirmationProps {
|
||||||
confirmationNumber: string
|
confirmationNumber: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ConfirmationProps extends BookingConfirmation {}
|
export interface ConfirmationProps extends BookingConfirmation {
|
||||||
|
room: Room & {
|
||||||
|
bedType: Room["roomTypes"][number]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,16 @@
|
|||||||
|
import type { z } from "zod"
|
||||||
|
|
||||||
|
import type { Room } from "@/types/hotel"
|
||||||
import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation"
|
import type { BookingConfirmation } from "@/types/trpc/routers/booking/confirmation"
|
||||||
|
import type { linkedReservationsSchema } from "@/server/routers/booking/output"
|
||||||
|
|
||||||
|
export interface LinkedReservationSchema
|
||||||
|
extends z.output<typeof linkedReservationsSchema> {}
|
||||||
|
|
||||||
export interface BookingConfirmationRoomsProps
|
export interface BookingConfirmationRoomsProps
|
||||||
extends Pick<BookingConfirmation, "booking" | "room"> {}
|
extends Pick<BookingConfirmation, "booking"> {
|
||||||
|
mainRoom: Room & {
|
||||||
|
bedType: Room["roomTypes"][number]
|
||||||
|
}
|
||||||
|
linkedReservations?: LinkedReservationSchema[]
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user