diff --git a/components/ContentType/HotelPage/Rooms/RoomCard/index.tsx b/components/ContentType/HotelPage/Rooms/RoomCard/index.tsx index b6784513a..dba816cb5 100644 --- a/components/ContentType/HotelPage/Rooms/RoomCard/index.tsx +++ b/components/ContentType/HotelPage/Rooms/RoomCard/index.tsx @@ -1,24 +1,23 @@ "use client" +import Link from "next/link" import { useIntl } from "react-intl" -import useSidePeekStore from "@/stores/sidepeek" - import { ChevronRightSmallIcon } from "@/components/Icons" import ImageGallery from "@/components/ImageGallery" import Button from "@/components/TempDesignSystem/Button" import Body from "@/components/TempDesignSystem/Text/Body" import Subtitle from "@/components/TempDesignSystem/Text/Subtitle" +import { getRoomNameAsParam } from "../../utils" + import styles from "./roomCard.module.css" import type { RoomCardProps } from "@/types/components/hotelPage/room" -import { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek" -export function RoomCard({ hotelId, room }: RoomCardProps) { +export function RoomCard({ room }: RoomCardProps) { const { images, name, roomSize, occupancy } = room const intl = useIntl() - const openSidePeek = useSidePeekStore((state) => state.openSidePeek) const size = roomSize?.min === roomSize?.max @@ -51,21 +50,11 @@ export function RoomCard({ hotelId, room }: RoomCardProps) { )} - diff --git a/components/ContentType/HotelPage/Rooms/index.tsx b/components/ContentType/HotelPage/Rooms/index.tsx index 325f60eb6..e976ee8af 100644 --- a/components/ContentType/HotelPage/Rooms/index.tsx +++ b/components/ContentType/HotelPage/Rooms/index.tsx @@ -15,7 +15,7 @@ import styles from "./rooms.module.css" import type { RoomsProps } from "@/types/components/hotelPage/room" import { HotelHashValues } from "@/types/components/hotelPage/tabNavigation" -export function Rooms({ hotelId, rooms }: RoomsProps) { +export function Rooms({ rooms }: RoomsProps) { const intl = useIntl() const showToggleButton = rooms.length > 3 const [allRoomsVisible, setAllRoomsVisible] = useState(!showToggleButton) @@ -45,7 +45,7 @@ export function Rooms({ hotelId, rooms }: RoomsProps) { > {rooms.map((room) => (
- +
))} diff --git a/components/ContentType/HotelPage/SidePeeks/Room/index.tsx b/components/ContentType/HotelPage/SidePeeks/Room/index.tsx new file mode 100644 index 000000000..ded1acf8d --- /dev/null +++ b/components/ContentType/HotelPage/SidePeeks/Room/index.tsx @@ -0,0 +1,118 @@ +import Link from "next/link" + +import ImageGallery from "@/components/ImageGallery" +import { getBedIcon } from "@/components/SidePeeks/RoomSidePeek/bedIcon" +import { getFacilityIcon } from "@/components/SidePeeks/RoomSidePeek/facilityIcon" +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 { getIntl } from "@/i18n" + +import { getRoomNameAsParam } from "../../utils" + +import styles from "./room.module.css" + +import type { RoomSidePeekProps } from "@/types/components/hotelPage/sidepeek/room" + +export default async function RoomSidePeek({ room }: RoomSidePeekProps) { + const intl = await getIntl() + const { roomSize, occupancy, descriptions, images } = room + const roomDescription = descriptions.medium + const totalOccupancy = occupancy.total + // TODO: Not defined where this should lead. + const ctaUrl = "" + + return ( + +
+
+ + {roomSize.min === roomSize.max + ? roomSize.min + : `${roomSize.min} - ${roomSize.max}`} + m².{" "} + {intl.formatMessage( + { id: "booking.accommodatesUpTo" }, + { nrOfGuests: totalOccupancy } + )} + +
+ +
+ {roomDescription} +
+ +
+ +

+ {intl.formatMessage({ id: "booking.thisRoomIsEquippedWith" })} +

+
+
    + {room.roomFacilities + .sort((a, b) => a.sortOrder - b.sortOrder) + .map((facility) => { + const Icon = getFacilityIcon(facility.icon) + return ( +
  • + {Icon && ( + + )} + + {facility.name} + +
  • + ) + })} +
+
+ +
+ +

{intl.formatMessage({ id: "booking.bedOptions" })}

+
+ + {intl.formatMessage({ id: "booking.basedOnAvailability" })} + +
    + {room.roomTypes.map((roomType) => { + const BedIcon = getBedIcon(roomType.mainBed.type) + return ( +
  • + {BedIcon && ( + + )} + + {roomType.mainBed.description} + +
  • + ) + })} +
+
+
+ {ctaUrl && ( +
+ +
+ )} +
+ ) +} diff --git a/components/ContentType/HotelPage/SidePeeks/Room/room.module.css b/components/ContentType/HotelPage/SidePeeks/Room/room.module.css new file mode 100644 index 000000000..2996dd8f2 --- /dev/null +++ b/components/ContentType/HotelPage/SidePeeks/Room/room.module.css @@ -0,0 +1,48 @@ +.content { + display: grid; + gap: var(--Spacing-x2); + position: relative; + margin-bottom: calc( + var(--Spacing-x4) * 2 + 80px + ); /* Creates space between the wrapper and buttonContainer */ +} +.innerContent { + display: grid; + gap: var(--Spacing-x-one-and-half); +} + +.imageContainer { + position: relative; + border-radius: var(--Corner-radius-Medium); + overflow: hidden; +} + +.facilityList { + column-count: 2; + column-gap: var(--Spacing-x2); +} + +.bedOptions { + display: flex; + flex-direction: column; +} + +.listItem { + display: flex; + gap: var(--Spacing-x1); + margin-bottom: var(--Spacing-x-half); +} + +.noIcon { + margin-left: var(--Spacing-x4); +} + +.buttonContainer { + background-color: var(--Base-Background-Primary-Normal); + border-top: 1px solid var(--Base-Border-Subtle); + padding: var(--Spacing-x4) var(--Spacing-x2); + width: 100%; + position: absolute; + left: 0; + bottom: 0; +} diff --git a/components/ContentType/HotelPage/SidePeeks/index.ts b/components/ContentType/HotelPage/SidePeeks/index.ts index 9990bd96b..5da71bbcd 100644 --- a/components/ContentType/HotelPage/SidePeeks/index.ts +++ b/components/ContentType/HotelPage/SidePeeks/index.ts @@ -1,2 +1,3 @@ export { default as AboutTheHotelSidePeek } from "./AboutTheHotel" +export { default as RoomSidePeek } from "./Room" export { default as WellnessAndExerciseSidePeek } from "./WellnessAndExercise" diff --git a/components/ContentType/HotelPage/index.tsx b/components/ContentType/HotelPage/index.tsx index 09143ce01..969d75936 100644 --- a/components/ContentType/HotelPage/index.tsx +++ b/components/ContentType/HotelPage/index.tsx @@ -1,11 +1,15 @@ import { notFound } from "next/navigation" -import hotelPageParams from "@/constants/routes/hotelPageParams" +import { + activities, + amenities, + meetingsAndConferences, + restaurantAndBar, +} from "@/constants/routes/hotelPageParams" import { env } from "@/env/server" import { getHotelData, getHotelPage } from "@/lib/trpc/memoizedRequests" import AccordionSection from "@/components/Blocks/Accordion" -import HotelReservationSidePeek from "@/components/HotelReservation/SidePeek" import SidePeekProvider from "@/components/SidePeeks/SidePeekProvider" import Alert from "@/components/TempDesignSystem/Alert" import SidePeek from "@/components/TempDesignSystem/SidePeek" @@ -24,7 +28,11 @@ import Facilities from "./Facilities" import IntroSection from "./IntroSection" import PreviewImages from "./PreviewImages" import { Rooms } from "./Rooms" -import { AboutTheHotelSidePeek, WellnessAndExerciseSidePeek } from "./SidePeeks" +import { + AboutTheHotelSidePeek, + RoomSidePeek, + WellnessAndExerciseSidePeek, +} from "./SidePeeks" import TabNavigation from "./TabNavigation" import styles from "./hotelPage.module.css" @@ -144,7 +152,7 @@ export default async function HotelPage({ hotelId }: HotelPageProps) { ) : null} - + {faq.accordions.length > 0 && ( @@ -169,9 +177,8 @@ export default async function HotelPage({ hotelId }: HotelPageProps) { ) : null} - {/* eslint-disable import/no-named-as-default-member */} {/* TODO: Render amenities as per the design. */} @@ -186,7 +193,7 @@ export default async function HotelPage({ hotelId }: HotelPageProps) { descriptions={hotelContent.texts} /> {/* TODO */} @@ -197,22 +204,23 @@ export default async function HotelPage({ hotelId }: HotelPageProps) { buttonUrl="#" /> {/* TODO */} Activities {/* TODO */} Meetings & Conferences - {/* eslint-enable import/no-named-as-default-member */} + {roomCategories.map((room) => ( + + ))} - ) } diff --git a/components/ContentType/HotelPage/utils.ts b/components/ContentType/HotelPage/utils.ts new file mode 100644 index 000000000..b10db9afd --- /dev/null +++ b/components/ContentType/HotelPage/utils.ts @@ -0,0 +1,3 @@ +export function getRoomNameAsParam(roomName: string) { + return roomName.replace(/[()]/g, "").replaceAll(" ", "-").toLowerCase() +} diff --git a/types/components/hotelPage/room.ts b/types/components/hotelPage/room.ts index f8faaecd8..7be59609d 100644 --- a/types/components/hotelPage/room.ts +++ b/types/components/hotelPage/room.ts @@ -1,11 +1,9 @@ import type { RoomData } from "@/types/hotel" export interface RoomCardProps { - hotelId: string room: RoomData } export type RoomsProps = { - hotelId: string rooms: RoomData[] } diff --git a/types/components/hotelPage/sidepeek/room.ts b/types/components/hotelPage/sidepeek/room.ts new file mode 100644 index 000000000..7ff699273 --- /dev/null +++ b/types/components/hotelPage/sidepeek/room.ts @@ -0,0 +1,5 @@ +import type { RoomData } from "@/types/hotel" + +export interface RoomSidePeekProps { + room: RoomData +}