Merged in feat/SW-1652-confirmation-page (pull request #1483)

Feat/SW-1652 confirmation page

* feat(SW-1652): handle linkedReservations fetching

* fix: add missing translations

* feat: add linkedReservation retry functionality

* chore: align naming


Approved-by: Simon.Emanuelsson
This commit is contained in:
Arvid Norlin
2025-03-07 12:47:04 +00:00
parent 7fa86a2077
commit ec60e9abdd
34 changed files with 474 additions and 303 deletions

View File

@@ -0,0 +1,23 @@
"use client"
import { useIntl } from "react-intl"
import Button from "@/components/TempDesignSystem/Button"
import Body from "@/components/TempDesignSystem/Text/Body"
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({ id: "Something went wrong!" })}</Body>
<Button size={"small"} onPress={handleRefetch}>
{intl.formatMessage({ id: "Try again" })}
</Button>
</div>
)
}

View File

@@ -1,22 +1,50 @@
import { serverClient } from "@/lib/trpc/server"
"use client"
import { useEffect } from "react"
import { trpc } from "@/lib/trpc/client"
import { useBookingConfirmationStore } from "@/stores/booking-confirmation"
import useLang from "@/hooks/useLang"
import { mapRoomState } from "../../utils"
import Room from "../Room"
import { LinkedReservationCardSkeleton } from "./LinkedReservationCardSkeleton"
import Retry from "./Retry"
export async function LinkedReservation({
import type { LinkedReservationProps } from "@/types/components/hotelReservation/bookingConfirmation/rooms/linkedReservation"
export function LinkedReservation({
confirmationNumber,
}: {
confirmationNumber: string
}) {
const confirmation = await serverClient().booking.confirmation({
roomIndex,
}: LinkedReservationProps) {
const lang = useLang()
const { data, refetch, isLoading } = trpc.booking.confirmation.useQuery({
confirmationNumber,
lang,
})
const setRoom = useBookingConfirmationStore((state) => state.actions.setRoom)
const room = confirmation?.room
const booking = confirmation?.booking
useEffect(() => {
if (data?.room) {
const roomData = mapRoomState(data.booking, data.room)
setRoom(roomData, roomIndex)
}
}, [data, roomIndex, setRoom])
if (!booking || !room) {
return <div>Something went wrong, try again</div>
if (isLoading) {
return <LinkedReservationCardSkeleton />
}
return <Room booking={booking} img={room.images[0]} roomName={room.name} />
if (!data?.room) {
return <Retry handleRefetch={refetch} />
}
return (
<Room
img={data.room.images[0]}
booking={data.booking}
roomName={data.room.name}
/>
)
}

View File

@@ -0,0 +1,10 @@
.retry {
background-color: var(--Base-Background-Primary-Normal);
border-radius: var(--Corner-radius-Large);
display: flex;
flex-direction: column;
gap: var(--Spacing-x2);
padding: var(--Spacing-x2) var(--Spacing-x2) var(--Spacing-x3)
var(--Spacing-x2);
align-items: center;
}

View File

@@ -2,6 +2,7 @@
import { useIntl } from "react-intl"
import { CancellationRuleEnum } from "@/constants/booking"
import { dt } from "@/lib/dt"
import {
@@ -27,6 +28,12 @@ export default function Room({ booking, img, roomName }: RoomProps) {
const guestName = `${booking.guest.firstName} ${booking.guest.lastName}`
const fromDate = dt(booking.checkInDate).locale(lang)
const toDate = dt(booking.checkOutDate).locale(lang)
const isFlexBooking =
booking.rateDefinition.cancellationRule ===
CancellationRuleEnum.CancellableBefore6PM
const isChangeBooking =
booking.rateDefinition.cancellationRule === CancellationRuleEnum.Changeable
return (
<article className={styles.room}>
<header className={styles.header}>
@@ -98,14 +105,6 @@ export default function Room({ booking, img, roomName }: RoomProps) {
)}
</Body>
</li>
<li className={styles.listItem}>
<Body color="uiTextPlaceholder">
{intl.formatMessage({ id: "Breakfast" })}
</Body>
<Body color="uiTextHighContrast">
{intl.formatMessage({ id: "N/A" })}
</Body>
</li>
<li className={styles.listItem}>
<Body color="uiTextPlaceholder">
{intl.formatMessage({ id: "Cancellation policy" })}
@@ -114,14 +113,19 @@ export default function Room({ booking, img, roomName }: RoomProps) {
{booking.rateDefinition.cancellationText}
</Body>
</li>
<li className={styles.listItem}>
<Body color="uiTextPlaceholder">
{intl.formatMessage({ id: "Rebooking" })}
</Body>
<Body color="uiTextHighContrast">
{intl.formatMessage({ id: "N/A" })}
</Body>
</li>
{isFlexBooking || isChangeBooking ? (
<li className={styles.listItem}>
<Body color="uiTextPlaceholder">
{intl.formatMessage({ id: "Rebooking" })}
</Body>
<Body color="uiTextHighContrast">
{intl.formatMessage(
{ id: "Until {time}, {date}" },
{ time: "18:00", date: fromDate.format("dddd D MMM") }
)}
</Body>
</li>
) : null}
</ul>
<div className={styles.guest}>
<Body color="uiTextPlaceholder">

View File

@@ -1,9 +1,6 @@
import { Suspense } from "react"
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import { getIntl } from "@/i18n"
import { LinkedReservationCardSkeleton } from "./LinkedReservation/LinkedReservationCardSkeleton"
import { LinkedReservation } from "./LinkedReservation"
import Room from "./Room"
@@ -17,6 +14,7 @@ export default async function Rooms({
linkedReservations,
}: BookingConfirmationRoomsProps) {
const intl = await getIntl()
return (
<section className={styles.rooms}>
<div className={styles.room}>
@@ -40,11 +38,10 @@ export default async function Rooms({
{ roomIndex: idx + 2 }
)}
</Subtitle>
<Suspense fallback={<LinkedReservationCardSkeleton />}>
<LinkedReservation
confirmationNumber={reservation.confirmationNumber}
/>
</Suspense>
<LinkedReservation
confirmationNumber={reservation.confirmationNumber}
roomIndex={idx + 1}
/>
</div>
))}
</section>