Files
web/packages/booking-flow/lib/components/RoomSidePeek/RoomSidePeekContent/index.tsx
Anton Gunnarsson 322268595d Merged in feat/sw-3218-move-hotelreservationsidepeek-to-booking-flow (pull request #2600)
feat(SW-2873): Move HotelReservationSidePeek to booking-flow

* Move sidepeek store to booking-flow

* Begin move of HotelReservationSidePeek to booking-flow

* Copy Link

* Update AccessibilityAccordionItem

* Split AccessibilityAccordionItem into two components

* Fix tracking for Accordion

* Duplicate ButtonLink to booking-flow TEMP

* AdditionalAmeneties

* wip

* Move sidepeek accordion items

* Remove temp ButtonLink

* Merge branch 'master' into feat/sw-3218-move-hotelreservationsidepeek-to-booking-flow

* Fix accordion tracking

* Merge branch 'master' into feat/sw-3218-move-hotelreservationsidepeek-to-booking-flow

* Update exports

* Fix self-referencing import

* Merge branch 'master' into feat/sw-3218-move-hotelreservationsidepeek-to-booking-flow

* Add 'use client' to tracking function

* Merge branch 'master' into feat/sw-3218-move-hotelreservationsidepeek-to-booking-flow

* Fix TEMP folder

* Refactor sidepeek tracking

* Merge branch 'master' into feat/sw-3218-move-hotelreservationsidepeek-to-booking-flow


Approved-by: Joakim Jäderberg
2025-08-14 12:25:40 +00:00

175 lines
5.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useIntl } from "react-intl"
import { FacilityIcon } from "@scandic-hotels/design-system/Icons/FacilityIcon"
import ImageGallery from "@scandic-hotels/design-system/ImageGallery"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { BED_TYPE_ICONS, type BedTypes } from "../../../misc/bedTypeIcons"
import styles from "./roomSidePeekContent.module.css"
import type { ApiImage, Room } from "@scandic-hotels/trpc/types/hotel"
interface RoomSidePeekContentProps {
room: Room
}
export function RoomSidePeekContent({ room }: RoomSidePeekContentProps) {
const intl = useIntl()
const roomSize = room.roomSize
const totalOccupancy = room.totalOccupancy
const roomDescription = room.descriptions.medium
const galleryImages = mapApiImagesToGalleryImages(room.images)
return (
<div className={styles.wrapper}>
<div className={styles.mainContent}>
{totalOccupancy && (
<Typography variant="Body/Supporting text (caption)/smRegular">
<p>
{intl.formatMessage(
{
defaultMessage:
"Max. {max, plural, one {{range} guest} other {{range} guests}}",
},
{
max: totalOccupancy.max,
range: totalOccupancy.range,
}
)}
</p>
</Typography>
)}
{roomSize && (
<Typography variant="Body/Supporting text (caption)/smRegular">
<p>
{roomSize.min === roomSize.max
? intl.formatMessage(
{
defaultMessage: "{roomSize} m²",
},
{
roomSize: roomSize.min,
}
)
: intl.formatMessage(
{
defaultMessage: "{roomSizeMin}{roomSizeMax} m²",
},
{
roomSizeMin: roomSize.min,
roomSizeMax: roomSize.max,
}
)}
</p>
</Typography>
)}
<div className={styles.imageContainer}>
<ImageGallery images={galleryImages} title={room.name} height={280} />
</div>
</div>
<div className={styles.listContainer}>
<Typography variant="Title/Subtitle/md">
<p>
{intl.formatMessage({
defaultMessage: "Room amenities",
})}
</p>
</Typography>
<Typography variant="Body/Paragraph/mdRegular">
<ul className={styles.facilityList}>
{room.roomFacilities
.sort((a, b) => a.sortOrder - b.sortOrder)
.map((facility) => {
return (
<li key={facility.name}>
<FacilityIcon
name={facility.icon}
size={24}
color="Icon/Default"
/>
<span>
{facility.availableInAllRooms
? facility.name
: intl.formatMessage(
{
defaultMessage:
"{facility} (available in some rooms)",
},
{
facility: facility.name,
}
)}
</span>
</li>
)
})}
</ul>
</Typography>
</div>
<div className={styles.listContainer}>
<Typography variant="Title/Subtitle/md">
<p>
{intl.formatMessage({
defaultMessage: "Bed options",
})}
</p>
</Typography>
<Typography variant="Body/Paragraph/mdRegular">
<p>
{intl.formatMessage({
defaultMessage: "Subject to availability",
})}
</p>
</Typography>
<ul className={styles.bedOptions}>
{room.roomTypes.map((roomType) => {
const description =
roomType.description || roomType.mainBed.description
const MainBedIcon =
BED_TYPE_ICONS[roomType.mainBed.type as BedTypes]
const ExtraBedIcon = roomType.fixedExtraBed
? BED_TYPE_ICONS[roomType.fixedExtraBed.type as BedTypes]
: null
return (
<li key={roomType.code}>
{MainBedIcon ? <MainBedIcon height={24} width={24} /> : null}
{ExtraBedIcon ? <ExtraBedIcon height={24} width={30} /> : null}
<Typography variant="Body/Paragraph/mdRegular">
<span>{description}</span>
</Typography>
</li>
)
})}
</ul>
</div>
<div className={styles.listContainer}>
<Typography variant="Title/Subtitle/md">
<p>
{intl.formatMessage({
defaultMessage: "About the hotel",
})}
</p>
</Typography>
<Typography variant="Body/Paragraph/mdRegular">
<p>{roomDescription}</p>
</Typography>
</div>
</div>
)
}
function mapApiImagesToGalleryImages(apiImages: ApiImage[]) {
return apiImages.map((apiImage) => ({
src: apiImage.imageSizes.medium,
alt:
apiImage.metaData.altText ||
apiImage.metaData.altText_En ||
apiImage.metaData.title ||
apiImage.metaData.title_En,
caption: apiImage.metaData.title || apiImage.metaData.title_En,
smallSrc: apiImage.imageSizes.small,
}))
}