127 lines
3.6 KiB
TypeScript
127 lines
3.6 KiB
TypeScript
"use client"
|
|
import {
|
|
AdvancedMarker,
|
|
AdvancedMarkerAnchorPoint,
|
|
Map,
|
|
type MapProps,
|
|
useMap,
|
|
} from "@vis.gl/react-google-maps"
|
|
import { useIntl } from "react-intl"
|
|
|
|
import { MinusIcon, PlusIcon } from "@/components/Icons"
|
|
import PoiMarker from "@/components/Maps/Markers/Poi"
|
|
import ScandicMarker from "@/components/Maps/Markers/Scandic"
|
|
import Button from "@/components/TempDesignSystem/Button"
|
|
import Body from "@/components/TempDesignSystem/Text/Body"
|
|
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
|
|
|
import styles from "./interactiveMap.module.css"
|
|
|
|
import type { InteractiveMapProps } from "@/types/components/hotelPage/map/interactiveMap"
|
|
|
|
export default function InteractiveMap({
|
|
coordinates,
|
|
pointsOfInterest,
|
|
activePoi,
|
|
mapId,
|
|
onActivePoiChange,
|
|
closeButton,
|
|
}: InteractiveMapProps) {
|
|
const intl = useIntl()
|
|
const map = useMap()
|
|
|
|
const mapOptions: MapProps = {
|
|
defaultZoom: 14,
|
|
defaultCenter: coordinates,
|
|
disableDefaultUI: true,
|
|
clickableIcons: false,
|
|
mapId,
|
|
}
|
|
|
|
function zoomIn() {
|
|
const currentZoom = map && map.getZoom()
|
|
if (currentZoom) {
|
|
map.setZoom(currentZoom + 1)
|
|
}
|
|
}
|
|
function zoomOut() {
|
|
const currentZoom = map && map.getZoom()
|
|
if (currentZoom) {
|
|
map.setZoom(currentZoom - 1)
|
|
}
|
|
}
|
|
|
|
function toggleActivePoi(poiName: string) {
|
|
onActivePoiChange(activePoi === poiName ? null : poiName)
|
|
}
|
|
|
|
return (
|
|
<div className={styles.mapContainer}>
|
|
<Map {...mapOptions}>
|
|
<AdvancedMarker position={coordinates} zIndex={1}>
|
|
<ScandicMarker />
|
|
</AdvancedMarker>
|
|
|
|
{pointsOfInterest.map((poi) => (
|
|
<AdvancedMarker
|
|
key={poi.name}
|
|
className={styles.advancedMarker}
|
|
position={poi.coordinates}
|
|
anchorPoint={AdvancedMarkerAnchorPoint.CENTER}
|
|
zIndex={activePoi === poi.name ? 2 : 0}
|
|
onMouseEnter={() => onActivePoiChange(poi.name)}
|
|
onMouseLeave={() => onActivePoiChange(null)}
|
|
onClick={() => toggleActivePoi(poi.name)}
|
|
>
|
|
<span
|
|
className={`${styles.poi} ${activePoi === poi.name ? styles.active : ""}`}
|
|
>
|
|
<PoiMarker
|
|
group={poi.group}
|
|
categoryName={poi.categoryName}
|
|
className={styles.poiMarker}
|
|
size={activePoi === poi.name ? 20 : 16}
|
|
/>
|
|
<Body className={styles.poiLabel} asChild>
|
|
<span>
|
|
{poi.name}
|
|
<Caption asChild>
|
|
<span>{poi.distance} km</span>
|
|
</Caption>
|
|
</span>
|
|
</Body>
|
|
</span>
|
|
</AdvancedMarker>
|
|
))}
|
|
</Map>
|
|
<div className={styles.ctaButtons}>
|
|
{closeButton}
|
|
<div className={styles.zoomButtons}>
|
|
<Button
|
|
theme="base"
|
|
intent="inverted"
|
|
variant="icon"
|
|
size="small"
|
|
className={styles.zoomButton}
|
|
onClick={zoomOut}
|
|
aria-label={intl.formatMessage({ id: "Zoom in" })}
|
|
>
|
|
<MinusIcon color="burgundy" width={20} height={20} />
|
|
</Button>
|
|
<Button
|
|
theme="base"
|
|
intent="inverted"
|
|
variant="icon"
|
|
size="small"
|
|
className={styles.zoomButton}
|
|
onClick={zoomIn}
|
|
aria-label={intl.formatMessage({ id: "Zoom out" })}
|
|
>
|
|
<PlusIcon color="burgundy" width={20} height={20} />
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|