Files
web/app/[lang]/(live)/(public)/hotelreservation/(confirmation)/booking-confirmation/page.tsx
Tobias Johansson 025c5c8291 Merged in feat/SW-659-payment-send-query-params (pull request #727)
feat(SW-659): Receive query params from Planet callbacks

* feat(SW-659): read confirmation number from url and update callback url if dev

* fix(SW-659): moved callback url into env variable


Approved-by: Simon.Emanuelsson
2024-10-23 11:51:44 +00:00

282 lines
9.4 KiB
TypeScript

import { dt } from "@/lib/dt"
import { serverClient } from "@/lib/trpc/server"
import {
CalendarIcon,
DownloadIcon,
ImageIcon,
PrinterIcon,
} from "@/components/Icons"
import Button from "@/components/TempDesignSystem/Button"
import Divider from "@/components/TempDesignSystem/Divider"
import Link from "@/components/TempDesignSystem/Link"
import Body from "@/components/TempDesignSystem/Text/Body"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
import Title from "@/components/TempDesignSystem/Text/Title"
import { getIntl } from "@/i18n"
import styles from "./page.module.css"
import type { LangParams, PageArgs } from "@/types/params"
export default async function BookingConfirmationPage({
params,
searchParams,
}: PageArgs<LangParams, { confirmationNumber: string }>) {
const confirmationNumber = searchParams.confirmationNumber
const booking = await serverClient().booking.confirmation({
confirmationNumber,
})
if (!booking) {
return null
}
const intl = await getIntl()
const text = intl.formatMessage<React.ReactNode>(
{ id: "booking.confirmation.text" },
{
emailLink: (str) => (
<Link color="burgundy" href="#" textDecoration="underline">
{str}
</Link>
),
}
)
const fromDate = dt(booking.temp.fromDate).locale(params.lang)
const toDate = dt(booking.temp.toDate).locale(params.lang)
const nights = intl.formatMessage(
{ id: "booking.nights" },
{
totalNights: dt(toDate.format("YYYY-MM-DD")).diff(
dt(fromDate.format("YYYY-MM-DD")),
"days"
),
}
)
return (
<main className={styles.main}>
<header className={styles.header}>
<hgroup className={styles.hgroup}>
<Title
as="h4"
color="red"
textAlign="center"
textTransform="regular"
type="h2"
>
{intl.formatMessage({ id: "booking.confirmation.title" })}
</Title>
<Title
as="h4"
color="burgundy"
textAlign="center"
textTransform="regular"
type="h1"
>
{booking.hotel.name}
</Title>
</hgroup>
<Body className={styles.body} textAlign="center">
{text}
</Body>
</header>
<section className={styles.section}>
<div className={styles.booking}>
<article className={styles.details}>
<header>
<Subtitle color="burgundy" type="two">
{intl.formatMessage(
{ id: "Reference #{bookingNr}" },
{ bookingNr: "A92320VV" }
)}
</Subtitle>
</header>
<ul className={styles.list}>
<li className={styles.listItem}>
<Body>{intl.formatMessage({ id: "Check-in" })}</Body>
<Body>
{`${fromDate.format("ddd, D MMM")} ${intl.formatMessage({ id: "from" })} ${fromDate.format("HH:mm")}`}
</Body>
</li>
<li className={styles.listItem}>
<Body>{intl.formatMessage({ id: "Check-out" })}</Body>
<Body>
{`${toDate.format("ddd, D MMM")} ${intl.formatMessage({ id: "from" })} ${toDate.format("HH:mm")}`}
</Body>
</li>
<li className={styles.listItem}>
<Body>{intl.formatMessage({ id: "Breakfast" })}</Body>
<Body>
{booking.temp.breakfastFrom} - {booking.temp.breakfastTo}
</Body>
</li>
<li className={styles.listItem}>
<Body>{intl.formatMessage({ id: "Cancellation policy" })}</Body>
<Body>
{intl.formatMessage({ id: booking.temp.cancelPolicy })}
</Body>
</li>
<li className={styles.listItem}>
<Body>{intl.formatMessage({ id: "Rebooking" })}</Body>
<Body>{`${intl.formatMessage({ id: "Free until" })} ${fromDate.subtract(3, "day").format("ddd, D MMM")}`}</Body>
</li>
</ul>
</article>
<aside className={styles.tempImage}>
<ImageIcon height={80} width={80} />
</aside>
<div className={styles.actions}>
<Button
intent="text"
size="small"
theme="base"
variant="icon"
wrapping
>
<CalendarIcon />
{intl.formatMessage({ id: "Add to calendar" })}
</Button>
<Button
intent="text"
size="small"
theme="base"
variant="icon"
wrapping
>
<PrinterIcon />
{intl.formatMessage({ id: "Print confirmation" })}
</Button>
<Button
intent="text"
size="small"
theme="base"
variant="icon"
wrapping
>
<DownloadIcon />
{intl.formatMessage({ id: "Download invoice" })}
</Button>
</div>
</div>
<div className={styles.summary}>
<div className={styles.guest}>
<Caption color="uiTextPlaceholder">
{intl.formatMessage({ id: "Guest" })}
</Caption>
<div>
<Body color="burgundy" textTransform="bold">
{`${booking.guest.firstName} ${booking.guest.lastName}${booking.guest.memberbershipNumber ? ` (${intl.formatMessage({ id: "member no" })} ${booking.guest.memberbershipNumber})` : ""}`}
</Body>
<Body color="uiTextHighContrast">{booking.guest.email}</Body>
<Body color="uiTextHighContrast">
{booking.guest.phoneNumber}
</Body>
</div>
</div>
<div className={styles.hotel}>
<Caption color="uiTextPlaceholder">
{intl.formatMessage({ id: "Your hotel" })}
</Caption>
<div>
<Body color="burgundy" textTransform="bold">
{booking.hotel.name}
</Body>
<Body color="uiTextHighContrast">{booking.hotel.email}</Body>
<Body color="uiTextHighContrast">
{booking.hotel.phoneNumber}
</Body>
</div>
</div>
<Divider className={styles.divider} color="primaryLightSubtle" />
<div className={styles.receipt}>
<div>
<Body color="burgundy" textTransform="bold">
{`${booking.temp.room.type}, ${nights}`}
</Body>
<Body color="uiTextHighContrast">{booking.temp.room.price}</Body>
</div>
{booking.temp.packages.map((pkg) => (
<div key={pkg.name}>
<Body color="burgundy" textTransform="bold">
{pkg.name}
</Body>
<Body color="uiTextHighContrast">{pkg.price}</Body>
</div>
))}
</div>
<div className={styles.total}>
<div>
<Body color="burgundy" textTransform="bold">
{intl.formatMessage({ id: "VAT" })}
</Body>
<Body color="uiTextHighContrast">{booking.temp.room.vat}</Body>
</div>
<div>
<Body color="burgundy" textTransform="bold">
{intl.formatMessage({ id: "Total cost" })}
</Body>
<Body color="uiTextHighContrast">{booking.temp.total}</Body>
<Caption color="uiTextPlaceholder">
{`${intl.formatMessage({ id: "Approx." })} ${booking.temp.totalInEuro}`}
</Caption>
</div>
</div>
<Divider className={styles.divider} color="primaryLightSubtle" />
<div>
<Body color="burgundy" textTransform="bold">
{`${intl.formatMessage({ id: "Payment received" })} ${dt(booking.temp.payment).locale(params.lang).format("D MMM YYYY, h:mm z")}`}
</Body>
<Caption color="uiTextPlaceholder">
{intl.formatMessage(
{ id: "{card} ending with {cardno}" },
{
card: "Mastercard",
cardno: "2202",
}
)}
</Caption>
</div>
</div>
</section>
</main>
)
}
// const { email, hotel, stay, summary } = tempConfirmationData
// const confirmationNumber = useMemo(() => {
// if (typeof window === "undefined") return ""
// const storedConfirmationNumber = sessionStorage.getItem(
// BOOKING_CONFIRMATION_NUMBER
// )
// TODO: cleanup stored values
// sessionStorage.removeItem(BOOKING_CONFIRMATION_NUMBER)
// return storedConfirmationNumber
// }, [])
// const bookingStatus = useHandleBookingStatus(
// confirmationNumber,
// BookingStatusEnum.BookingCompleted,
// maxRetries,
// retryInterval
// )
// if (
// confirmationNumber === null ||
// bookingStatus.isError ||
// (bookingStatus.isFetched && !bookingStatus.data)
// ) {
// // TODO: handle error
// throw new Error("Error fetching booking status")
// }
// if (
// bookingStatus.data?.reservationStatus === BookingStatusEnum.BookingCompleted
// ) {
// return <LoadingSpinner />