From 0efa52ada5de44f7a8333354314c2ca9efefaaa3 Mon Sep 17 00:00:00 2001 From: Niclas Edenvin Date: Fri, 25 Oct 2024 14:11:06 +0000 Subject: [PATCH] Merged in feat/sw-587-sidepeek-for-room (pull request #767) Create the sidepeek for a specific roomtype. This also changes the lightbox to use react-aria instead of radix-ui, so we use the same for the lightbox and the sidepeek. Works better together! Approved-by: Bianca Widstam --- app/globals.css | 3 +- .../SelectRate/ImageGallery/index.tsx | 1 - .../RoomSelection/RoomCard/index.tsx | 17 +-- .../RoomSidePeek/facilityIcon.ts | 124 ++++++++++++++++++ .../RoomSelection/RoomSidePeek/index.tsx | 96 ++++++++++++++ .../RoomSidePeek/roomSidePeek.module.css | 29 ++++ components/Icons/Ac.tsx | 36 +++++ components/Icons/Bathtub.tsx | 36 +++++ components/Icons/BedDouble.tsx | 40 ++++++ components/Icons/Chair.tsx | 36 +++++ components/Icons/City.tsx | 36 +++++ components/Icons/Desk.tsx | 36 +++++ components/Icons/Hairdryer.tsx | 58 ++++++++ components/Icons/HandSoap.tsx | 49 +++++++ components/Icons/Iron.tsx | 36 +++++ components/Icons/Mirror.tsx | 25 ++++ components/Icons/SafetyBox.tsx | 46 +++++++ components/Icons/Shower.tsx | 36 +++++ components/Icons/WindowCurtainsAlt.tsx | 40 ++++++ components/Icons/WindowNotAvailable.tsx | 52 ++++++++ components/Icons/WineBar.tsx | 36 +++++ components/Icons/WoodFloor.tsx | 84 ++++++++++++ components/Icons/Yard.tsx | 36 +++++ components/Icons/index.tsx | 18 +++ components/Lightbox/Gallery.tsx | 8 -- components/Lightbox/Lightbox.module.css | 22 +++- components/Lightbox/index.tsx | 36 +++-- .../SidePeek/sidePeek.module.css | 2 +- .../Text/Body/body.module.css | 4 + .../TempDesignSystem/Text/Body/variants.ts | 1 + i18n/dictionaries/da.json | 2 + i18n/dictionaries/de.json | 2 + i18n/dictionaries/en.json | 2 + i18n/dictionaries/fi.json | 2 + i18n/dictionaries/no.json | 2 + i18n/dictionaries/sv.json | 2 + server/routers/hotels/schemas/room.ts | 1 + .../selectRate/roomSidePeek.ts | 8 ++ 38 files changed, 1055 insertions(+), 45 deletions(-) create mode 100644 components/HotelReservation/SelectRate/RoomSelection/RoomSidePeek/facilityIcon.ts create mode 100644 components/HotelReservation/SelectRate/RoomSelection/RoomSidePeek/index.tsx create mode 100644 components/HotelReservation/SelectRate/RoomSelection/RoomSidePeek/roomSidePeek.module.css create mode 100644 components/Icons/Ac.tsx create mode 100644 components/Icons/Bathtub.tsx create mode 100644 components/Icons/BedDouble.tsx create mode 100644 components/Icons/Chair.tsx create mode 100644 components/Icons/City.tsx create mode 100644 components/Icons/Desk.tsx create mode 100644 components/Icons/Hairdryer.tsx create mode 100644 components/Icons/HandSoap.tsx create mode 100644 components/Icons/Iron.tsx create mode 100644 components/Icons/Mirror.tsx create mode 100644 components/Icons/SafetyBox.tsx create mode 100644 components/Icons/Shower.tsx create mode 100644 components/Icons/WindowCurtainsAlt.tsx create mode 100644 components/Icons/WindowNotAvailable.tsx create mode 100644 components/Icons/WineBar.tsx create mode 100644 components/Icons/WoodFloor.tsx create mode 100644 components/Icons/Yard.tsx create mode 100644 types/components/hotelReservation/selectRate/roomSidePeek.ts diff --git a/app/globals.css b/app/globals.css index 5fff0324b..539f9827a 100644 --- a/app/globals.css +++ b/app/globals.css @@ -115,7 +115,8 @@ --header-z-index: 10; --menu-overlay-z-index: 10; --dialog-z-index: 9; - --sidepeek-z-index: 11; + --sidepeek-z-index: 100; + --lightbox-z-index: 150; } * { diff --git a/components/HotelReservation/SelectRate/ImageGallery/index.tsx b/components/HotelReservation/SelectRate/ImageGallery/index.tsx index 778c2d45e..1d4500cdb 100644 --- a/components/HotelReservation/SelectRate/ImageGallery/index.tsx +++ b/components/HotelReservation/SelectRate/ImageGallery/index.tsx @@ -21,7 +21,6 @@ export default function ImageGallery({ images, title }: ImageGalleryProps) { {images[0].metaData.altText}
diff --git a/components/HotelReservation/SelectRate/RoomSelection/RoomCard/index.tsx b/components/HotelReservation/SelectRate/RoomSelection/RoomCard/index.tsx index 444968ce1..1afec6119 100644 --- a/components/HotelReservation/SelectRate/RoomSelection/RoomCard/index.tsx +++ b/components/HotelReservation/SelectRate/RoomSelection/RoomCard/index.tsx @@ -5,14 +5,13 @@ import { useIntl } from "react-intl" import { RateDefinition } from "@/server/routers/hotels/output" import FlexibilityOption from "@/components/HotelReservation/SelectRate/RoomSelection/FlexibilityOption" -import { ChevronRightSmallIcon } from "@/components/Icons" -import Button from "@/components/TempDesignSystem/Button" import Body from "@/components/TempDesignSystem/Text/Body" import Caption from "@/components/TempDesignSystem/Text/Caption" import Footnote from "@/components/TempDesignSystem/Text/Footnote" import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" import ImageGallery from "../../ImageGallery" +import RoomSidePeek from "../RoomSidePeek" import styles from "./roomCard.module.css" @@ -83,16 +82,10 @@ export default function RoomCard({ : `${roomSize?.min}-${roomSize?.max}`} m² - +
diff --git a/components/HotelReservation/SelectRate/RoomSelection/RoomSidePeek/facilityIcon.ts b/components/HotelReservation/SelectRate/RoomSelection/RoomSidePeek/facilityIcon.ts new file mode 100644 index 000000000..d45ce7b30 --- /dev/null +++ b/components/HotelReservation/SelectRate/RoomSelection/RoomSidePeek/facilityIcon.ts @@ -0,0 +1,124 @@ +import { FC } from "react" + +import { + AcIcon, + BathtubIcon, + BedDoubleIcon, + ChairIcon, + CityIcon, + DeskIcon, + HairdryerIcon, + HandSoapIcon, + HeartIcon, + IronIcon, + MirrorIcon, + NatureIcon, + NoSmokingIcon, + SafetyBoxIcon, + ShowerIcon, + StreetIcon, + WifiIcon, + WindowCurtainsAltIcon, + WindowNotAvailableIcon, + WineBarIcon, + WoodFloorIcon, + YardIcon, +} from "@/components/Icons" + +import { IconProps } from "@/types/components/icon" + +export function getFacilityIcon(name: string): FC | null { + const iconMappings = [ + { + icon: DeskIcon, + texts: ["Desk and chair"], + }, + { + icon: HairdryerIcon, + texts: ["Hairdryer"], + }, + { + icon: AcIcon, + texts: ["Air Condition"], + }, + { + icon: ChairIcon, + texts: ["Armchair / armchairs"], + }, + { + icon: BathtubIcon, + texts: ["Bathroom with shower or bathtub"], + }, + { + icon: WindowCurtainsAltIcon, + texts: ["Blackout curtains"], + }, + { + icon: MirrorIcon, + texts: ["Cosmetic mirror"], + }, + { + icon: WifiIcon, + texts: ["Free WiFi"], + }, + { + icon: ChairIcon, + texts: ["Connecting rooms"], + }, + { + icon: YardIcon, + texts: ["View - atrium view"], + }, + { + icon: CityIcon, + texts: ["View - city view"], + }, + { + icon: NatureIcon, + texts: ["View - park view"], + }, + { + icon: StreetIcon, + texts: ["View - street view"], + }, + { + icon: WineBarIcon, + texts: ["Minibar"], + }, + { + icon: NoSmokingIcon, + texts: ["Non smoking"], + }, + { + icon: ShowerIcon, + texts: ["Rain shower"], + }, + { + icon: SafetyBoxIcon, + texts: ["Safety box"], + }, + { + icon: BedDoubleIcon, + texts: ["Set of two pillows"], + }, + { + icon: IronIcon, + texts: ["Iron and ironing board"], + }, + { + icon: HandSoapIcon, + texts: ["Toiletries"], + }, + { + icon: WoodFloorIcon, + texts: ["Wooden floor"], + }, + { + icon: WindowNotAvailableIcon, + texts: ["Not window"], + }, + ] + + const icon = iconMappings.find((icon) => icon.texts.includes(name)) + return icon ? icon.icon : HeartIcon +} diff --git a/components/HotelReservation/SelectRate/RoomSelection/RoomSidePeek/index.tsx b/components/HotelReservation/SelectRate/RoomSelection/RoomSidePeek/index.tsx new file mode 100644 index 000000000..f95626e6a --- /dev/null +++ b/components/HotelReservation/SelectRate/RoomSelection/RoomSidePeek/index.tsx @@ -0,0 +1,96 @@ +import { useState } from "react" +import { useIntl } from "react-intl" + +import { ChevronRightSmallIcon } from "@/components/Icons" +import Button from "@/components/TempDesignSystem/Button" +import SidePeek from "@/components/TempDesignSystem/SidePeek" +import Body from "@/components/TempDesignSystem/Text/Body" +import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" + +import ImageGallery from "../../ImageGallery" +import { getFacilityIcon } from "./facilityIcon" + +import styles from "./roomSidePeek.module.css" + +import type { RoomSidePeekProps } from "@/types/components/hotelReservation/selectRate/roomSidePeek" + +export default function RoomSidePeek({ + selectedRoom, + roomConfiguration, +}: RoomSidePeekProps) { + const [isSidePeekOpen, setIsSidePeekOpen] = useState(false) + const intl = useIntl() + + const roomSize = selectedRoom?.roomSize + const occupancy = selectedRoom?.occupancy.total + const roomDescription = selectedRoom?.descriptions.medium + const images = selectedRoom?.images + + return ( +
+ + + setIsSidePeekOpen(false)} + > + + {roomSize?.min === roomSize?.max + ? roomSize?.min + : `${roomSize?.min} - ${roomSize?.max}`} + m².{" "} + {intl.formatMessage( + { + id: "booking.accommodatesUpTo", + }, + { nrOfGuests: occupancy } + )} + + + {images && ( +
+ +
+ )} + + + {roomDescription} + + + {intl.formatMessage({ id: "booking.thisRoomIsEquippedWith" })} + +
    + {selectedRoom?.roomFacilities + .sort((a, b) => a.sortOrder - b.sortOrder) + .map((facility) => { + const Icon = getFacilityIcon(facility.name) + + return ( +
  • + {Icon && } + + {facility.name} + +
  • + ) + })} +
