From 2ef2b2e28da56e07d9b9972558bab2618462e1d3 Mon Sep 17 00:00:00 2001 From: Erik Tiekstra Date: Tue, 11 Mar 2025 06:33:04 +0000 Subject: [PATCH] Merged in feat/SW-1230-meeting-booking-widget (pull request #1507) feat(SW-1230): Added meeting booking widget to hotel meeting pages * feat(SW-1230): Added meeting booking widget to hotel meeting pages Approved-by: Fredrik Thorsson --- .../HotelSubpage/MeetingWidget/index.tsx | 31 +++ .../MeetingWidget/meetingWidget.module.css | 13 + .../HotelSubpage/hotelSubpage.module.css | 6 - .../ContentType/HotelSubpage/index.tsx | 13 +- .../MeetingPackageWidget/Skeleton/index.tsx | 21 ++ .../Skeleton/skeleton.module.css | 20 ++ .../components/MeetingPackageWidget/index.tsx | 54 +++++ .../meetingPackageWidget.module.css | 16 ++ .../components/MeetingPackageWidget/utils.ts | 226 ++++++++++++++++++ apps/scandic-web/stores/sticky-position.ts | 2 + 10 files changed, 387 insertions(+), 15 deletions(-) create mode 100644 apps/scandic-web/components/ContentType/HotelSubpage/MeetingWidget/index.tsx create mode 100644 apps/scandic-web/components/ContentType/HotelSubpage/MeetingWidget/meetingWidget.module.css create mode 100644 apps/scandic-web/components/MeetingPackageWidget/Skeleton/index.tsx create mode 100644 apps/scandic-web/components/MeetingPackageWidget/Skeleton/skeleton.module.css create mode 100644 apps/scandic-web/components/MeetingPackageWidget/index.tsx create mode 100644 apps/scandic-web/components/MeetingPackageWidget/meetingPackageWidget.module.css create mode 100644 apps/scandic-web/components/MeetingPackageWidget/utils.ts diff --git a/apps/scandic-web/components/ContentType/HotelSubpage/MeetingWidget/index.tsx b/apps/scandic-web/components/ContentType/HotelSubpage/MeetingWidget/index.tsx new file mode 100644 index 000000000..db6abecc2 --- /dev/null +++ b/apps/scandic-web/components/ContentType/HotelSubpage/MeetingWidget/index.tsx @@ -0,0 +1,31 @@ +"use client" + +import { useRef } from "react" + +import { StickyElementNameEnum } from "@/stores/sticky-position" + +import MeetingPackageWidget from "@/components/MeetingPackageWidget" +import useStickyPosition from "@/hooks/useStickyPosition" + +import styles from "./meetingWidget.module.css" + +interface MeetingWidgetProps { + hotelId: string +} + +export function MeetingWidget({ hotelId }: MeetingWidgetProps) { + const ref = useRef(null) + useStickyPosition({ + ref, + name: StickyElementNameEnum.MEETING_BOOKING_WIDGET, + }) + + return ( +
+ +
+ ) +} diff --git a/apps/scandic-web/components/ContentType/HotelSubpage/MeetingWidget/meetingWidget.module.css b/apps/scandic-web/components/ContentType/HotelSubpage/MeetingWidget/meetingWidget.module.css new file mode 100644 index 000000000..9c3125467 --- /dev/null +++ b/apps/scandic-web/components/ContentType/HotelSubpage/MeetingWidget/meetingWidget.module.css @@ -0,0 +1,13 @@ +.wrapper { + position: sticky; + top: 0; + background-color: var(--Base-Surface-Primary-light-Normal); + box-shadow: 0px 16px 24px 0px rgba(0, 0, 0, 0.08); + z-index: var(--booking-widget-z-index); +} + +.meetingPackageWidget { + width: 100%; + max-width: var(--max-width-page); + margin: 0 auto; +} diff --git a/apps/scandic-web/components/ContentType/HotelSubpage/hotelSubpage.module.css b/apps/scandic-web/components/ContentType/HotelSubpage/hotelSubpage.module.css index 93f7c4503..1487ee692 100644 --- a/apps/scandic-web/components/ContentType/HotelSubpage/hotelSubpage.module.css +++ b/apps/scandic-web/components/ContentType/HotelSubpage/hotelSubpage.module.css @@ -43,12 +43,6 @@ grid-column: 1; } -.meetingBookingWidget { - padding: var(--Spacing-x4); - background-color: var(--Base-Surface-Primary-dark-Normal); - text-align: center; -} - .buttonContainer { position: sticky; padding: var(--Spacing-x3) var(--Spacing-x2); diff --git a/apps/scandic-web/components/ContentType/HotelSubpage/index.tsx b/apps/scandic-web/components/ContentType/HotelSubpage/index.tsx index 2e6f486a0..9989273c8 100644 --- a/apps/scandic-web/components/ContentType/HotelSubpage/index.tsx +++ b/apps/scandic-web/components/ContentType/HotelSubpage/index.tsx @@ -20,6 +20,7 @@ import { getLang } from "@/i18n/serverContext" import MeetingsAdditionalContent from "./AdditionalContent/Meetings" import HotelSubpageAdditionalContent from "./AdditionalContent" import HtmlContent from "./HtmlContent" +import { MeetingWidget } from "./MeetingWidget" import HotelSubpageSidebar from "./Sidebar" import { getSubpageData, verifySubpageShouldExist } from "./utils" @@ -55,24 +56,19 @@ export default async function HotelSubpage({ let meetingRooms if (hotelData.additionalData.meetingRooms.nameInUrl === subpage) { - meetingRooms = await getMeetingRooms({ hotelId: hotelId, language: lang }) + meetingRooms = await getMeetingRooms({ hotelId, language: lang }) } const restaurantButton = restaurants.find( (restaurant) => restaurant.nameInUrl === subpage ) - const meetingBookingWidget = meetingRooms ? ( -
- Booking Widget Placeholder -
- ) : null - return ( <>
+ {meetingRooms && }
}> - {pageData.heroImage || meetingBookingWidget ? ( + {pageData.heroImage ? (
- {meetingBookingWidget} {pageData.heroImage && ( +
+ +
+
+ + + + + + +
+ + ) +} diff --git a/apps/scandic-web/components/MeetingPackageWidget/Skeleton/skeleton.module.css b/apps/scandic-web/components/MeetingPackageWidget/Skeleton/skeleton.module.css new file mode 100644 index 000000000..76c6bdba0 --- /dev/null +++ b/apps/scandic-web/components/MeetingPackageWidget/Skeleton/skeleton.module.css @@ -0,0 +1,20 @@ +.mobile, +.desktop { + padding: var(--Spacing-x2) 0; + background-color: var(--Base-Surface-Primary-light-Normal); +} + +.desktop { + display: none; +} + +/* Meeting booking widget changes design at 948px */ +@media screen and (min-width: 948px) { + .mobile { + display: none; + } + .desktop { + display: flex; + gap: var(--Spacing-x2); + } +} diff --git a/apps/scandic-web/components/MeetingPackageWidget/index.tsx b/apps/scandic-web/components/MeetingPackageWidget/index.tsx new file mode 100644 index 000000000..8a1f4e783 --- /dev/null +++ b/apps/scandic-web/components/MeetingPackageWidget/index.tsx @@ -0,0 +1,54 @@ +"use client" + +import Script from "next/script" +import { useState } from "react" + +import useLang from "@/hooks/useLang" + +import MeetingPackageWidgetSkeleton from "./Skeleton" +import { meetingPackageDestinationByHotelId } from "./utils" + +import styles from "./meetingPackageWidget.module.css" + +const SOURCE = "https://bookingengine-mp.s3.eu-west-2.amazonaws.com/script.js" + +interface MeetingPackageWidgetProps { + hotelId?: string + className?: string +} + +export default function MeetingPackageWidget({ + hotelId, + className = "", +}: MeetingPackageWidgetProps) { + const lang = useLang() + const [isLoading, setIsLoading] = useState(true) + const destination = hotelId + ? meetingPackageDestinationByHotelId[hotelId] + : undefined + + function handleOnReady() { + setIsLoading(false) + } + + return ( +
+ {isLoading && } + +
+