diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/@modal/(.)map/modal.tsx b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/@modal/(.)map/modal.tsx deleted file mode 100644 index ab8e0a451..000000000 --- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/@modal/(.)map/modal.tsx +++ /dev/null @@ -1,30 +0,0 @@ -"use client" - -import { useRouter } from "next/navigation" -import { type ElementRef, useEffect, useRef } from "react" - -export function Modal({ children }: { children: React.ReactNode }) { - const router = useRouter() - const dialogRef = useRef>(null) - - console.log("modal is open") - - useEffect(() => { - if (!dialogRef.current?.open) { - dialogRef.current?.showModal() - } - }, []) - - function onDismiss() { - router.back() - } - - return ( -
- - {children} - -
- ) -} diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/@modal/(.)map/page.tsx b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/@modal/(.)map/page.tsx index 6df8e0fec..f2c2ab55f 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/@modal/(.)map/page.tsx +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/@modal/(.)map/page.tsx @@ -4,7 +4,7 @@ import { env } from "@/env/server" import { getLocations } from "@/lib/trpc/memoizedRequests" import SelectHotelMap from "@/components/HotelReservation/SelectHotel/SelectHotelMap" -import getHotelReservationQueryParams from "@/components/HotelReservation/SelectRate/RoomSelection/utils" +import { getHotelReservationQueryParams } from "@/components/HotelReservation/SelectRate/RoomSelection/utils" import { MapModal } from "@/components/MapModal" import { setLang } from "@/i18n/serverContext" diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/layout.module.css b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/layout.module.css index 0969a7151..b86e58a72 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/layout.module.css +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/layout.module.css @@ -1,4 +1,5 @@ .layout { min-height: 100dvh; background-color: var(--Base-Background-Primary-Normal); + position: relative; } diff --git a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/map/page.tsx b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/map/page.tsx index 4c09e3bd8..5d0d9e5c4 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/map/page.tsx +++ b/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/map/page.tsx @@ -10,7 +10,7 @@ import { getPointOfInterests, } from "@/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/utils" import SelectHotelMap from "@/components/HotelReservation/SelectHotel/SelectHotelMap" -import getHotelReservationQueryParams from "@/components/HotelReservation/SelectRate/RoomSelection/utils" +import { getHotelReservationQueryParams } from "@/components/HotelReservation/SelectRate/RoomSelection/utils" import { setLang } from "@/i18n/serverContext" import styles from "./page.module.css" diff --git a/components/HotelReservation/SelectHotel/SelectHotelMap/index.tsx b/components/HotelReservation/SelectHotel/SelectHotelMap/index.tsx index cd63a00bf..3109d5cc3 100644 --- a/components/HotelReservation/SelectHotel/SelectHotelMap/index.tsx +++ b/components/HotelReservation/SelectHotel/SelectHotelMap/index.tsx @@ -1,11 +1,12 @@ "use client" import { APIProvider } from "@vis.gl/react-google-maps" +import { useRouter } from "next/navigation" import { useState } from "react" import { useIntl } from "react-intl" import { selectHotel } from "@/constants/routes/hotelReservation" -import { CloseIcon } from "@/components/Icons" +import { CloseIcon, CloseLargeIcon } from "@/components/Icons" import InteractiveMap from "@/components/Maps/InteractiveMap" import Button from "@/components/TempDesignSystem/Button" import Link from "@/components/TempDesignSystem/Link" @@ -23,38 +24,38 @@ export default function SelectHotelMap({ pointsOfInterest, mapId, }: SelectHotelMapProps) { + const router = useRouter() const lang = useLang() const intl = useIntl() const [activePoi, setActivePoi] = useState(null) + function onDismiss() { + router.back() + } + const closeButton = ( ) return (
Filter and sort {/* TODO: Add filter and sort button */} diff --git a/components/HotelReservation/SelectHotel/SelectHotelMap/selectHotelMap.module.css b/components/HotelReservation/SelectHotel/SelectHotelMap/selectHotelMap.module.css index 7892f77bd..adb35a386 100644 --- a/components/HotelReservation/SelectHotel/SelectHotelMap/selectHotelMap.module.css +++ b/components/HotelReservation/SelectHotel/SelectHotelMap/selectHotelMap.module.css @@ -9,7 +9,7 @@ display: flex; justify-content: space-between; align-items: center; - position: absolute; + position: relative; top: 0; left: 0; right: 0; @@ -18,6 +18,10 @@ padding: 0 var(--Spacing-x2); } +.filterContainer .closeButton { + color: var(--UI-Text-High-Contrast); +} + @media (min-width: 768px) { .closeButton { display: flex !important; diff --git a/components/MapModal/index.tsx b/components/MapModal/index.tsx index 8064355cb..ddedd622f 100644 --- a/components/MapModal/index.tsx +++ b/components/MapModal/index.tsx @@ -1,43 +1,88 @@ "use client" import { useRouter } from "next/navigation" -import { useEffect, useRef, useState } from "react" +import { useCallback, useEffect, useRef, useState } from "react" import { Dialog, Modal } from "react-aria-components" +import { useHandleKeyUp } from "@/hooks/useHandleKeyUp" +import { debounce } from "@/utils/debounce" + import styles from "./mapModal.module.css" export function MapModal({ children }: { children: React.ReactNode }) { const router = useRouter() + const [mapHeight, setMapHeight] = useState("0px") + const [mapTop, setMapTop] = useState("0px") + const [scrollHeightWhenOpened, setScrollHeightWhenOpened] = useState(0) - const hasMounted = useRef(false) + + const rootDiv = useRef(null) function onDismiss() { router.back() } - // Making sure the map is always opened at the top of the page, just below the header. + useHandleKeyUp((event: KeyboardEvent) => { + if (event.key === "Escape") { + onDismiss() + } + }) + + // Calculate the height of the map based on the viewport height from the start-point (below the header and booking widget) + const handleMapHeight = useCallback(() => { + const topPosition = rootDiv.current?.getBoundingClientRect().top ?? 0 + const scrollY = window.scrollY + setMapHeight(`calc(100dvh - ${topPosition + scrollY}px)`) + setMapTop(`${topPosition + scrollY}px`) + }, []) + + // Making sure the map is always opened at the top of the page, + // just below the header and booking widget as these should stay visible. // When closing, the page should scroll back to the position it was before opening the map. useEffect(() => { // Skip the first render - if (!hasMounted.current) { - hasMounted.current = true + if (!rootDiv.current) { return } if (scrollHeightWhenOpened === 0) { - setScrollHeightWhenOpened(window.scrollY) + const scrollY = window.scrollY + setScrollHeightWhenOpened(scrollY) window.scrollTo({ top: 0, behavior: "instant" }) } - }, [scrollHeightWhenOpened]) + }, [scrollHeightWhenOpened, rootDiv]) + + useEffect(() => { + const debouncedResizeHandler = debounce(function () { + handleMapHeight() + }) + + const observer = new ResizeObserver(debouncedResizeHandler) + + observer.observe(document.documentElement) + + return () => { + if (observer) { + observer.unobserve(document.documentElement) + } + } + }, [rootDiv, handleMapHeight]) return ( - - - {children} - - - +
+ + + {children} + + +
) } diff --git a/components/MapModal/mapModal.module.css b/components/MapModal/mapModal.module.css index 31029868e..3000d4673 100644 --- a/components/MapModal/mapModal.module.css +++ b/components/MapModal/mapModal.module.css @@ -1,15 +1,21 @@ .dynamicMap { - position: fixed; - top: calc( - var(--main-menu-mobile-height) + var(--booking-widget-mobile-height) - 4px - ); - right: 0; - bottom: 0; + --hotel-map-height: 100dvh; + --hotel-map-top: 0px; + position: absolute; + top: var(--hotel-map-top); left: 0; - z-index: var(--dialog-z-index); + height: var(--hotel-map-height); + width: 100dvw; + z-index: var(--hotel-dynamic-map-z-index); display: flex; + flex-direction: column; background-color: var(--Base-Surface-Primary-light-Normal); } +.wrapper { + position: absolute; + top: 0; + left: 0; +} @media screen and (min-width: 768px) { .dynamicMap { diff --git a/components/Maps/InteractiveMap/interactiveMap.module.css b/components/Maps/InteractiveMap/interactiveMap.module.css index 557730bfe..471409188 100644 --- a/components/Maps/InteractiveMap/interactiveMap.module.css +++ b/components/Maps/InteractiveMap/interactiveMap.module.css @@ -1,6 +1,7 @@ .mapContainer { --button-box-shadow: 0 0 8px 1px rgba(0, 0, 0, 0.1); width: 100%; + height: 100%; position: relative; z-index: 0; }