+
+
+ ) +} diff --git a/components/HotelReservation/SelectRate/RoomSelection/RoomSidePeek/roomSidePeek.module.css b/components/HotelReservation/SelectRate/RoomSelection/RoomSidePeek/roomSidePeek.module.css new file mode 100644 index 000000000..9197cb152 --- /dev/null +++ b/components/HotelReservation/SelectRate/RoomSelection/RoomSidePeek/roomSidePeek.module.css @@ -0,0 +1,29 @@ +.button { + margin-left: auto; + padding: 0 0 0 var(--Spacing-x-half); + text-decoration: none; +} + +.imageContainer { + min-height: 185px; + position: relative; +} + +.description { + margin-top: var(--Spacing-x-one-and-half); + margin-bottom: var(--Spacing-x2); +} +.facilityList { + margin-top: var(--Spacing-x-one-and-half); + column-count: 2; + column-gap: var(--Spacing-x2); +} +.facilityList li { + display: flex; + gap: var(--Spacing-x1); + margin-bottom: var(--Spacing-x-half); +} + +.noIcon { + margin-left: var(--Spacing-x4); +} diff --git a/components/Icons/Ac.tsx b/components/Icons/Ac.tsx new file mode 100644 index 000000000..5449112ca --- /dev/null +++ b/components/Icons/Ac.tsx @@ -0,0 +1,36 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function AcIcon({ className, color, ...props }: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + + + + + + ) +} diff --git a/components/Icons/Bathtub.tsx b/components/Icons/Bathtub.tsx new file mode 100644 index 000000000..26ab4ed54 --- /dev/null +++ b/components/Icons/Bathtub.tsx @@ -0,0 +1,36 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function BathtubIcon({ className, color, ...props }: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + + + + + + ) +} diff --git a/components/Icons/BedDouble.tsx b/components/Icons/BedDouble.tsx new file mode 100644 index 000000000..6eb59d7b0 --- /dev/null +++ b/components/Icons/BedDouble.tsx @@ -0,0 +1,40 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function BedDoubleIcon({ + className, + color, + ...props +}: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + + + + + + ) +} diff --git a/components/Icons/Chair.tsx b/components/Icons/Chair.tsx new file mode 100644 index 000000000..d7cdc81a2 --- /dev/null +++ b/components/Icons/Chair.tsx @@ -0,0 +1,36 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function ChairIcon({ className, color, ...props }: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + + + + + + ) +} diff --git a/components/Icons/City.tsx b/components/Icons/City.tsx new file mode 100644 index 000000000..791242ade --- /dev/null +++ b/components/Icons/City.tsx @@ -0,0 +1,36 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function CityIcon({ className, color, ...props }: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + + + + + + ) +} diff --git a/components/Icons/Desk.tsx b/components/Icons/Desk.tsx new file mode 100644 index 000000000..de9d79ac6 --- /dev/null +++ b/components/Icons/Desk.tsx @@ -0,0 +1,36 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function DeskIcon({ className, color, ...props }: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + + + + + + ) +} diff --git a/components/Icons/Hairdryer.tsx b/components/Icons/Hairdryer.tsx new file mode 100644 index 000000000..4d6ca72b2 --- /dev/null +++ b/components/Icons/Hairdryer.tsx @@ -0,0 +1,58 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function HairdryerIcon({ + className, + color, + ...props +}: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + + + + + + + + + + ) +} diff --git a/components/Icons/HandSoap.tsx b/components/Icons/HandSoap.tsx new file mode 100644 index 000000000..a6850e4fe --- /dev/null +++ b/components/Icons/HandSoap.tsx @@ -0,0 +1,49 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function HandSoapIcon({ + className, + color, + ...props +}: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + + + + + + + + + + + + + ) +} diff --git a/components/Icons/Iron.tsx b/components/Icons/Iron.tsx new file mode 100644 index 000000000..ac2ac4882 --- /dev/null +++ b/components/Icons/Iron.tsx @@ -0,0 +1,36 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function IronIcon({ className, color, ...props }: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + + + + + + ) +} diff --git a/components/Icons/Mirror.tsx b/components/Icons/Mirror.tsx new file mode 100644 index 000000000..f7f873a53 --- /dev/null +++ b/components/Icons/Mirror.tsx @@ -0,0 +1,25 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function MirrorIcon({ className, color, ...props }: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + ) +} diff --git a/components/Icons/SafetyBox.tsx b/components/Icons/SafetyBox.tsx new file mode 100644 index 000000000..2b79a063f --- /dev/null +++ b/components/Icons/SafetyBox.tsx @@ -0,0 +1,46 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function SafetyBoxIcon({ + className, + color, + ...props +}: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + + + + + + + ) +} diff --git a/components/Icons/Shower.tsx b/components/Icons/Shower.tsx new file mode 100644 index 000000000..432b5f346 --- /dev/null +++ b/components/Icons/Shower.tsx @@ -0,0 +1,36 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function ShowerIcon({ className, color, ...props }: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + + + + + + ) +} diff --git a/components/Icons/WindowCurtainsAlt.tsx b/components/Icons/WindowCurtainsAlt.tsx new file mode 100644 index 000000000..f32529566 --- /dev/null +++ b/components/Icons/WindowCurtainsAlt.tsx @@ -0,0 +1,40 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function WindowCurtainsAltIcon({ + className, + color, + ...props +}: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + + + + + + ) +} diff --git a/components/Icons/WindowNotAvailable.tsx b/components/Icons/WindowNotAvailable.tsx new file mode 100644 index 000000000..f064e146d --- /dev/null +++ b/components/Icons/WindowNotAvailable.tsx @@ -0,0 +1,52 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function WindowNotAvailableIcon({ + className, + color, + ...props +}: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + + + + + + + + ) +} diff --git a/components/Icons/WineBar.tsx b/components/Icons/WineBar.tsx new file mode 100644 index 000000000..a0ae499d1 --- /dev/null +++ b/components/Icons/WineBar.tsx @@ -0,0 +1,36 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function WineBarIcon({ className, color, ...props }: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + + + + + + ) +} diff --git a/components/Icons/WoodFloor.tsx b/components/Icons/WoodFloor.tsx new file mode 100644 index 000000000..e7eaa4f35 --- /dev/null +++ b/components/Icons/WoodFloor.tsx @@ -0,0 +1,84 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function WoodFloorIcon({ + className, + color, + ...props +}: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + + + + + + + + + + + + + + + + + ) +} diff --git a/components/Icons/Yard.tsx b/components/Icons/Yard.tsx new file mode 100644 index 000000000..9e853b4b0 --- /dev/null +++ b/components/Icons/Yard.tsx @@ -0,0 +1,36 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function YardIcon({ className, color, ...props }: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + + + + + + ) +} diff --git a/components/Icons/index.tsx b/components/Icons/index.tsx index e7547b178..fc7407ce8 100644 --- a/components/Icons/index.tsx +++ b/components/Icons/index.tsx @@ -1,3 +1,4 @@ +export { default as AcIcon } from "./Ac" export { default as AccesoriesIcon } from "./Accesories" export { default as AccessibilityIcon } from "./Accessibility" export { default as AccountCircleIcon } from "./AccountCircle" @@ -5,18 +6,22 @@ export { default as AirIcon } from "./Air" export { default as AirplaneIcon } from "./Airplane" export { default as ArrowRightIcon } from "./ArrowRight" export { default as BarIcon } from "./Bar" +export { default as BathtubIcon } from "./Bathtub" +export { default as BedDoubleIcon } from "./BedDouble" export { default as BikingIcon } from "./Biking" export { default as BreakfastIcon } from "./Breakfast" export { default as BusinessIcon } from "./Business" export { default as CalendarIcon } from "./Calendar" export { default as CameraIcon } from "./Camera" export { default as CellphoneIcon } from "./Cellphone" +export { default as ChairIcon } from "./Chair" export { default as CheckIcon } from "./Check" export { default as CheckCircleIcon } from "./CheckCircle" export { default as ChevronDownIcon } from "./ChevronDown" export { default as ChevronLeftIcon } from "./ChevronLeft" export { default as ChevronRightIcon } from "./ChevronRight" export { default as ChevronRightSmallIcon } from "./ChevronRightSmall" +export { default as CityIcon } from "./City" export { default as CloseIcon } from "./Close" export { default as CloseLargeIcon } from "./CloseLarge" export { default as CoffeeAltIcon } from "./CoffeeAlt" @@ -27,6 +32,7 @@ export { default as CreditCard } from "./CreditCard" export { default as CrossCircle } from "./CrossCircle" export { default as CulturalIcon } from "./Cultural" export { default as DeleteIcon } from "./Delete" +export { default as DeskIcon } from "./Desk" export { default as DoorOpenIcon } from "./DoorOpen" export { default as DownloadIcon } from "./Download" export { default as DresserIcon } from "./Dresser" @@ -46,6 +52,8 @@ export { default as GiftIcon } from "./Gift" export { default as GlobeIcon } from "./Globe" export { default as GolfIcon } from "./Golf" export { default as GroceriesIcon } from "./Groceries" +export { default as HairdryerIcon } from "./Hairdryer" +export { default as HandSoapIcon } from "./HandSoap" export { default as HangerIcon } from "./Hanger" export { default as HangerAltIcon } from "./HangerAlt" export { default as HeartIcon } from "./Heart" @@ -53,6 +61,8 @@ export { default as HeatIcon } from "./Heat" export { default as HouseIcon } from "./House" export { default as ImageIcon } from "./Image" export { default as InfoCircleIcon } from "./InfoCircle" +export { default as InstagramIcon } from "./Instagram" +export { default as IronIcon } from "./Iron" export { default as KayakingIcon } from "./Kayaking" export { default as KettleIcon } from "./Kettle" export { default as KingBedIcon } from "./KingBed" @@ -63,6 +73,7 @@ export { default as LocationIcon } from "./Location" export { default as LockIcon } from "./Lock" export { default as MapIcon } from "./Map" export { default as MinusIcon } from "./Minus" +export { default as MirrorIcon } from "./Mirror" export { default as MuseumIcon } from "./Museum" export { default as NatureIcon } from "./Nature" export { default as NightlifeIcon } from "./Nightlife" @@ -80,11 +91,13 @@ export { default as PriceTagIcon } from "./PriceTag" export { default as PrinterIcon } from "./Printer" export { default as RestaurantIcon } from "./Restaurant" export { default as RoomServiceIcon } from "./RoomService" +export { default as SafetyBoxIcon } from "./SafetyBox" export { default as SaunaIcon } from "./Sauna" export { default as ScandicLogoIcon } from "./ScandicLogo" export { default as SearchIcon } from "./Search" export { default as ServiceIcon } from "./Service" export { default as ShoppingIcon } from "./Shopping" +export { default as ShowerIcon } from "./Shower" export { default as SkateboardingIcon } from "./Skateboarding" export { default as SmokingIcon } from "./Smoking" export { default as SnowflakeIcon } from "./Snowflake" @@ -99,3 +112,8 @@ export { default as TshirtWashIcon } from "./TshirtWash" export { default as TvCastingIcon } from "./TvCasting" export { default as WarningTriangle } from "./WarningTriangle" export { default as WifiIcon } from "./Wifi" +export { default as WindowCurtainsAltIcon } from "./WindowCurtainsAlt" +export { default as WindowNotAvailableIcon } from "./WindowNotAvailable" +export { default as WineBarIcon } from "./WineBar" +export { default as WoodFloorIcon } from "./WoodFloor" +export { default as YardIcon } from "./Yard" diff --git a/components/Lightbox/Gallery.tsx b/components/Lightbox/Gallery.tsx index fa4c94a5a..23149d3de 100644 --- a/components/Lightbox/Gallery.tsx +++ b/components/Lightbox/Gallery.tsx @@ -1,6 +1,4 @@ "use client" -import { DialogTitle } from "@radix-ui/react-dialog" -import { VisuallyHidden } from "@radix-ui/react-visually-hidden" import { AnimatePresence, motion } from "framer-motion" import { ChevronRightIcon } from "@/components/Icons" @@ -16,7 +14,6 @@ import type { GalleryProps } from "@/types/components/lightbox/lightbox" export default function Gallery({ images, - dialogTitle, onClose, onSelectImage, onImageClick, @@ -57,11 +54,6 @@ export default function Gallery({ {/* Desktop Gallery */}
- - - {dialogTitle} - -
{mainImage.title && (
diff --git a/components/Lightbox/Lightbox.module.css b/components/Lightbox/Lightbox.module.css index f5446a2aa..ae46b5a0e 100644 --- a/components/Lightbox/Lightbox.module.css +++ b/components/Lightbox/Lightbox.module.css @@ -1,3 +1,13 @@ +@keyframes darken-background { + from { + background-color: rgba(0, 0, 0, 0); + } + + to { + background-color: rgba(0, 0, 0, 0.5); + } +} + .mobileGallery { height: 100%; position: relative; @@ -33,14 +43,22 @@ position: fixed; top: 50%; left: 50%; - z-index: 10; + z-index: var(--lightbox-z-index); } .overlay { position: fixed; inset: 0; background-color: rgba(0, 0, 0, 0.5); - z-index: 10; + z-index: var(--lightbox-z-index); +} + +.overlay[data-entering] { + animation: darken-background 0.2s; +} + +.overlay[data-exiting] { + animation: darken-background 0.2s reverse; } .galleryContainer { diff --git a/components/Lightbox/index.tsx b/components/Lightbox/index.tsx index b63f10693..f76063848 100644 --- a/components/Lightbox/index.tsx +++ b/components/Lightbox/index.tsx @@ -1,7 +1,7 @@ "use client" -import * as Dialog from "@radix-ui/react-dialog" import { AnimatePresence, motion } from "framer-motion" import React, { useState } from "react" +import { Dialog, Modal, ModalOverlay } from "react-aria-components" import FullView from "./FullView" import Gallery from "./Gallery" @@ -62,20 +62,16 @@ export default function Lightbox({ return ( <> {triggerElement} - - - {isOpen && ( - - - - - + + + + {isOpen && ( + )} - - - )} - - + + )} + + + ) } diff --git a/components/TempDesignSystem/SidePeek/sidePeek.module.css b/components/TempDesignSystem/SidePeek/sidePeek.module.css index 8282166c1..4c2bb9187 100644 --- a/components/TempDesignSystem/SidePeek/sidePeek.module.css +++ b/components/TempDesignSystem/SidePeek/sidePeek.module.css @@ -39,7 +39,7 @@ width: 100%; height: 100vh; background-color: var(--Base-Background-Primary-Normal); - z-index: 100; + z-index: var(--sidepeek-z-index); box-shadow: 0 0 10px rgba(0, 0, 0, 0.85); } diff --git a/components/TempDesignSystem/Text/Body/body.module.css b/components/TempDesignSystem/Text/Body/body.module.css index dd9b85156..85b286b3a 100644 --- a/components/TempDesignSystem/Text/Body/body.module.css +++ b/components/TempDesignSystem/Text/Body/body.module.css @@ -80,6 +80,10 @@ color: var(--UI-Text-High-contrast); } +.baseTextMediumContrast { + color: var(--Base-Text-Medium-contrast); +} + .white { color: var(--UI-Opacity-White-100); } diff --git a/components/TempDesignSystem/Text/Body/variants.ts b/components/TempDesignSystem/Text/Body/variants.ts index 1663e21f0..324d1baef 100644 --- a/components/TempDesignSystem/Text/Body/variants.ts +++ b/components/TempDesignSystem/Text/Body/variants.ts @@ -12,6 +12,7 @@ const config = { pale: styles.pale, red: styles.red, textMediumContrast: styles.textMediumContrast, + baseTextMediumContrast: styles.baseTextMediumContrast, textHighContrast: styles.textHighContrast, white: styles.white, peach50: styles.peach50, diff --git a/i18n/dictionaries/da.json b/i18n/dictionaries/da.json index 1bbfdcd6d..ee5954d7d 100644 --- a/i18n/dictionaries/da.json +++ b/i18n/dictionaries/da.json @@ -346,12 +346,14 @@ "Zoom in": "Zoom ind", "Zoom out": "Zoom ud", "as of today": "pr. dags dato", + "booking.accommodatesUpTo": "Plads til {nrOfGuests, plural, one {# person} other {op til # personer}}", "booking.adults": "{totalAdults, plural, one {# voksen} other {# voksne}}", "booking.children": "{totalChildren, plural, one {# barn} other {# børn}}", "booking.guests": "Maks {nrOfGuests, plural, one {# gæst} other {# gæster}}", "booking.nights": "{totalNights, plural, one {# nat} other {# nætter}}", "booking.rooms": "{totalRooms, plural, one {# værelse} other {# værelser}}", "booking.terms": "Ved at betale med en af de tilgængelige betalingsmetoder, accepterer jeg vilkårene for denne booking og de generelle Vilkår og betingelser, og forstår, at Scandic vil behandle min personlige data i forbindelse med denne booking i henhold til Scandics Privatlivspolitik. Jeg accepterer, at Scandic kræver et gyldigt kreditkort under min besøg i tilfælde af, at noget er tilbagebetalt.", + "booking.thisRoomIsEquippedWith": "Dette værelse er udstyret med", "by": "inden", "characters": "tegn", "guest": "gæst", diff --git a/i18n/dictionaries/de.json b/i18n/dictionaries/de.json index a5c32a198..9eb8bd1ec 100644 --- a/i18n/dictionaries/de.json +++ b/i18n/dictionaries/de.json @@ -346,12 +346,14 @@ "Zoom in": "Vergrößern", "Zoom out": "Verkleinern", "as of today": "Stand heute", + "booking.accommodatesUpTo": "Bietet Platz für {nrOfGuests, plural, one {# Person } other {bis zu # Personen}}", "booking.adults": "{totalAdults, plural, one {# erwachsene} other {# erwachsene}}", "booking.children": "{totalChildren, plural, one {# kind} other {# kinder}}", "booking.guests": "Max {nrOfGuests, plural, one {# gast} other {# gäste}}", "booking.nights": "{totalNights, plural, one {# nacht} other {# Nächte}}", "booking.rooms": "{totalRooms, plural, one {# zimmer} other {# räume}}", "booking.terms": "Ved at betale med en af de tilgængelige betalingsmetoder, accepterer jeg vilkårene for denne booking og de generelle Vilkår og betingelser, og forstår, at Scandic vil behandle min personlige data i forbindelse med denne booking i henhold til Scandics Privatlivspolitik. Jeg accepterer, at Scandic kræver et gyldigt kreditkort under min besøg i tilfælde af, at noget er tilbagebetalt.", + "booking.thisRoomIsEquippedWith": "Dieses Zimmer ist ausgestattet mit", "by": "bis", "characters": "figuren", "guest": "gast", diff --git a/i18n/dictionaries/en.json b/i18n/dictionaries/en.json index 2299d715b..f40909ac9 100644 --- a/i18n/dictionaries/en.json +++ b/i18n/dictionaries/en.json @@ -364,6 +364,7 @@ "Zoom in": "Zoom in", "Zoom out": "Zoom out", "as of today": "as of today", + "booking.accommodatesUpTo": "Accommodates up to {nrOfGuests, plural, one {# person} other {# people}}", "booking.adults": "{totalAdults, plural, one {# adult} other {# adults}}", "booking.children": "{totalChildren, plural, one {# child} other {# children}}", "booking.confirmation.text": "Thank you for booking with us! We look forward to welcoming you and hope you have a pleasant stay. If you have any questions or need to make changes to your reservation, please email us.", @@ -372,6 +373,7 @@ "booking.nights": "{totalNights, plural, one {# night} other {# nights}}", "booking.rooms": "{totalRooms, plural, one {# room} other {# rooms}}", "booking.terms": "By paying with any of the payment methods available, I accept the terms for this booking and the general Terms & Conditions, and understand that Scandic will process my personal data for this booking in accordance with Scandic's Privacy policy. I also accept that Scandic require a valid credit card during my visit in case anything is left unpaid.", + "booking.thisRoomIsEquippedWith": "This room is equipped with", "by": "by", "characters": "characters", "from": "from", diff --git a/i18n/dictionaries/fi.json b/i18n/dictionaries/fi.json index 8a98227fa..b44c6755d 100644 --- a/i18n/dictionaries/fi.json +++ b/i18n/dictionaries/fi.json @@ -347,12 +347,14 @@ "Zoom in": "Lähennä", "Zoom out": "Loitonna", "as of today": "tänään", + "booking.accommodatesUpTo": "Huoneeseen {nrOfGuests, plural, one {# person} other {mahtuu 2 henkilöä}}", "booking.adults": "{totalAdults, plural, one {# aikuinen} other {# aikuiset}}", "booking.children": "{totalChildren, plural, one {# lapsi} other {# lasta}}", "booking.guests": "Max {nrOfGuests, plural, one {# vieras} other {# vieraita}}", "booking.nights": "{totalNights, plural, one {# yö} other {# yötä}}", "booking.rooms": "{totalRooms, plural, one {# huone} other {# sviitti}}", "booking.terms": "Maksamalla minkä tahansa saatavilla olevan maksutavan avulla hyväksyn tämän varauksen ehdot ja yleiset ehdot ja ehtoja, ja ymmärrän, että Scandic käsittelee minun henkilötietoni tässä varauksessa mukaisesti Scandicin tietosuojavaltuuden mukaisesti. Hyväksyn myös, että Scandic vaatii validin luottokortin majoituksen ajan, jos jokin jää maksamatta.", + "booking.thisRoomIsEquippedWith": "Tämä huone on varustettu", "by": "mennessä", "characters": "hahmoja", "guest": "Vieras", diff --git a/i18n/dictionaries/no.json b/i18n/dictionaries/no.json index 2feec1e8c..ab4143986 100644 --- a/i18n/dictionaries/no.json +++ b/i18n/dictionaries/no.json @@ -344,11 +344,13 @@ "Zoom in": "Zoom inn", "Zoom out": "Zoom ut", "as of today": "per i dag", + "booking.accommodatesUpTo": "Plass til {nrOfGuests, plural, one {# person} other {opptil # personer}}", "booking.adults": "{totalAdults, plural, one {# voksen} other {# voksne}}", "booking.children": "{totalChildren, plural, one {# barn} other {# barn}}", "booking.guests": "Maks {nrOfGuests, plural, one {# gjest} other {# gjester}}", "booking.nights": "{totalNights, plural, one {# natt} other {# netter}}", "booking.rooms": "{totalRooms, plural, one {# rom} other {# rom}}", + "booking.thisRoomIsEquippedWith": "Dette rommet er utstyrt med", "by": "innen", "characters": "tegn", "guest": "gjest", diff --git a/i18n/dictionaries/sv.json b/i18n/dictionaries/sv.json index 300b0141d..9d7c3b95d 100644 --- a/i18n/dictionaries/sv.json +++ b/i18n/dictionaries/sv.json @@ -344,12 +344,14 @@ "Zoom in": "Zooma in", "Zoom out": "Zooma ut", "as of today": "från och med idag", + "booking.accommodatesUpTo": "Rymmer {nrOfGuests, plural, one {# person} other {upp till # personer}}", "booking.adults": "{totalAdults, plural, one {# vuxen} other {# vuxna}}", "booking.children": "{totalChildren, plural, one {# barn} other {# barn}}", "booking.guests": "Max {nrOfGuests, plural, one {# gäst} other {# gäster}}", "booking.nights": "{totalNights, plural, one {# natt} other {# nätter}}", "booking.rooms": "{totalRooms, plural, one {# rum} other {# rum}}", "booking.terms": "Genom att betala med någon av de tillgängliga betalningsmetoderna accepterar jag villkoren för denna bokning och de generella Villkoren och villkoren, och förstår att Scandic kommer att behandla min personliga data i samband med denna bokning i enlighet med Scandics integritetspolicy. Jag accepterar att Scandic kräver ett giltigt kreditkort under min besök i fall att något är tillbaka betalt.", + "booking.thisRoomIsEquippedWith": "Detta rum är utrustat med", "by": "innan", "characters": "tecken", "guest": "gäst", diff --git a/server/routers/hotels/schemas/room.ts b/server/routers/hotels/schemas/room.ts index bb3f7019c..19f922db0 100644 --- a/server/routers/hotels/schemas/room.ts +++ b/server/routers/hotels/schemas/room.ts @@ -89,5 +89,6 @@ export const roomSchema = z roomSize: data.attributes.roomSize, sortOrder: data.attributes.sortOrder, type: data.type, + roomFacilities: data.attributes.roomFacilities, } }) diff --git a/types/components/hotelReservation/selectRate/roomSidePeek.ts b/types/components/hotelReservation/selectRate/roomSidePeek.ts new file mode 100644 index 000000000..c526d04b4 --- /dev/null +++ b/types/components/hotelReservation/selectRate/roomSidePeek.ts @@ -0,0 +1,8 @@ +import { RoomConfiguration } from "@/server/routers/hotels/output" + +import { RoomData } from "@/types/hotel" + +export type RoomSidePeekProps = { + roomConfiguration: RoomConfiguration + selectedRoom?: RoomData +}