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
175 lines
5.7 KiB
TypeScript
175 lines
5.7 KiB
TypeScript
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,
|
||
}))
|
||
}
|