Merged in fix/SW-2553-sidepeeks (pull request #1919)

Fix/SW-2553 sidepeeks

* fix(SW-2553): apply sidepeek display logic

* chore: move convertToChildType and getPriceType utils

* fix: apply PR requested changes

* fix(SW-2553): fix roomNumber for multiroom

* fix(SW-2553): fix sidepeek for my-stay page


Approved-by: Michael Zetterberg
Approved-by: Bianca Widstam
Approved-by: Matilda Landström
This commit is contained in:
Arvid Norlin
2025-05-02 15:10:34 +00:00
committed by Bianca Widstam
parent f5f9aba2e5
commit 0c7836fa59
33 changed files with 881 additions and 510 deletions

View File

@@ -5,7 +5,6 @@ import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { dt } from "@/lib/dt"
import { useMyStayStore } from "@/stores/my-stay"
import GuestDetails from "@/components/HotelReservation/MyStay/GuestDetails"
import PriceType from "@/components/HotelReservation/MyStay/PriceType"
@@ -14,7 +13,7 @@ import ImageGallery from "@/components/ImageGallery"
import Accordion from "@/components/TempDesignSystem/Accordion"
import AccordionItem from "@/components/TempDesignSystem/Accordion/AccordionItem"
import IconChip from "@/components/TempDesignSystem/IconChip"
import SidePeek from "@/components/TempDesignSystem/SidePeek"
import SidePeekSelfControlled from "@/components/TempDesignSystem/SidePeekSelfControlled"
import useLang from "@/hooks/useLang"
import { mapApiImagesToGalleryImages } from "@/utils/imageGallery"
import { formatPrice } from "@/utils/numberFormatting"
@@ -23,28 +22,60 @@ import RoomDetails from "./RoomDetails"
import styles from "./bookedRoomSidePeek.module.css"
import type { BreakfastPackage } from "@/types/components/hotelReservation/breakfast"
import type { BedTypeSchema } from "@/types/components/hotelReservation/enterDetails/bedType"
import type { PriceTypeEnum } from "@/types/components/hotelReservation/myStay/myStay"
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
import { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek"
import type { BookedRoomSidePeekProps } from "@/types/components/sidePeeks/bookedRoomSidePeek"
import type { Child } from "@/types/components/hotelReservation/selectRate/selectRate"
import type { Room as HotelRoom } from "@/types/hotel"
import type { Packages } from "@/types/requests/packages"
import type { BookingConfirmationSchema } from "@/types/trpc/routers/booking/confirmation"
import type { SafeUser } from "@/types/user"
export type PartialHotelRoom = Pick<
HotelRoom,
"descriptions" | "images" | "name" | "roomFacilities" | "roomTypes"
>
export type Room = Pick<
BookingConfirmationSchema,
| "adults"
| "bookingCode"
| "cancellationNumber"
| "checkInDate"
| "cheques"
| "confirmationNumber"
| "currencyCode"
| "guest"
| "rateDefinition"
| "roomPoints"
| "totalPrice"
| "vouchers"
> & {
bedType: BedTypeSchema
breakfast: Omit<BreakfastPackage, "requestedPrice"> | null
childrenInRoom: Child[]
isCancelled: boolean
packages: Packages | null
priceType: PriceTypeEnum
roomName: string
roomNumber: number
terms: string | null
}
interface RoomDetailsSidePeekProps {
hotelRoom: PartialHotelRoom | null
room: Room
user: SafeUser
}
export default function BookedRoomSidePeek({
hotelRoom,
room,
activeSidePeek,
user,
confirmationNumber,
close,
}: BookedRoomSidePeekProps) {
}: RoomDetailsSidePeekProps) {
const intl = useIntl()
const lang = useLang()
const rooms = useMyStayStore((state) => state.rooms)
const bookingRoom = rooms.find(
(r) => r.confirmationNumber === confirmationNumber
)
if (!bookingRoom) {
return null
}
const {
adults,
@@ -53,20 +84,28 @@ export default function BookedRoomSidePeek({
breakfast,
cancellationNumber,
checkInDate,
cheques,
childrenInRoom,
confirmationNumber,
currencyCode,
guest,
isCancelled,
roomName,
packages,
priceType,
rateDefinition,
roomNumber,
roomPoints,
terms,
totalPrice,
} = bookingRoom
vouchers,
} = room
const fromDate = dt(checkInDate).locale(lang)
const roomDescription = room.descriptions.medium
const galleryImages = mapApiImagesToGalleryImages(room.images)
const galleryImages = hotelRoom
? mapApiImagesToGalleryImages(hotelRoom.images)
: null
const adultsMsg = intl.formatMessage(
{
@@ -106,12 +145,10 @@ export default function BookedRoomSidePeek({
)
}
const hotelRoomName = hotelRoom?.name || roomName
return (
<SidePeek
title={room.name}
isOpen={activeSidePeek === SidePeekEnum.bookedRoomDetails}
handleClose={close}
>
<SidePeekSelfControlled title={hotelRoomName}>
<div className={styles.wrapper}>
<div className={styles.roomHeader}>
{isCancelled ? (
@@ -180,11 +217,13 @@ export default function BookedRoomSidePeek({
</div>
<div className={styles.mainContent}>
<div className={styles.imageContainer}>
<ImageGallery
images={galleryImages}
title={room.name}
height={280}
/>
{galleryImages ? (
<ImageGallery
height={280}
images={galleryImages}
title={hotelRoomName}
/>
) : null}
</div>
<div className={styles.roomDetails}>
<div className={styles.row}>
@@ -334,14 +373,14 @@ export default function BookedRoomSidePeek({
</Typography>
<PriceType
cheques={bookingRoom.cheques}
cheques={cheques}
formattedTotalPrice={formattedTotalPrice}
isCancelled={bookingRoom.isCancelled}
priceType={bookingRoom.priceType}
rateDefinition={bookingRoom.rateDefinition}
roomPoints={bookingRoom.roomPoints}
totalPrice={bookingRoom.totalPrice}
vouchers={bookingRoom.vouchers}
isCancelled={isCancelled}
priceType={priceType}
rateDefinition={rateDefinition}
roomPoints={roomPoints}
totalPrice={totalPrice}
vouchers={vouchers}
/>
</div>
</div>
@@ -369,23 +408,30 @@ export default function BookedRoomSidePeek({
</Typography>
)}
<GuestDetails selectedRoom={bookingRoom} user={user} />
<GuestDetails
confirmationNumber={confirmationNumber}
guest={guest}
isCancelled={isCancelled}
user={user}
/>
</div>
<Accordion>
<AccordionItem
title={intl.formatMessage({
defaultMessage: "Room details",
})}
variant="sidepeek"
>
<RoomDetails
roomDescription={roomDescription}
roomFacilities={room.roomFacilities}
roomTypes={room.roomTypes}
/>
</AccordionItem>
</Accordion>
{hotelRoom ? (
<Accordion>
<AccordionItem
title={intl.formatMessage({
defaultMessage: "Room details",
})}
variant="sidepeek"
>
<RoomDetails
roomDescription={hotelRoom.descriptions.medium}
roomFacilities={hotelRoom.roomFacilities}
roomTypes={hotelRoom.roomTypes}
/>
</AccordionItem>
</Accordion>
) : null}
</div>
</SidePeek>
</SidePeekSelfControlled>
)
}