From 3c810d67a28a6a4fd17fc9247de43b7a7245400e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20J=C3=A4derberg?= Date: Fri, 4 Apr 2025 06:52:37 +0000 Subject: [PATCH] Merged in feature/SW-1736-foating-booking-widget (pull request #1696) Feature/SW-1736 floating booking widget * feature: Add floating booking widget on start page SW-1736 * fix: Make sure we don't try to use IntersectionObserver on the server * fix: make sure that we disconnect the intersectionobserver when dismounting * fix: pass searchparams to floating bookingwidget Approved-by: Michael Zetterberg --- .../(public)/[contentType]/[uid]/page.tsx | 2 +- .../components/BookingWidget/Client.tsx | 51 ++++++++++++--- .../FloatingBookingWidget.module.css | 27 ++++++++ .../FloatingBookingWidgetClient.tsx | 65 +++++++++++++++++++ .../FloatingBookingWidget/index.tsx | 23 +++++++ .../BookingWidget/bookingWidget.module.css | 14 +++- .../ContentType/StartPage/index.tsx | 9 ++- .../StartPage/startPage.module.css | 33 +++++++++- .../FormContent/Voucher/index.tsx | 4 +- .../FormContent/Voucher/voucher.module.css | 3 + .../FormContent/formContent.module.css | 3 + .../Forms/BookingWidget/FormContent/index.tsx | 4 +- .../Forms/BookingWidget/form.module.css | 8 +++ .../components/Forms/BookingWidget/index.tsx | 13 +++- .../Forms/BookingWidget/variants.ts | 1 + .../components/SkeletonShimmer/index.tsx | 3 + apps/scandic-web/utils/isBrowser.ts | 1 + 17 files changed, 243 insertions(+), 21 deletions(-) create mode 100644 apps/scandic-web/components/BookingWidget/FloatingBookingWidget/FloatingBookingWidget.module.css create mode 100644 apps/scandic-web/components/BookingWidget/FloatingBookingWidget/FloatingBookingWidgetClient.tsx create mode 100644 apps/scandic-web/components/BookingWidget/FloatingBookingWidget/index.tsx create mode 100644 apps/scandic-web/utils/isBrowser.ts diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/page.tsx index 49829fdc0..160b4360e 100644 --- a/apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/page.tsx +++ b/apps/scandic-web/app/[lang]/(live)/(public)/[contentType]/[uid]/page.tsx @@ -102,7 +102,7 @@ export default async function ContentTypePage({ if (env.HIDE_FOR_NEXT_RELEASE) { return notFound() } - return + return default: const type: never = params.contentType console.error(`Unsupported content type given: ${type}`) diff --git a/apps/scandic-web/components/BookingWidget/Client.tsx b/apps/scandic-web/components/BookingWidget/Client.tsx index 6c0fdbf19..90abd9a31 100644 --- a/apps/scandic-web/components/BookingWidget/Client.tsx +++ b/apps/scandic-web/components/BookingWidget/Client.tsx @@ -1,6 +1,7 @@ "use client" import { zodResolver } from "@hookform/resolvers/zod" +import { cva } from "class-variance-authority" import { use, useEffect, useRef, useState } from "react" import { FormProvider, useForm } from "react-hook-form" @@ -126,6 +127,17 @@ export default function BookingWidgetClient({ reValidateMode: "onSubmit", }) + useEffect(() => { + if (!selectedLocation) return + + /* + If `trpc.hotel.locations.get.useQuery` hasn't been fetched previously and is hence async + we need to update the default values when data is available + */ + methods.setValue("search", selectedLocation.name) + methods.setValue("location", JSON.stringify(selectedLocation)) + }, [selectedLocation, methods]) + function closeMobileSearch() { setIsOpen(false) document.body.style.overflowY = "visible" @@ -190,7 +202,7 @@ export default function BookingWidgetClient({ }, [methods, selectedBookingCode]) if (isLoading) { - return + return } if (!isSuccess || !locations) { @@ -198,13 +210,13 @@ export default function BookingWidgetClient({ return null } + const classNames = bookingWidgetContainerVariants({ + type, + }) + return ( -
+
{header.hero_image ? ( ) : null} +
{blocks.map((block, index) => { if (block.typename === BlocksEnums.block.FullWidthCampaign) { diff --git a/apps/scandic-web/components/ContentType/StartPage/startPage.module.css b/apps/scandic-web/components/ContentType/StartPage/startPage.module.css index 9968fe460..a836b536a 100644 --- a/apps/scandic-web/components/ContentType/StartPage/startPage.module.css +++ b/apps/scandic-web/components/ContentType/StartPage/startPage.module.css @@ -5,7 +5,7 @@ .header { height: 560px; position: relative; - overflow: hidden; + z-index: 10; } .header:after { @@ -34,7 +34,6 @@ @media screen and (min-width: 768px) { .headerContent { grid-gap: var(--Spacing-x4); - padding: 320px 160px 80px; } } @@ -42,6 +41,36 @@ max-width: 100%; } +.fauxBookingWidget { + height: 84px; + width: 100%; +} + +.floatingBookingWidgetContainer { + height: 0px; + width: 100vw; + display: flex; + justify-content: center; + background-color: green; +} + +.floatingBookingWidget { + background: pink; + transform: translateY(-155px); + height: fit-content; + width: 100%; + display: flex; + justify-content: center; + + &[data-intersecting="true"] { + background: white; + } + + & > * { + max-width: 100%; + } +} + .main { display: grid; gap: var(--Spacing-x6); diff --git a/apps/scandic-web/components/Forms/BookingWidget/FormContent/Voucher/index.tsx b/apps/scandic-web/components/Forms/BookingWidget/FormContent/Voucher/index.tsx index 4d92f30ba..439de6631 100644 --- a/apps/scandic-web/components/Forms/BookingWidget/FormContent/Voucher/index.tsx +++ b/apps/scandic-web/components/Forms/BookingWidget/FormContent/Voucher/index.tsx @@ -86,13 +86,13 @@ export function VoucherSkeleton() { return (
-
+
- +
diff --git a/apps/scandic-web/components/Forms/BookingWidget/FormContent/Voucher/voucher.module.css b/apps/scandic-web/components/Forms/BookingWidget/FormContent/Voucher/voucher.module.css index 4979a6f44..4bd9dc0e1 100644 --- a/apps/scandic-web/components/Forms/BookingWidget/FormContent/Voucher/voucher.module.css +++ b/apps/scandic-web/components/Forms/BookingWidget/FormContent/Voucher/voucher.module.css @@ -16,6 +16,9 @@ display: flex; flex-direction: column; } +.voucherSkeletonContainer { + padding: var(--Spacing-x1) var(--Spacing-x-one-and-half); +} .checkbox { width: 24px; diff --git a/apps/scandic-web/components/Forms/BookingWidget/FormContent/formContent.module.css b/apps/scandic-web/components/Forms/BookingWidget/FormContent/formContent.module.css index d5eb5f992..70bf30857 100644 --- a/apps/scandic-web/components/Forms/BookingWidget/FormContent/formContent.module.css +++ b/apps/scandic-web/components/Forms/BookingWidget/FormContent/formContent.module.css @@ -59,6 +59,9 @@ height: 60px; } } +.voucherContainer { + height: 100%; +} @media screen and (min-width: 768px) { .input { diff --git a/apps/scandic-web/components/Forms/BookingWidget/FormContent/index.tsx b/apps/scandic-web/components/Forms/BookingWidget/FormContent/index.tsx index 6ee9a2bf8..1d545d7ba 100644 --- a/apps/scandic-web/components/Forms/BookingWidget/FormContent/index.tsx +++ b/apps/scandic-web/components/Forms/BookingWidget/FormContent/index.tsx @@ -135,13 +135,13 @@ export function BookingWidgetFormContentSkeleton() { { totalNights: 0 } )} - +
{intl.formatMessage({ id: "Rooms & Guests" })} - +
diff --git a/apps/scandic-web/components/Forms/BookingWidget/form.module.css b/apps/scandic-web/components/Forms/BookingWidget/form.module.css index d8c0cb4e2..79676b9a0 100644 --- a/apps/scandic-web/components/Forms/BookingWidget/form.module.css +++ b/apps/scandic-web/components/Forms/BookingWidget/form.module.css @@ -34,9 +34,17 @@ .full { padding: var(--Spacing-x1) 0; } + .form { width: 100%; max-width: var(--max-width-page); margin: 0 auto; } + + .compact { + width: 1160px; + padding: var(--Spacing-x-one-and-half) var(--Spacing-x2) + var(--Spacing-x-one-and-half) var(--Spacing-x1); + white-space: nowrap; + } } diff --git a/apps/scandic-web/components/Forms/BookingWidget/index.tsx b/apps/scandic-web/components/Forms/BookingWidget/index.tsx index 28a52f2ac..d11ca0d08 100644 --- a/apps/scandic-web/components/Forms/BookingWidget/index.tsx +++ b/apps/scandic-web/components/Forms/BookingWidget/index.tsx @@ -15,7 +15,10 @@ import { bookingWidgetVariants } from "./variants" import styles from "./form.module.css" -import type { BookingWidgetSchema } from "@/types/components/bookingWidget" +import type { + BookingWidgetSchema, + BookingWidgetType, +} from "@/types/components/bookingWidget" import type { BookingWidgetFormProps } from "@/types/components/form/bookingwidget" import type { Location } from "@/types/trpc/routers/hotel/locations" @@ -85,9 +88,13 @@ export default function Form({ ) } -export function BookingWidgetFormSkeleton() { +export function BookingWidgetFormSkeleton({ + type, +}: { + type: BookingWidgetType +}) { const classNames = bookingWidgetVariants({ - type: "full", + type, }) return ( diff --git a/apps/scandic-web/components/Forms/BookingWidget/variants.ts b/apps/scandic-web/components/Forms/BookingWidget/variants.ts index d31fd9643..7bbada7a8 100644 --- a/apps/scandic-web/components/Forms/BookingWidget/variants.ts +++ b/apps/scandic-web/components/Forms/BookingWidget/variants.ts @@ -7,6 +7,7 @@ export const bookingWidgetVariants = cva(styles.section, { type: { default: styles.default, full: styles.full, + compact: styles.compact, }, }, defaultVariants: { diff --git a/apps/scandic-web/components/SkeletonShimmer/index.tsx b/apps/scandic-web/components/SkeletonShimmer/index.tsx index ea9ba325f..3c6d7cc6f 100644 --- a/apps/scandic-web/components/SkeletonShimmer/index.tsx +++ b/apps/scandic-web/components/SkeletonShimmer/index.tsx @@ -18,10 +18,12 @@ export default function SkeletonShimmer({ height, width, contrast = "light", + display = "initial", }: { height?: string width?: string contrast?: "light" | "dark" + display?: "block" | "inline-block" | "initial" }) { return ( ) diff --git a/apps/scandic-web/utils/isBrowser.ts b/apps/scandic-web/utils/isBrowser.ts new file mode 100644 index 000000000..c6e4fac54 --- /dev/null +++ b/apps/scandic-web/utils/isBrowser.ts @@ -0,0 +1 @@ +export const isBrowser = typeof window !== "undefined" && !("Deno" in window)