Move map out to its own component

This commit is contained in:
Niclas Edenvin
2024-09-25 17:44:53 +02:00
parent d3c01237db
commit 1440b4dbae
3 changed files with 3 additions and 3 deletions

View File

@@ -0,0 +1,139 @@
"use client"
import {
AdvancedMarker,
AdvancedMarkerAnchorPoint,
Map,
type MapProps,
useMap,
} from "@vis.gl/react-google-maps"
import { useIntl } from "react-intl"
import useHotelPageStore from "@/stores/hotel-page"
import { MinusIcon, PlusIcon } from "@/components/Icons"
import CloseLargeIcon from "@/components/Icons/CloseLarge"
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 { MapContentProps } from "@/types/components/hotelPage/map/mapContent"
export default function InteractiveMap({
coordinates,
pointsOfInterest,
activePoi,
mapId,
onActivePoiChange,
}: MapContentProps) {
const intl = useIntl()
const { closeDynamicMap } = useHotelPageStore()
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}>
<Button
theme="base"
intent="inverted"
variant="icon"
size="small"
className={styles.closeButton}
onClick={closeDynamicMap}
>
<CloseLargeIcon color="burgundy" />
<span>{intl.formatMessage({ id: "Close the map" })}</span>
</Button>
<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>
)
}

View File

@@ -0,0 +1,108 @@
.mapContainer {
--button-box-shadow: 0 0 8px 1px rgba(0, 0, 0, 0.1);
width: 100%;
position: relative;
z-index: 0;
}
.mapContainer::after {
content: "";
position: absolute;
top: 0;
right: 0;
background: linear-gradient(
43deg,
rgba(172, 172, 172, 0) 57.66%,
rgba(0, 0, 0, 0.25) 92.45%
);
width: 100%;
height: 100%;
pointer-events: none;
}
.ctaButtons {
position: absolute;
top: var(--Spacing-x2);
right: var(--Spacing-x2);
z-index: 1;
display: flex;
flex-direction: column;
gap: var(--Spacing-x7);
align-items: flex-end;
pointer-events: none;
}
.zoomButtons {
display: grid;
gap: var(--Spacing-x1);
}
.closeButton {
pointer-events: initial;
box-shadow: var(--button-box-shadow);
gap: var(--Spacing-x-half);
}
.zoomButton {
width: var(--Spacing-x5);
height: var(--Spacing-x5);
padding: 0;
pointer-events: initial;
box-shadow: var(--button-box-shadow);
}
.advancedMarker {
height: var(--Spacing-x4);
width: var(
--Spacing-x4
) !important; /* Overwriting the default width of the @vis.gl/react-google-maps AdvancedMarker */
}
.advancedMarker.active {
height: var(--Spacing-x5);
width: var(
--Spacing-x5
) !important; /* Overwriting the default width of the @vis.gl/react-google-maps AdvancedMarker */
}
.poi {
position: absolute;
top: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
padding: var(--Spacing-x-half);
border-radius: var(--Corner-radius-Rounded);
background-color: var(--Base-Surface-Primary-light-Normal);
box-shadow: 0 0 4px 2px rgba(0, 0, 0, 0.1);
gap: var(--Spacing-x1);
}
.poi.active {
padding-right: var(--Spacing-x-one-and-half);
}
.poiLabel {
display: none;
}
.poi.active .poiLabel {
display: flex;
align-items: center;
gap: var(--Spacing-x2);
text-wrap: nowrap;
}
@media screen and (min-width: 768px) {
.ctaButtons {
top: var(--Spacing-x4);
right: var(--Spacing-x4);
bottom: var(--Spacing-x4);
justify-content: space-between;
}
.zoomButtons {
display: flex;
}
}