feat(SW-340): Added hotel pins

This commit is contained in:
Pontus Dreij
2024-11-06 14:27:55 +01:00
parent fe6582ccbb
commit 378225f995
14 changed files with 321 additions and 129 deletions

View File

@@ -0,0 +1,51 @@
.advancedMarker {
height: 32px;
min-width: 109px !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 */
}
.pin {
position: absolute;
top: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
padding: var(--Spacing-x-half) var(--Spacing-x1) var(--Spacing-x-half)
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);
}
.pin.active {
padding-right: var(--Spacing-x-one-and-half);
}
.pinLabel {
display: none;
}
.pin.active .pinLabel {
display: flex;
align-items: center;
gap: var(--Spacing-x2);
text-wrap: nowrap;
}
.pinIcon {
width: 24px;
height: 24px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
background: var(--Primary-Dark-Surface-Normal);
}

View File

@@ -0,0 +1,47 @@
import {
AdvancedMarker,
AdvancedMarkerAnchorPoint,
} from "@vis.gl/react-google-maps"
import Body from "@/components/TempDesignSystem/Text/Body"
import HotelMarker from "../../Markers/Hotel"
import styles from "./hotelListingMapContent.module.css"
import { HotelPin } from "@/types/components/hotelReservation/selectHotel/map"
export default function HotelListingMapContent({
activeHotelPin,
hotelPins,
}: {
activeHotelPin?: HotelPin["name"] | null
hotelPins: HotelPin[]
}) {
return (
<div>
{hotelPins.map((pin) => (
<AdvancedMarker
key={pin.name}
className={styles.advancedMarker}
position={pin.coordinates}
anchorPoint={AdvancedMarkerAnchorPoint.CENTER}
zIndex={activeHotelPin === pin.name ? 2 : 0}
>
<span
className={`${styles.pin} ${activeHotelPin === pin.name ? styles.active : ""}`}
>
<span className={styles.pinIcon}>
<HotelMarker width={16} />
</span>
<Body asChild>
<span>
{pin.price} {pin.currency}
</span>
</Body>
</span>
</AdvancedMarker>
))}
</div>
)
}

View File

@@ -0,0 +1,42 @@
.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;
}

View File

@@ -0,0 +1,68 @@
import {
AdvancedMarker,
AdvancedMarkerAnchorPoint,
} from "@vis.gl/react-google-maps"
import Body from "@/components/TempDesignSystem/Text/Body"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import PoiMarker from "../../Markers/Poi"
import ScandicMarker from "../../Markers/Scandic"
import styles from "./hotelMapContent.module.css"
import { PointOfInterest } from "@/types/hotel"
export default function HotelMapContent({
coordinates,
pointsOfInterest,
onActivePoiChange,
activePoi,
}: {
coordinates: { lat: number; lng: number }
pointsOfInterest: PointOfInterest[]
onActivePoiChange?: (poiName: string | null) => void
activePoi?: string | null
}) {
function toggleActivePoi(poiName: string) {
onActivePoiChange?.(activePoi === poiName ? null : poiName)
}
return (
<>
<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}
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>
))}
</>
)
}

View File

@@ -1,19 +1,12 @@
"use client"
import {
AdvancedMarker,
AdvancedMarkerAnchorPoint,
Map,
type MapProps,
useMap,
} from "@vis.gl/react-google-maps"
import { 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 HotelListingMapContent from "./HotelListingMapContent"
import HotelMapContent from "./HotelMapContent"
import styles from "./interactiveMap.module.css"
@@ -23,9 +16,12 @@ export default function InteractiveMap({
coordinates,
pointsOfInterest,
activePoi,
hotelPins,
activeHotelPin,
mapId,
onActivePoiChange,
closeButton,
onActivePoiChange,
onActiveHotelPinChange,
}: InteractiveMapProps) {
const intl = useIntl()
const map = useMap()
@@ -51,46 +47,23 @@ export default function InteractiveMap({
}
}
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)}
onClick={() => toggleActivePoi(poi.name)}
>
<span
className={`${styles.poi} ${activePoi === poi.name ? styles.active : ""}`}
>
<PoiMarker
group={poi.group}
categoryName={poi.categoryName}
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>
))}
{hotelPins && (
<HotelListingMapContent
activeHotelPin={activeHotelPin}
hotelPins={hotelPins}
/>
)}
{pointsOfInterest && (
<HotelMapContent
coordinates={coordinates}
pointsOfInterest={pointsOfInterest}
onActivePoiChange={onActivePoiChange}
activePoi={activePoi}
/>
)}
</Map>
<div className={styles.ctaButtons}>
{closeButton}

View File

@@ -52,49 +52,6 @@
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);