feat(SW-340): Added hotel pins
This commit is contained in:
@@ -20,7 +20,7 @@ import { SelectHotelMapProps } from "@/types/components/hotelReservation/selectH
|
||||
export default function SelectHotelMap({
|
||||
apiKey,
|
||||
coordinates,
|
||||
pointsOfInterest,
|
||||
hotelPins,
|
||||
mapId,
|
||||
isModal,
|
||||
}: SelectHotelMapProps) {
|
||||
@@ -28,7 +28,7 @@ export default function SelectHotelMap({
|
||||
const router = useRouter()
|
||||
const lang = useLang()
|
||||
const intl = useIntl()
|
||||
const [activePoi, setActivePoi] = useState<string | null>(null)
|
||||
const [activeHotelPin, setActiveHotelPin] = useState<string | null>(null)
|
||||
|
||||
function handleModalDismiss() {
|
||||
router.back()
|
||||
@@ -70,9 +70,9 @@ export default function SelectHotelMap({
|
||||
<InteractiveMap
|
||||
closeButton={closeButton}
|
||||
coordinates={coordinates}
|
||||
pointsOfInterest={pointsOfInterest}
|
||||
activePoi={activePoi}
|
||||
onActivePoiChange={setActivePoi}
|
||||
hotelPins={hotelPins}
|
||||
activeHotelPin={activeHotelPin}
|
||||
onActiveHotelPinChange={setActiveHotelPin}
|
||||
mapId={mapId}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -12,14 +12,13 @@ export function MapModal({ children }: { children: React.ReactNode }) {
|
||||
const router = useRouter()
|
||||
const [mapHeight, setMapHeight] = useState("0px")
|
||||
const [mapTop, setMapTop] = useState("0px")
|
||||
const [isOpen, setOpen] = useState(true)
|
||||
|
||||
const [isOpen, setIsOpen] = useState(true)
|
||||
const [scrollHeightWhenOpened, setScrollHeightWhenOpened] = useState(0)
|
||||
|
||||
const rootDiv = useRef<HTMLDivElement | null>(null)
|
||||
|
||||
const handleOnOpenChange = (open: boolean) => {
|
||||
setOpen(open)
|
||||
setIsOpen(open)
|
||||
if (!open) {
|
||||
router.back()
|
||||
}
|
||||
|
||||
+51
@@ -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);
|
||||
}
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -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}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
export default function HotelMarker({
|
||||
className,
|
||||
...props
|
||||
}: React.SVGAttributes<HTMLOrSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
className={className}
|
||||
width="16"
|
||||
height="11"
|
||||
viewBox="0 0 16 11"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M1.45898 10.5331C1.28676 10.5331 1.13954 10.472 1.01732 10.3498C0.895095 10.2276 0.833984 10.0804 0.833984 9.90814V1.4248C0.833984 1.25258 0.895095 1.10536 1.01732 0.983138C1.13954 0.860916 1.28676 0.799805 1.45898 0.799805C1.63121 0.799805 1.77843 0.860916 1.90065 0.983138C2.02287 1.10536 2.08398 1.25258 2.08398 1.4248V7.2998H7.38398V3.36647C7.38398 3.02272 7.50638 2.72844 7.75117 2.48365C7.99596 2.23887 8.29023 2.11647 8.63398 2.11647H12.6007C13.3118 2.11647 13.9173 2.36647 14.4173 2.86647C14.9173 3.36647 15.1673 3.97203 15.1673 4.68314V9.90814C15.1673 10.0804 15.1062 10.2276 14.984 10.3498C14.8618 10.472 14.7145 10.5331 14.5423 10.5331C14.3701 10.5331 14.2229 10.472 14.1007 10.3498C13.9784 10.2276 13.9173 10.0804 13.9173 9.90814V8.5498H2.08398V9.90814C2.08398 10.0804 2.02287 10.2276 1.90065 10.3498C1.77843 10.472 1.63121 10.5331 1.45898 10.5331ZM4.71633 6.5998C4.18366 6.5998 3.73121 6.41337 3.35898 6.04049C2.98676 5.66761 2.80065 5.21483 2.80065 4.68215C2.80065 4.14948 2.98709 3.69703 3.35997 3.3248C3.73285 2.95258 4.18562 2.76647 4.7183 2.76647C5.25098 2.76647 5.70343 2.95291 6.07565 3.32579C6.44787 3.69867 6.63398 4.15144 6.63398 4.68412C6.63398 5.2168 6.44755 5.66925 6.07467 6.04147C5.70179 6.41369 5.24901 6.5998 4.71633 6.5998ZM8.63398 7.2998H13.9173V4.6815C13.9173 4.32148 13.788 4.0123 13.5293 3.75397C13.2707 3.49564 12.9597 3.36647 12.5965 3.36647H8.63398V7.2998ZM4.71732 5.3498C4.90621 5.3498 5.06454 5.28592 5.19232 5.15814C5.3201 5.03036 5.38398 4.87203 5.38398 4.68314C5.38398 4.49425 5.3201 4.33592 5.19232 4.20814C5.06454 4.08036 4.90621 4.01647 4.71732 4.01647C4.52843 4.01647 4.3701 4.08036 4.24232 4.20814C4.11454 4.33592 4.05065 4.49425 4.05065 4.68314C4.05065 4.87203 4.11454 5.03036 4.24232 5.15814C4.3701 5.28592 4.52843 5.3498 4.71732 5.3498Z"
|
||||
fill="white"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user