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
This commit is contained in:
Anton Gunnarsson
2025-08-14 12:25:40 +00:00
parent f04e476a6e
commit 322268595d
53 changed files with 826 additions and 425 deletions
@@ -1,61 +0,0 @@
"use client"
import { useIntl } from "react-intl"
import { isDefined } from "@scandic-hotels/common/utils/isDefined"
import AccordionItem from "@scandic-hotels/design-system/Accordion/AccordionItem"
import { IconName } from "@scandic-hotels/design-system/Icons/iconName"
import OpeningHours from "@scandic-hotels/design-system/OpeningHours"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { HotelTypeEnum } from "@scandic-hotels/trpc/enums/hotelType"
import { trackAccordionClick } from "@/utils/tracking"
import styles from "./sidePeekAccordion.module.css"
import type { BreakfastAccordionItemProps } from "@/types/components/sidePeeks/amenities"
export default function BreakfastAccordionItem({
restaurants,
hotelType,
}: BreakfastAccordionItemProps) {
const intl = useIntl()
const openingHours = restaurants
?.map((restaurant) => {
const breakfastDetail = restaurant.openingDetails.find(
(details) =>
details.openingHours.name === "Breakfast" ||
details.openingHours.name ===
intl.formatMessage({ defaultMessage: "Breakfast" })
)
return breakfastDetail
})
.filter(isDefined)[0]
if (!openingHours && hotelType !== HotelTypeEnum.ScandicGo) {
return null
}
return (
<AccordionItem
title={intl.formatMessage({ defaultMessage: "Breakfast" })}
iconName={IconName.CoffeeAlt}
variant="sidepeek"
className={styles.accordionItem}
onOpen={() => trackAccordionClick("amenities:breakfast")}
>
{openingHours ? (
<OpeningHours
openingHours={openingHours.openingHours}
alternateOpeningHours={openingHours.alternateOpeningHours}
heading={intl.formatMessage({ defaultMessage: "Opening hours" })}
/>
) : (
<Typography variant="Body/Paragraph/mdRegular">
<p>{intl.formatMessage({ defaultMessage: "All-day breakfast" })}</p>
</Typography>
)}
</AccordionItem>
)
}
@@ -1,61 +0,0 @@
"use client"
import { useIntl } from "react-intl"
import AccordionItem from "@scandic-hotels/design-system/Accordion/AccordionItem"
import { Divider } from "@scandic-hotels/design-system/Divider"
import { IconName } from "@scandic-hotels/design-system/Icons/iconName"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { trackAccordionClick } from "@/utils/tracking"
import styles from "./sidePeekAccordion.module.css"
import type { CheckInCheckOutAccordionItemProps } from "@/types/components/sidePeeks/amenities"
export default function CheckInCheckOutAccordionItem({
checkInData,
}: CheckInCheckOutAccordionItemProps) {
const intl = useIntl()
const { checkInTime, checkOutTime } = checkInData
return (
<AccordionItem
title={intl.formatMessage({ defaultMessage: "Check-in/Check-out" })}
iconName={IconName.Business}
variant="sidepeek"
className={styles.accordionItem}
onOpen={() => trackAccordionClick("amenities:check-in")}
>
<div className={styles.checkInCheckOutContent}>
<Typography variant="Title/Overline/sm">
<h4 className={styles.subheading}>
{intl.formatMessage({ defaultMessage: "Hours" })}
</h4>
</Typography>
<Divider />
<Typography variant="Body/Paragraph/mdRegular">
<div>
<p>
{intl.formatMessage(
{ defaultMessage: "Check in from: {checkInTime}" },
{
checkInTime,
}
)}
</p>
<p>
{intl.formatMessage(
{ defaultMessage: "Check out at latest: {checkOutTime}" },
{
checkOutTime,
}
)}
</p>
</div>
</Typography>
</div>
</AccordionItem>
)
}
@@ -1,63 +0,0 @@
"use client"
import { useIntl } from "react-intl"
import AccordionItem from "@scandic-hotels/design-system/Accordion/AccordionItem"
import ButtonLink from "@scandic-hotels/design-system/ButtonLink"
import { IconName } from "@scandic-hotels/design-system/Icons/iconName"
import ParkingInformation from "@scandic-hotels/design-system/ParkingInformation"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { trackAccordionClick } from "@/utils/tracking"
import styles from "./sidePeekAccordion.module.css"
import type { ParkingAccordionItemProps } from "@/types/components/sidePeeks/amenities"
export default function ParkingAccordionItem({
parking,
elevatorPitch,
parkingPageHref,
}: ParkingAccordionItemProps) {
const intl = useIntl()
if (!parking.length && !elevatorPitch && !parkingPageHref) {
return null
}
return (
<AccordionItem
title={intl.formatMessage({
defaultMessage: "Parking",
})}
iconName={IconName.Parking}
variant="sidepeek"
className={styles.accordionItem}
onOpen={() => trackAccordionClick("amenities:parking")}
>
<div className={styles.parkingContent}>
{elevatorPitch ? (
<Typography variant="Body/Paragraph/mdRegular">
<p>{elevatorPitch}</p>
</Typography>
) : null}
{parking.map((data) => (
<ParkingInformation key={data.type} parking={data} />
))}
{parkingPageHref ? (
<ButtonLink
href={parkingPageHref}
variant="Secondary"
color="Primary"
size="Medium"
typography="Body/Paragraph/mdBold"
>
{intl.formatMessage({
defaultMessage: "About parking",
})}
</ButtonLink>
) : null}
</div>
</AccordionItem>
)
}
@@ -1,17 +0,0 @@
.wrapper {
padding: var(--Space-x1) var(--Space-x0);
border-bottom: 1px solid var(--Base-Border-Subtle);
color: var(--Text-Interactive-Default);
}
.amenity {
display: flex;
gap: var(--Space-x1);
padding: var(--Space-x15) var(--Space-x1);
}
.amenityName {
display: flex;
align-items: center;
min-height: var(--Space-x3);
}
@@ -1,42 +0,0 @@
import { Typography } from "@scandic-hotels/design-system/Typography"
import { FacilityEnum } from "@scandic-hotels/trpc/enums/facilities"
import { FacilityToIcon } from "../../../ContentType/HotelPage/data"
import styles from "./additionalAmenities.module.css"
import type { AdditionalAmenitiesProps } from "@/types/components/sidePeeks/amenities"
export default function AdditionalAmenities({
amenities,
}: AdditionalAmenitiesProps) {
const amenitiesToIgnore = [
FacilityEnum.ParkingAdditionalCost,
FacilityEnum.ParkingElectricCharging,
FacilityEnum.ParkingFreeParking,
FacilityEnum.ParkingGarage,
FacilityEnum.ParkingOutdoor,
FacilityEnum.MeetingArea,
FacilityEnum.ServesBreakfastAlwaysIncluded,
FacilityEnum.LateCheckOutUntil1400Guaranteed,
]
const filteredAmenities = amenities.filter(
(amenity) => !amenitiesToIgnore.includes(amenity.id)
)
return filteredAmenities?.map((amenity) => (
<Typography key={amenity.name} variant="Title/Subtitle/md">
<li className={styles.wrapper}>
<div className={styles.amenity}>
<FacilityToIcon
id={amenity.id}
color="Icon/Interactive/Default"
size={24}
/>
<span className={styles.amenityName}>{amenity.name}</span>
</div>
</li>
</Typography>
))
}
@@ -2,11 +2,11 @@
import { useIntl } from "react-intl"
import { FacilityIcon } from "@scandic-hotels/design-system/Icons/FacilityIcon"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { getBedIconName } from "../RoomSidePeek/bedIcon"
import { FacilityIcon } from "../RoomSidePeek/facilityIcon"
import { getBedIconName } from "@/components/utils"
import styles from "./bookedRoomSidePeek.module.css"
@@ -1,5 +0,0 @@
.content {
display: grid;
gap: var(--Spacing-x2);
color: var(--Text-Default);
}
@@ -1,81 +0,0 @@
"use client"
import { useIntl } from "react-intl"
import Accordion from "@scandic-hotels/design-system/Accordion"
import ButtonLink from "@scandic-hotels/design-system/ButtonLink"
import SidePeek from "@scandic-hotels/design-system/SidePeek"
import { Typography } from "@scandic-hotels/design-system/Typography"
import Contact from "@/components/HotelReservation/Contact"
import AdditionalAmenities from "@/components/SidePeeks/AmenitiesSidepeekContent/AdditionalAmenities"
import AccessibilityAccordionItem from "../AmenitiesSidepeekContent/Accordions/Accessibility"
import BreakfastAccordionItem from "../AmenitiesSidepeekContent/Accordions/Breakfast"
import CheckInCheckOutAccordionItem from "../AmenitiesSidepeekContent/Accordions/CheckInCheckOut"
import ParkingAccordionItem from "../AmenitiesSidepeekContent/Accordions/Parking"
import styles from "./hotelSidePeek.module.css"
import type { HotelSidePeekProps } from "@/types/components/hotelReservation/hotelSidePeek"
import { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek"
export default function HotelSidePeek({
hotel,
restaurants,
additionalHotelData,
activeSidePeek,
close,
}: HotelSidePeekProps) {
const intl = useIntl()
return (
<SidePeek
title={hotel.name}
isOpen={activeSidePeek === SidePeekEnum.hotelDetails}
handleClose={close}
closeLabel={intl.formatMessage({
defaultMessage: "Close",
})}
>
<div className={styles.content}>
<Typography variant="Title/Subtitle/lg">
<h3>
{intl.formatMessage({ defaultMessage: "Practical information" })}
</h3>
</Typography>
<Contact hotel={hotel} />
<Accordion>
<ParkingAccordionItem
parking={hotel.parking}
elevatorPitch={additionalHotelData?.hotelParking.elevatorPitch}
/>
<BreakfastAccordionItem
restaurants={restaurants}
hotelType={hotel.hotelType}
/>
<CheckInCheckOutAccordionItem
checkInData={hotel.hotelFacts.checkin}
/>
<AccessibilityAccordionItem
elevatorPitch={additionalHotelData?.hotelSpecialNeeds.elevatorPitch}
/>
<AdditionalAmenities amenities={hotel.detailedFacilities} />
</Accordion>
{hotel.url ? (
<ButtonLink
href={hotel.url}
variant="Secondary"
size="Medium"
typography="Body/Paragraph/mdBold"
>
{intl.formatMessage({
defaultMessage: "Read more about the hotel",
})}
</ButtonLink>
) : null}
</div>
</SidePeek>
)
}
@@ -1,164 +0,0 @@
import { useIntl } from "react-intl"
import ImageGallery from "@scandic-hotels/design-system/ImageGallery"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { BED_TYPE_ICONS, type BedTypes } from "@/constants/booking"
import { mapApiImagesToGalleryImages } from "@/utils/imageGallery"
import { FacilityIcon } from "../facilityIcon"
import styles from "./roomSidePeekContent.module.css"
import type { 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>
)
}
@@ -1,58 +0,0 @@
.wrapper {
display: flex;
flex-direction: column;
gap: var(--Spacing-x2);
position: relative;
margin-bottom: calc(
var(--Spacing-x4) * 2 + 80px
); /* Creates space between the wrapper and buttonContainer */
}
.mainContent {
color: var(--Text-Secondary);
}
.mainContent,
.listContainer {
display: flex;
flex-direction: column;
gap: var(--Spacing-x-one-and-half);
}
.imageContainer {
position: relative;
border-radius: var(--Corner-radius-md);
overflow: hidden;
}
.imageContainer img {
width: 100%;
aspect-ratio: 16/9;
object-fit: cover;
}
.facilityList {
column-count: 2;
column-gap: var(--Spacing-x2);
color: var(--Text-Secondary);
}
.facilityList li {
display: flex !important; /* Overrides the display none from grids.stackable on Hotel Page */
gap: var(--Spacing-x1);
margin-bottom: var(--Spacing-x-half);
}
.bedOptions {
color: var(--Text-Secondary);
}
.bedOptions li {
display: flex;
gap: var(--Spacing-x1);
margin-bottom: var(--Spacing-x-half);
}
.facilityList li svg {
flex-shrink: 0;
}
@@ -1,29 +0,0 @@
import type { MaterialSymbolProps } from "@scandic-hotels/design-system/Icons/MaterialIcon/MaterialSymbol"
export function getBedIconName(name: string): MaterialSymbolProps["icon"] {
const iconMappings = [
{
icon: "bed",
texts: ["Queen"],
},
{
icon: "king_bed",
texts: ["King"],
},
{
icon: "single_bed",
texts: ["CustomOccupancy"],
},
{
icon: "bed",
texts: ["Twin"],
},
{
icon: "single_bed",
texts: ["Single"],
},
]
const icon = iconMappings.find((icon) => icon.texts.includes(name))
return icon ? (icon.icon as MaterialSymbolProps["icon"]) : "single_bed"
}
@@ -1,240 +0,0 @@
import BathroomCabinetIcon from "@scandic-hotels/design-system/Icons/BathroomCabinetIcon"
import BedHotelIcon from "@scandic-hotels/design-system/Icons/BedHotelIcon"
import BowlingPinsIcon from "@scandic-hotels/design-system/Icons/BowlingPinsIcon"
import BunkBedIcon from "@scandic-hotels/design-system/Icons/BunkBedIcon"
import ConferenceRoomIcon from "@scandic-hotels/design-system/Icons/ConferenceRoomIcon"
import CoolingIcon from "@scandic-hotels/design-system/Icons/CoolingIcon"
import CouchTableIcon from "@scandic-hotels/design-system/Icons/CouchTableIcon"
import DoorIcon from "@scandic-hotels/design-system/Icons/DoorIcon"
import FootStoolIcon from "@scandic-hotels/design-system/Icons/FootStoolIcon"
import HairdresserIcon from "@scandic-hotels/design-system/Icons/HairdresserIcon"
import HairdryerIcon from "@scandic-hotels/design-system/Icons/HairdryerIcon"
import HandSoapIcon from "@scandic-hotels/design-system/Icons/HandSoapIcon"
import IceMachineIcon from "@scandic-hotels/design-system/Icons/IceMachineIcon"
import MassageIcon from "@scandic-hotels/design-system/Icons/MassageIcon"
import {
MaterialIcon,
type MaterialIconSetIconProps,
} from "@scandic-hotels/design-system/Icons/MaterialIcon"
import MirrorIcon from "@scandic-hotels/design-system/Icons/MirrorIcon"
import MovingBedsIcon from "@scandic-hotels/design-system/Icons/MovingBedsIcon"
import RecordPlayerIcon from "@scandic-hotels/design-system/Icons/RecordPlayerIcon"
import RoadIcon from "@scandic-hotels/design-system/Icons/RoadIcon"
import RugIcon from "@scandic-hotels/design-system/Icons/RugIcon"
import SafetyBoxIcon from "@scandic-hotels/design-system/Icons/SafetyBoxIcon"
import SlippersIcon from "@scandic-hotels/design-system/Icons/SlippersIcon"
import ToiletIcon from "@scandic-hotels/design-system/Icons/ToiletIcon"
import TowelIcon from "@scandic-hotels/design-system/Icons/TowelIcon"
import UserPoliceIcon from "@scandic-hotels/design-system/Icons/UserPoliceIcon"
import ViewIcon from "@scandic-hotels/design-system/Icons/ViewIcon"
import WardIcon from "@scandic-hotels/design-system/Icons/WardIcon"
import WindowNotAvailableIcon from "@scandic-hotels/design-system/Icons/WindowNotAvailableIcon"
import WoodFloorIcon from "@scandic-hotels/design-system/Icons/WoodFloorIcon"
import type {
IconProps,
NucleoIconProps,
} from "@scandic-hotels/design-system/Icons"
import type { MaterialSymbolProps } from "@scandic-hotels/design-system/Icons/MaterialIcon/MaterialSymbol"
import type { JSX } from "react"
interface FacilityIconProps {
name: string | undefined
}
export function FacilityIcon({
name,
...props
}:
| (FacilityIconProps & MaterialIconSetIconProps)
| NucleoIconProps
| IconProps): JSX.Element {
if (!name) {
return <MaterialIcon icon="favorite" {...props} />
}
const normalizedName = name.toLowerCase()
const customIcon = CustomIconMappings.find(
(icon) => icon.name.toLowerCase() === normalizedName
)
if (customIcon) {
return <customIcon.icon {...props} />
}
const materialSymbolIcon = MaterialIconMappings.find(
(icon) => icon.name.toLowerCase() === normalizedName
)
return materialSymbolIcon ? (
<MaterialIcon icon={materialSymbolIcon.icon} {...props} />
) : (
<MaterialIcon icon="favorite" {...props} />
)
}
const MaterialIconMappings: {
icon: MaterialSymbolProps["icon"]
name: string
}[] = [
{ icon: "air_purifier_gen", name: "aircondition" },
{ icon: "travel", name: "airport" },
{ icon: "balcony", name: "balcony" },
{ icon: "deck", name: "balconyorterrace" },
{ icon: "balcony", name: "frenchbalcony" },
{ icon: "bathtub", name: "bathroomwithbathtub" },
{ icon: "bathtub", name: "bathroomwithshowerandbathtub" },
{ icon: "bed", name: "setoftwopillows" },
{ icon: "chair", name: "armchairbed" },
{ icon: "meeting_room", name: "separatebedroom" },
{ icon: "pedal_bike", name: "bikeforloan" },
{ icon: "bakery_dining", name: "breakfast" },
{ icon: "bakery_dining", name: "servesbreakfastalwaysincluded" },
{ icon: "business_center", name: "meetingconferencefacilities" },
{ icon: "business_center", name: "meetingrooms" },
{ icon: "router", name: "internetwithcableintheroom" },
{ icon: "chair", name: "armchair" },
{ icon: "chair", name: "chair" },
{ icon: "meeting_room", name: "connectingrooms" },
{ icon: "location_city", name: "viewcityview" },
{ icon: "coffee_maker", name: "nespressomachine" },
{ icon: "dining", name: "café" },
{ icon: "coffee", name: "coffee" },
{ icon: "coffee_maker", name: "coffeemachine" },
{ icon: "concierge", name: "lifestyleconcierge" },
{ icon: "mode_fan", name: "aircooling" },
{ icon: "mode_fan", name: "cooler" },
{ icon: "desk", name: "deskandchair" },
{ icon: "desk", name: "desk" },
{ icon: "dining", name: "diningarea" },
{ icon: "table_bar", name: "tablefordining" },
{ icon: "electric_bike", name: "ebikeschargingstation" },
{ icon: "family_restroom", name: "extrafamilyfriendly" },
{ icon: "exercise", name: "gym" },
{ icon: "health_and_beauty", name: "beautysalon" },
{ icon: "bathroom", name: "bathroom2separatebathrooms" },
{ icon: "credit_card_heart", name: "cashfree800pmtill0600am" },
{ icon: "credit_card_heart", name: "cashfreehotel" },
{ icon: "confirmation_number", name: "coffeevoucher" },
{ icon: "water_full", name: "complimentarycoldrefreshments" },
{ icon: "groups", name: "conventioncentre" },
{ icon: "accessible", name: "disabledparking" },
{ icon: "charging_station", name: "dockingstationforipodipad" },
{ icon: "cool_to_dry", name: "dryingcabinet" },
{ icon: "assistant_navigation", name: "easyaccess" },
{ icon: "laundry", name: "garmentsteamer" },
{ icon: "stairs", name: "highfloor" },
{ icon: "hot_tub", name: "jaccuzzi" },
{ icon: "hot_tub", name: "jacuzzi" },
{ icon: "countertops", name: "kitchen" },
{ icon: "countertops", name: "kitchenette" },
{ icon: "checked_bag", name: "latecheckoutuntil1400guaranteed" },
{ icon: "music_cast", name: "livemusicexhibitions" },
{ icon: "liquor", name: "minibarincludedinroomrate" },
{ icon: "local_parking", name: "parkingadditionalcost" },
{ icon: "sauna", name: "privatesauna" },
{ icon: "kitchen", name: "refrigerator" },
{ icon: "airline_seat_recline_normal", name: "seatingarea" },
{ icon: "scene", name: "separatelivingroom" },
{ icon: "chair", name: "sofabed" },
{ icon: "chair", name: "sofas" },
{ icon: "chair", name: "sofa" },
{ icon: "bedroom_parent", name: "spaciousroom" },
{ icon: "local_drink", name: "stillandsparklingwater" },
{ icon: "table_bar", name: "table" },
{ icon: "coffee_maker", name: "tassimocoffeemaker" },
{ icon: "deck", name: "terrace" },
{ icon: "iron", name: "trouserpress" },
{ icon: "tv_guide", name: "tv" },
{ icon: "tv_remote", name: "tvwithcomplimentarymoviechannels" },
{ icon: "tv_remote", name: "tvwithmoviechannels" },
{ icon: "live_tv", name: "tvwithstreamingoption" },
{ icon: "hvac", name: "ventilationinroom" },
{ icon: "landscape", name: "viewfjordview" },
{ icon: "houseboat", name: "viewlakeview" },
{ icon: "panorama", name: "viewpanoramicview" },
{ icon: "sailing", name: "viewseaview" },
{ icon: "ward", name: "wallbed" },
{ icon: "pedal_bike", name: "wallmountedcyclerack" },
{ icon: "dresser", name: "wardrobe" },
{ icon: "spa", name: "wellnessandsaunaentrancefeeadmission16years" },
{ icon: "spa", name: "wellnesspoolsaunaentrancefeeadmission16years" },
{ icon: "curtains", name: "windownook" },
{ icon: "iron", name: "ironandironingboard" },
{ icon: "iron", name: "ironingroom" },
{ icon: "kayaking", name: "kayaksforloan" },
{ icon: "kettle", name: "kettle" },
{ icon: "kettle", name: "kettlewithcoffee" },
{ icon: "sync_saved_locally", name: "laptopsafe" },
{ icon: "computer", name: "laptoptray" },
{ icon: "local_laundry_service", name: "laundryservice" },
{ icon: "local_bar", name: "bar" },
{ icon: "deck", name: "rooftopbar" },
{ icon: "local_bar", name: "skybar" },
{ icon: "microwave", name: "microwave" },
{ icon: "nature", name: "viewparkview" },
{ icon: "nightlife", name: "disconightclub" },
{ icon: "smoke_free", name: "nonsmoking" },
{ icon: "deck", name: "outdoorterrace" },
{ icon: "local_parking", name: "parking" },
{ icon: "local_parking", name: "parkingfreeparking" },
{ icon: "pets", name: "petfriendlyrooms" },
{ icon: "phone", name: "directdialphoneandvoicemail" },
{ icon: "restaurant", name: "restaurant" },
{ icon: "room_service", name: "roomservice" },
{ icon: "sauna", name: "sauna" },
{ icon: "shower", name: "bathroomwithshower" },
{ icon: "shower", name: "rainshower" },
{ icon: "shower", name: "sharedbathroomwithshower" },
{ icon: "radio", name: "musicplayer" },
{ icon: "shopping_bag", name: "shop" },
{ icon: "pool", name: "pool" },
{ icon: "laundry", name: "handwash" },
{ icon: "connected_tv", name: "tvwithchromecast" },
{ icon: "wifi", name: "freewifi" },
{ icon: "curtains_closed", name: "blackoutcurtains" },
{ icon: "liquor", name: "minibar" },
{ icon: "yard", name: "viewatriumview" },
]
const CustomIconMappings = [
{ icon: BathroomCabinetIcon, name: "bathroomwithshowerorbathtub" },
{ icon: MovingBedsIcon, name: "adjustablebeds" },
{ icon: MovingBedsIcon, name: "pulloutbed" },
{ icon: BedHotelIcon, name: "extrabed" },
{ icon: CoolingIcon, name: "coolingcabinet" },
{ icon: FootStoolIcon, name: "footstool" },
{ icon: HairdryerIcon, name: "hairdryer" },
{ icon: HairdresserIcon, name: "hairdresser" },
{ icon: HandSoapIcon, name: "toiletries" },
{ icon: TowelIcon, name: "bathrobes" },
{ icon: HandSoapIcon, name: "bodycareproducts" },
{ icon: HandSoapIcon, name: "bodylotion" },
{ icon: BowlingPinsIcon, name: "bowling" },
{ icon: BunkBedIcon, name: "bunkbed" },
{ icon: BunkBedIcon, name: "bunkbed80x188cm" },
{ icon: IceMachineIcon, name: "icemachine" },
{ icon: IceMachineIcon, name: "icemachinereception" },
{ icon: MassageIcon, name: "massage" },
{ icon: ConferenceRoomIcon, name: "meetingarea" },
{ icon: UserPoliceIcon, name: "overnightsecurity" },
{ icon: UserPoliceIcon, name: "security24hoours" },
{ icon: UserPoliceIcon, name: "servicesecurity24h" },
{ icon: FootStoolIcon, name: "footstool" },
{ icon: WindowNotAvailableIcon, name: "nowindow" },
{ icon: DoorIcon, name: "luggagelockers" },
{ icon: MirrorIcon, name: "cosmeticmirror" },
{ icon: WardIcon, name: "wallbed" },
{ icon: CouchTableIcon, name: "sofawithtable" },
{ icon: SafetyBoxIcon, name: "safetybox" },
{ icon: RecordPlayerIcon, name: "modernvinylplayer" },
{ icon: RugIcon, name: "carpetingwalltowallcarpet" },
{ icon: ToiletIcon, name: "separatetoilet" },
{ icon: WoodFloorIcon, name: "woodenfloor" },
{ icon: ViewIcon, name: "view" },
{ icon: HandSoapIcon, name: "shampoo" },
{ icon: HandSoapIcon, name: "conditioner" },
{ icon: RoadIcon, name: "viewstreetview" },
{ icon: SlippersIcon, name: "slippers" },
{ icon: HandSoapIcon, name: "showergel" },
{ icon: HandSoapIcon, name: "showerproductsscentbygrandcentral" },
]
@@ -1,29 +0,0 @@
import { useIntl } from "react-intl"
import SidePeek from "@scandic-hotels/design-system/SidePeek"
import { RoomSidePeekContent } from "./RoomSidePeekContent"
import { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek"
import type { RoomSidePeekProps } from "@/types/components/sidePeeks/roomSidePeek"
export default function RoomSidePeek({
room,
activeSidePeek,
close,
}: RoomSidePeekProps) {
const intl = useIntl()
return (
<SidePeek
title={room.name}
isOpen={activeSidePeek === SidePeekEnum.roomDetails}
handleClose={close}
closeLabel={intl.formatMessage({
defaultMessage: "Close",
})}
>
<RoomSidePeekContent room={room} />
</SidePeek>
)
}