Merged in chore/SW-2878-extract-booking-confirmation-pag (pull request #2779)

Chore/SW-2878 extract booking confirmation pag

* chore(SW-2878): Moved booking confirmation page to booking-flow package

* chore(SW-2878): Fixed promo styles as per design

* chore(SW-2878): Kept tiny duplicate function to avoid export from booking-flow package


Approved-by: Anton Gunnarsson
This commit is contained in:
Hrishikesh Vaipurkar
2025-09-10 07:50:48 +00:00
parent c6da0fb8cb
commit a5790ee454
77 changed files with 410 additions and 371 deletions

View File

@@ -0,0 +1,33 @@
import SkeletonShimmer from "@scandic-hotels/design-system/SkeletonShimmer"
import styles from "./linkedReservationCardSkeleton.module.css"
export function LinkedReservationCardSkeleton() {
return (
<div className={styles.card}>
<div className={styles.content}>
<div className={styles.img}>
<SkeletonShimmer height={"204px"} width={"100%"} />
</div>
<div className={styles.roomDetails}>
<div className={styles.roomName}>
<SkeletonShimmer height={"24px"} width={"130px"} />
<SkeletonShimmer height={"20px"} width={"140px"} />
</div>
<div className={styles.details}>
<SkeletonShimmer height={"20px"} width={"300px"} />
<SkeletonShimmer height={"20px"} width={"300px"} />
<SkeletonShimmer height={"20px"} width={"300px"} />
<SkeletonShimmer height={"20px"} width={"300px"} />
</div>
<div className={styles.guest}>
<SkeletonShimmer height={"20px"} width={"100px"} />
<SkeletonShimmer height={"20px"} width={"200px"} />
<SkeletonShimmer height={"20px"} width={"150px"} />
<SkeletonShimmer height={"20px"} width={"300px"} />
</div>
</div>
</div>
</div>
)
}

View File

@@ -0,0 +1,33 @@
"use client"
import { useIntl } from "react-intl"
import { Button } from "@scandic-hotels/design-system/Button"
import { Typography } from "@scandic-hotels/design-system/Typography"
import styles from "./retry.module.css"
export interface RetryProps {
handleRefetch: () => void
}
export default function Retry({ handleRefetch }: RetryProps) {
const intl = useIntl()
return (
<div className={styles.retry}>
<Typography variant={"Body/Paragraph/mdRegular"}>
<p>
{intl.formatMessage({
defaultMessage: "Something went wrong!",
})}
</p>
</Typography>
<Button size={"Small"} onPress={handleRefetch}>
{intl.formatMessage({
defaultMessage: "Try again",
})}
</Button>
</div>
)
}

View File

@@ -0,0 +1,95 @@
"use client"
import { useEffect } from "react"
import { useIntl } from "react-intl"
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
import { formatPrice } from "@scandic-hotels/common/utils/numberFormatting"
import { trpc } from "@scandic-hotels/trpc/client"
import useLang from "../../../../hooks/useLang"
import { useBookingConfirmationStore } from "../../../../stores/booking-confirmation"
import { mapRoomState } from "../../utils"
import { Room } from "../Room"
import { LinkedReservationCardSkeleton } from "./LinkedReservationCardSkeleton"
import Retry from "./Retry"
export interface LinkedReservationProps {
checkInTime: string
checkOutTime: string
refId: string
roomIndex: number
}
export function LinkedReservation({
checkInTime,
checkOutTime,
refId,
roomIndex,
}: LinkedReservationProps) {
const lang = useLang()
const { data, refetch, isLoading } = trpc.booking.get.useQuery({
refId,
lang,
})
const {
setRoom,
setFormattedTotalCost,
currencyCode,
totalBookingPrice,
totalBookingCheques,
} = useBookingConfirmationStore((state) => ({
setRoom: state.actions.setRoom,
setFormattedTotalCost: state.actions.setFormattedTotalCost,
currencyCode: state.currencyCode,
totalBookingPrice: state.totalBookingPrice,
totalBookingCheques: state.totalBookingCheques,
}))
const intl = useIntl()
useEffect(() => {
if (data?.room) {
const roomData = mapRoomState(data.booking, data.room, intl)
setRoom(roomData, roomIndex)
const formattedTotalCost = totalBookingCheques
? formatPrice(
intl,
totalBookingCheques,
CurrencyEnum.CC,
totalBookingPrice,
currencyCode
)
: formatPrice(intl, totalBookingPrice, currencyCode)
setFormattedTotalCost(formattedTotalCost)
}
}, [
data,
roomIndex,
intl,
setRoom,
totalBookingCheques,
totalBookingPrice,
currencyCode,
setFormattedTotalCost,
])
if (isLoading) {
return <LinkedReservationCardSkeleton />
}
if (!data?.room) {
return <Retry handleRefetch={refetch} />
}
return (
<Room
booking={data.booking}
checkInTime={checkInTime}
checkOutTime={checkOutTime}
img={data.room.images[0]}
roomName={data.room.name}
/>
)
}

View File

@@ -0,0 +1,66 @@
.card {
display: flex;
flex-direction: column;
gap: var(--Spacing-x2);
}
.content {
background-color: var(--Background-Primary);
border-radius: var(--Corner-radius-lg);
display: grid;
gap: var(--Spacing-x2);
padding: var(--Spacing-x2) var(--Spacing-x2) var(--Spacing-x3)
var(--Spacing-x2);
}
.img {
border-radius: var(--Corner-radius-md);
overflow: hidden;
}
.roomDetails {
display: grid;
gap: var(--Spacing-x2);
}
.roomName {
display: flex;
flex-direction: column;
gap: var(--Spacing-x1);
grid-column: 1/-1;
justify-content: space-evenly;
}
.details {
display: flex;
flex-direction: column;
gap: var(--Spacing-x1);
justify-content: space-evenly;
}
.guest {
display: flex;
flex-direction: column;
gap: var(--Spacing-x1);
justify-content: space-evenly;
}
@media screen and (min-width: 1367px) {
.content {
gap: var(--Spacing-x3);
grid-template-columns: auto 1fr;
padding: var(--Spacing-x2) var(--Spacing-x3) var(--Spacing-x2)
var(--Spacing-x2);
}
.img {
min-width: 306px;
}
.roomDetails {
grid-template-columns: 1fr 1fr;
}
.guest {
align-items: flex-end;
}
}

View File

@@ -0,0 +1,10 @@
.retry {
background-color: var(--Background-Primary);
border-radius: var(--Corner-radius-lg);
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;
}