'use client' import { Map, type MapProps, useMap } from '@vis.gl/react-google-maps' import { useEffect, useState } from 'react' import { useIntl } from 'react-intl' import { IconButton } from '../../IconButton' import { MaterialIcon } from '../../Icons/MaterialIcon' import { HOTEL_PAGE, MAP_RESTRICTIONS } from '../mapConstants' import { useZoomControls } from '@scandic-hotels/common/hooks/map/useZoomControls' import { HotelListingMapContent } from './HotelListingMapContent' import PoiMapMarkers from './PoiMapMarkers' import styles from './interactiveMap.module.css' import { CurrencyEnum } from '@scandic-hotels/common/constants/currency' import { Lang } from '@scandic-hotels/common/constants/language' import { HotelPin, MarkerInfo, PointOfInterest } from '../types' export type InteractiveMapProps = { lang: Lang coordinates: { lat: number lng: number } activePoi?: string | null hotelPins?: HotelPin[] pointsCurrency?: CurrencyEnum pointsOfInterest?: PointOfInterest[] markerInfo?: MarkerInfo mapId: string closeButton: React.ReactNode fitBounds?: boolean hoveredHotelPin?: string | null activeHotelPin?: string | null isUserLoggedIn: boolean onTilesLoaded?: () => void onActivePoiChange?: (poi: string | null) => void onClickHotel?: (hotelId: string) => void /** * Called when a hotel pin is hovered. * @param args when null, it means the hover has ended * @returns */ onHoverHotelPin?: ( args: { hotelName: string; hotelId: string } | null ) => void /** * Called when a hotel pin is activated. * @param args when null, it means nothing is active * @returns */ onSetActiveHotelPin?: ( args: { hotelName: string; hotelId: string } | null ) => void } export function InteractiveMap({ lang, coordinates, pointsOfInterest, activePoi, hotelPins, mapId, closeButton, markerInfo, fitBounds = true, hoveredHotelPin, activeHotelPin, isUserLoggedIn, pointsCurrency, onClickHotel, onHoverHotelPin, onSetActiveHotelPin, onTilesLoaded, onActivePoiChange, }: InteractiveMapProps) { const intl = useIntl() const map = useMap() const [hasInitializedBounds, setHasInitializedBounds] = useState(false) const { zoomIn, zoomOut, isMaxZoom, isMinZoom } = useZoomControls(HOTEL_PAGE) const mapOptions: MapProps = { defaultZoom: HOTEL_PAGE.DEFAULT_ZOOM, minZoom: HOTEL_PAGE.MIN_ZOOM, maxZoom: HOTEL_PAGE.MAX_ZOOM, defaultCenter: coordinates, disableDefaultUI: true, clickableIcons: false, mapId, gestureHandling: 'greedy', restriction: MAP_RESTRICTIONS, } useEffect(() => { if (map && hotelPins?.length && !hasInitializedBounds) { if (fitBounds) { const bounds = new google.maps.LatLngBounds() hotelPins.forEach((marker) => { bounds.extend(marker.coordinates) }) map.fitBounds(bounds, 100) } setHasInitializedBounds(true) } }, [map, fitBounds, hotelPins, hasInitializedBounds]) return (
{hotelPins && ( )} {pointsOfInterest && markerInfo && ( )}
{closeButton}
) }