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:
@@ -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>
|
||||
)
|
||||
}
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
@@ -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}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user