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

@@ -1,61 +1,49 @@
import { dt } from "@/lib/dt"
import { serverClient } from "@/lib/trpc/server"
"use client"
import { useIntl } from "react-intl"
import { useBookingConfirmationStore } from "@/stores/booking-confirmation"
import { CreditCardAddIcon } from "@/components/Icons"
import SkeletonShimmer from "@/components/SkeletonShimmer"
import Button from "@/components/TempDesignSystem/Button"
import Body from "@/components/TempDesignSystem/Text/Body"
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import { getIntl } from "@/i18n"
import { getLang } from "@/i18n/serverContext"
import { formatPrice } from "@/utils/numberFormatting"
import styles from "./paymentDetails.module.css"
import type { BookingConfirmationPaymentDetailsProps } from "@/types/components/hotelReservation/bookingConfirmation/paymentDetails"
export default function PaymentDetails() {
const intl = useIntl()
export default async function PaymentDetails({
booking,
}: BookingConfirmationPaymentDetailsProps) {
const intl = await getIntl()
const lang = getLang()
const linkedReservations = await Promise.all(
// TODO: How to handle partial failure (e.g. one booking can't be fetched)? Need UX/UI
booking.linkedReservations.map(async (res) => {
const confirmation = await serverClient().booking.confirmation({
confirmationNumber: res.confirmationNumber,
})
return confirmation
})
const rooms = useBookingConfirmationStore((state) => state.rooms)
const currencyCode = useBookingConfirmationStore(
(state) => state.currencyCode
)
const grandTotal = linkedReservations.reduce((acc, res) => {
return res ? acc + res.booking.totalPrice : acc
}, booking.totalPrice)
const hasAllRoomsLoaded = rooms.every((room) => room)
const grandTotal = rooms.reduce((acc, room) => {
const reservationTotalPrice = room?.totalPrice || 0
return acc + reservationTotalPrice
}, 0)
return (
<div className={styles.details}>
<Subtitle color="uiTextHighContrast" type="two">
{intl.formatMessage({ id: "Payment details" })}
</Subtitle>
<div className={styles.payment}>
<Body color="uiTextHighContrast">
{intl.formatMessage(
{ id: "{amount} has been paid" },
{
amount: formatPrice(intl, grandTotal, booking.currencyCode),
}
)}
</Body>
<Body color="uiTextHighContrast">
{dt(booking.createDateTime)
.locale(lang)
.format("ddd D MMM YYYY, hh:mm")}
</Body>
<Body color="uiTextHighContrast">
{intl.formatMessage(
{ id: "{card} ending with {cardno}" },
{ card: "N/A", cardno: "N/A" }
)}
</Body>
{hasAllRoomsLoaded ? (
<Body color="uiTextHighContrast">
{intl.formatMessage(
{ id: "{amount} has been paid" },
{
amount: formatPrice(intl, grandTotal, currencyCode),
}
)}
</Body>
) : (
<SkeletonShimmer width={"100%"} />
)}
</div>
<Button
className={styles.btn}

View File

@@ -6,6 +6,7 @@
.details {
gap: var(--Spacing-x-one-and-half);
max-width: fit-content;
}
.payment {