@@ -78,7 +136,7 @@ export default function FilterAndSortModal({
intent="primary"
size="medium"
theme="base"
- onClick={close}
+ onClick={() => handleApplyFiltersAndSorting(close)}
>
{intl.formatMessage(
{ id: "See results" },
diff --git a/components/HotelReservation/SelectHotel/SelectHotelMap/HotelListing/index.tsx b/components/HotelReservation/SelectHotel/SelectHotelMap/HotelListing/index.tsx
index 71d324155..92a302d58 100644
--- a/components/HotelReservation/SelectHotel/SelectHotelMap/HotelListing/index.tsx
+++ b/components/HotelReservation/SelectHotel/SelectHotelMap/HotelListing/index.tsx
@@ -1,5 +1,7 @@
"use client"
+import { useHotelsMapStore } from "@/stores/hotels-map"
+
import HotelCardDialogListing from "@/components/HotelReservation/HotelCardDialogListing"
import HotelCardListing from "@/components/HotelReservation/HotelCardListing"
@@ -8,27 +10,18 @@ import styles from "./hotelListing.module.css"
import { HotelCardListingTypeEnum } from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
import type { HotelListingProps } from "@/types/components/hotelReservation/selectHotel/map"
-export default function HotelListing({
- hotels,
- activeHotelPin,
- setActiveHotelPin,
-}: HotelListingProps) {
+export default function HotelListing({ hotels }: HotelListingProps) {
+ const { activeHotelPin } = useHotelsMapStore()
return (
<>
-
+
>
)
diff --git a/components/HotelReservation/SelectHotel/SelectHotelMap/SelectHotelMapContainer.tsx b/components/HotelReservation/SelectHotel/SelectHotelMap/SelectHotelMapContainer.tsx
new file mode 100644
index 000000000..d8237972e
--- /dev/null
+++ b/components/HotelReservation/SelectHotel/SelectHotelMap/SelectHotelMapContainer.tsx
@@ -0,0 +1,63 @@
+import { env } from "@/env/server"
+import { getCityCoordinates } from "@/lib/trpc/memoizedRequests"
+
+import {
+ fetchAvailableHotels,
+ getFiltersFromHotels,
+} from "@/app/[lang]/(live)/(public)/hotelreservation/(standard)/select-hotel/utils"
+import { safeTry } from "@/utils/safeTry"
+
+import { getHotelPins } from "../../HotelCardDialogListing/utils"
+import SelectHotelMap from "."
+
+import type {
+ HotelData,
+ NullableHotelData,
+} from "@/types/components/hotelReservation/selectHotel/hotelCardListingProps"
+import type { SelectHotelMapContainerProps } from "@/types/components/hotelReservation/selectHotel/map"
+
+function isValidHotelData(hotel: NullableHotelData): hotel is HotelData {
+ return hotel !== null && hotel !== undefined
+}
+
+export async function SelectHotelMapContainer({
+ city,
+ searchParams,
+ adultsInRoom,
+ childrenInRoom,
+}: SelectHotelMapContainerProps) {
+ const googleMapId = env.GOOGLE_DYNAMIC_MAP_ID
+ const googleMapsApiKey = env.GOOGLE_STATIC_MAP_KEY
+
+ const fetchAvailableHotelsPromise = safeTry(
+ fetchAvailableHotels({
+ cityId: city.id,
+ roomStayStartDate: searchParams.fromDate,
+ roomStayEndDate: searchParams.toDate,
+ adults: adultsInRoom,
+ children: childrenInRoom,
+ })
+ )
+
+ const [hotels] = await fetchAvailableHotelsPromise
+
+ const validHotels = hotels?.filter(isValidHotelData) || []
+
+ const hotelPins = getHotelPins(validHotels)
+ const filterList = getFiltersFromHotels(validHotels)
+ const cityCoordinates = await getCityCoordinates({
+ city: city.name,
+ hotel: { address: hotels?.[0]?.hotelData?.address.streetAddress },
+ })
+
+ return (
+
+ )
+}
diff --git a/components/HotelReservation/SelectHotel/SelectHotelMap/SelectHotelMapContainerSkeleton.module.css b/components/HotelReservation/SelectHotel/SelectHotelMap/SelectHotelMapContainerSkeleton.module.css
new file mode 100644
index 000000000..7ad45c4fb
--- /dev/null
+++ b/components/HotelReservation/SelectHotel/SelectHotelMap/SelectHotelMapContainerSkeleton.module.css
@@ -0,0 +1,47 @@
+.container {
+ max-width: var(--max-width);
+ height: 100vh;
+ display: flex;
+ width: 100%;
+}
+
+.listingContainer {
+ display: none;
+}
+
+.skeletonContainer {
+ display: none;
+ overflow: hidden;
+ flex-direction: row;
+ flex-wrap: wrap;
+ margin-top: 20px;
+ gap: var(--Spacing-x2);
+ padding-top: var(--Spacing-x6);
+ height: 100%;
+}
+
+.skeletonItem {
+ width: 440px;
+}
+
+.mapContainer {
+ flex: 1;
+}
+
+@media (min-width: 768px) {
+ .container {
+ height: 100%;
+ }
+ .listingContainer {
+ background-color: var(--Base-Surface-Secondary-light-Normal);
+ padding: var(--Spacing-x3) var(--Spacing-x4);
+ overflow-y: auto;
+ max-width: 505px;
+ position: relative;
+ height: 100%;
+ display: block;
+ }
+ .skeletonContainer {
+ display: flex;
+ }
+}
diff --git a/components/HotelReservation/SelectHotel/SelectHotelMap/SelectHotelMapContainerSkeleton.tsx b/components/HotelReservation/SelectHotel/SelectHotelMap/SelectHotelMapContainerSkeleton.tsx
new file mode 100644
index 000000000..75821477f
--- /dev/null
+++ b/components/HotelReservation/SelectHotel/SelectHotelMap/SelectHotelMapContainerSkeleton.tsx
@@ -0,0 +1,28 @@
+import SkeletonShimmer from "@/components/SkeletonShimmer"
+
+import { RoomCardSkeleton } from "../../SelectRate/RoomSelection/RoomCard/RoomCardSkeleton"
+
+import styles from "./SelectHotelMapContainerSkeleton.module.css"
+
+type Props = {
+ count?: number
+}
+
+export async function SelectHotelMapContainerSkeleton({ count = 2 }: Props) {
+ return (
+
+
+
+ {Array.from({ length: count }).map((_, index) => (
+
+
+
+ ))}
+
+
+
+
+
+
+ )
+}
diff --git a/components/HotelReservation/SelectHotel/SelectHotelMap/index.tsx b/components/HotelReservation/SelectHotel/SelectHotelMap/index.tsx
index 4208d4871..ec65ec961 100644
--- a/components/HotelReservation/SelectHotel/SelectHotelMap/index.tsx
+++ b/components/HotelReservation/SelectHotel/SelectHotelMap/index.tsx
@@ -1,16 +1,19 @@
"use client"
+
import { APIProvider } from "@vis.gl/react-google-maps"
-import { useRouter, useSearchParams } from "next/navigation"
-import { useEffect, useRef, useState } from "react"
+import { useEffect, useMemo, useRef, useState } from "react"
import { useIntl } from "react-intl"
import { useMediaQuery } from "usehooks-ts"
import { selectHotel } from "@/constants/routes/hotelReservation"
+import { useHotelFilterStore } from "@/stores/hotel-filters"
+import { useHotelsMapStore } from "@/stores/hotels-map"
import { CloseIcon, CloseLargeIcon } from "@/components/Icons"
import InteractiveMap from "@/components/Maps/InteractiveMap"
import { BackToTopButton } from "@/components/TempDesignSystem/BackToTopButton"
import Button from "@/components/TempDesignSystem/Button"
+import Link from "@/components/TempDesignSystem/Link"
import useLang from "@/hooks/useLang"
import FilterAndSortModal from "../FilterAndSortModal"
@@ -28,17 +31,13 @@ export default function SelectHotelMap({
filterList,
cityCoordinates,
}: SelectHotelMapProps) {
- const searchParams = useSearchParams()
- const router = useRouter()
const lang = useLang()
const intl = useIntl()
const isAboveMobile = useMediaQuery("(min-width: 768px)")
- const [activeHotelPin, setActiveHotelPin] = useState
(null)
const [showBackToTop, setShowBackToTop] = useState(false)
const listingContainerRef = useRef(null)
-
- const selectHotelParams = new URLSearchParams(searchParams.toString())
- const selectedHotel = selectHotelParams.get("selectedHotel")
+ const activeFilters = useHotelFilterStore((state) => state.activeFilters)
+ const { activeHotelCard, activeHotelPin } = useHotelsMapStore()
const coordinates = isAboveMobile
? cityCoordinates
@@ -52,13 +51,7 @@ export default function SelectHotelMap({
activeElement.scrollIntoView({ behavior: "smooth", block: "nearest" })
}
}
- }, [activeHotelPin])
-
- useEffect(() => {
- if (selectedHotel) {
- setActiveHotelPin(selectedHotel)
- }
- }, [selectedHotel])
+ }, [activeHotelCard, activeHotelPin])
useEffect(() => {
const hotelListingElement = document.querySelector(
@@ -82,9 +75,15 @@ export default function SelectHotelMap({
hotelListingElement?.scrollTo({ top: 0, behavior: "smooth" })
}
- function handlePageRedirect() {
- router.push(`${selectHotel(lang)}?${searchParams.toString()}`)
- }
+ const filteredHotelPins = useMemo(
+ () =>
+ hotelPins.filter((hotel) =>
+ activeFilters.every((filterId) =>
+ hotel.facilityIds.includes(Number(filterId))
+ )
+ ),
+ [activeFilters, hotelPins]
+ )
const closeButton = (
)
return (
@@ -108,26 +109,24 @@ export default function SelectHotelMap({
size="small"
variant="icon"
wrapping
- onClick={handlePageRedirect}
className={styles.filterContainerCloseButton}
+ asChild
>
-
+
+
+
-