-
{url}
-
diff --git a/src/components/maps/AreaMap.tsx b/src/components/maps/AreaMap.tsx
index bf75fd589..eb8d7cf90 100644
--- a/src/components/maps/AreaMap.tsx
+++ b/src/components/maps/AreaMap.tsx
@@ -1,15 +1,12 @@
'use client'
-import { useCallback, useEffect, useRef, useState } from 'react'
-import { Map, ScaleControl, FullscreenControl, NavigationControl, Source, Layer, MapLayerMouseEvent, LineLayer, MapInstance } from 'react-map-gl'
+import { Source, Layer, LineLayer, MapInstance } from 'react-map-gl'
import dynamic from 'next/dynamic'
-import { lineString, Point, Polygon, point } from '@turf/helpers'
+import { lineString, Point, Polygon } from '@turf/helpers'
import lineToPolygon from '@turf/line-to-polygon'
+import 'maplibre-gl/dist/maplibre-gl.css'
import { AreaMetadataType, AreaType } from '../../js/types'
-import { MAP_STYLES } from './BaseMap'
-import { AreaInfoDrawer } from './AreaInfoDrawer'
-import { AreaInfoHover } from './AreaInfoHover'
-import { SelectedFeature } from './AreaActiveMarker'
+import { GlobalMap } from './GlobalMap'
type ChildArea = Pick
& { metadata: Pick }
interface AreaMapProps {
@@ -42,13 +39,6 @@ export interface HoverInfo {
* Area map
*/
const AreaMap: React.FC = ({ area, subAreas }) => {
- const [clickInfo, setClickInfo] = useState(null)
- const [hoverInfo, setHoverInfo] = useState(null)
- const [selected, setSelected] = useState(null)
- const [mapInstance, setMapInstance] = useState(null)
- const [cursor, setCursor] = useState('default')
- const mapRef = useRef(null)
-
let fitBoundOpts: any = { padding: { top: 45, left: 45, bottom: 45, right: 45 } }
if (subAreas.length === 0) {
fitBoundOpts = { maxZoom: 14 }
@@ -56,92 +46,20 @@ const AreaMap: React.FC = ({ area, subAreas }) => {
const { metadata } = area
const boundary = metadata?.polygon == null ? null : lineToPolygon(lineString(metadata.polygon), { properties: { name: area.areaName } })
-
- useEffect(() => {
- if (mapRef.current != null) {
- setMapInstance(mapRef.current)
- }
- /**
- * Show drop pin if viewing a leaf area
- */
- if (metadata.leaf) {
- setSelected(point([metadata.lng, metadata.lat]).geometry as unknown as Point)
- }
- }, [metadata.leaf, mapRef?.current])
-
- const onClick = useCallback((event: MapLayerMouseEvent): void => {
- const feature = event?.features?.[0]
- if (feature == null) {
- setSelected(null)
- setClickInfo(null)
- } else {
- setSelected(feature.geometry as Point | Polygon)
- setClickInfo(feature.properties as MapAreaFeatureProperties)
- }
- }, [mapInstance])
-
- const onHover = useCallback((event: MapLayerMouseEvent) => {
- const obLayerId = event.features?.findIndex((f) => f.layer.id === 'crags' || f.layer.id === 'crag-group-boundaries') ?? -1
-
- if (obLayerId !== -1) {
- setCursor('pointer')
- const feature = event.features?.[obLayerId]
- if (feature != null && mapInstance != null) {
- const { geometry } = feature
- if (geometry.type === 'Point' || geometry.type === 'Polygon') {
- setHoverInfo({
- geometry: feature.geometry as Point | Polygon,
- data: feature.properties as MapAreaFeatureProperties,
- mapInstance
- })
- }
- }
- } else {
- setHoverInfo(null)
- setCursor('default')
- }
- }, [mapInstance])
-
return (
-
+
)
}
@@ -158,7 +76,7 @@ const areaPolygonStyle: LineLayer = {
type: 'line',
paint: {
'line-opacity': ['step', ['zoom'], 0.85, 10, 0.5],
- 'line-width': ['step', ['zoom'], 2, 10, 8],
+ 'line-width': ['step', ['zoom'], 4, 8, 6],
'line-color': 'rgb(219,39,119)',
'line-blur': 4
}
diff --git a/src/components/maps/GlobalMap.tsx b/src/components/maps/GlobalMap.tsx
index 016f05278..51c6405e1 100644
--- a/src/components/maps/GlobalMap.tsx
+++ b/src/components/maps/GlobalMap.tsx
@@ -1,27 +1,22 @@
'use client'
-import { useCallback, useEffect, useState } from 'react'
+import { useCallback, useState } from 'react'
import { Map, ScaleControl, FullscreenControl, NavigationControl, MapLayerMouseEvent, MapInstance } from 'react-map-gl/maplibre'
import maplibregl, { MapLibreEvent } from 'maplibre-gl'
-import { Protocol } from 'pmtiles'
import { Point, Polygon } from '@turf/helpers'
+import dynamic from 'next/dynamic'
import { MAP_STYLES } from './BaseMap'
import { AreaInfoDrawer } from './AreaInfoDrawer'
import { AreaInfoHover } from './AreaInfoHover'
import { SelectedFeature } from './AreaActiveMarker'
import { OBCustomLayers } from './OBCustomLayers'
+import { AreaType, ClimbType } from '@/js/types'
+import { TileProps, transformTileProps } from './utils'
-export interface MapAreaFeatureProperties {
- id: string
- name: string
- content: {
- description: string
- }
- parent: string // due to a backend backend bug, this is a string instead of a parent object
- // parent: {
- // id: string
- // name: string
- // }
+export type SimpleClimbType = Pick
+
+export type MapAreaFeatureProperties = Pick & {
+ climbs: SimpleClimbType[]
}
export interface HoverInfo {
@@ -32,34 +27,32 @@ export interface HoverInfo {
interface GlobalMapProps {
showFullscreenControl?: boolean
- initialCenter?: { longitude: number, latitude: number }
+ initialCenter?: [number, number]
+ initialViewState?: {
+ bounds: any
+ fitBoundsOptions: any
+ }
+ children?: React.ReactNode
}
/**
* Global map
*/
-export const GlobalMap: React.FC = ({ showFullscreenControl = true }) => {
- const [initialCenter, setInitialCenter] = useState<[number, number] | undefined>(undefined)
+export const GlobalMap: React.FC = ({
+ showFullscreenControl = true, initialCenter, initialViewState, children
+}) => {
const [clickInfo, setClickInfo] = useState(null)
const [hoverInfo, setHoverInfo] = useState(null)
const [selected, setSelected] = useState(null)
const [mapInstance, setMapInstance] = useState(null)
const [cursor, setCursor] = useState('default')
- useEffect(() => {
- getVisitorLocation().then((visitorLocation) => {
- if (visitorLocation != null) {
- setInitialCenter([visitorLocation.longitude, visitorLocation.latitude])
- }
- }).catch(() => {
- console.log('Unable to determine user\'s location')
- })
- }, [])
-
const onLoad = useCallback((e: MapLibreEvent) => {
setMapInstance(e.target)
if (initialCenter != null) {
e.target.jumpTo({ center: initialCenter, zoom: 6 })
+ } else if (initialViewState != null) {
+ e.target.fitBounds(initialViewState.bounds, initialViewState.fitBoundsOptions)
}
}, [initialCenter])
@@ -85,7 +78,7 @@ export const GlobalMap: React.FC = ({ showFullscreenControl = tr
if (geometry.type === 'Point' || geometry.type === 'Polygon') {
setHoverInfo({
geometry: feature.geometry as Point | Polygon,
- data: feature.properties as MapAreaFeatureProperties,
+ data: transformTileProps(feature.properties as TileProps),
mapInstance
})
}
@@ -96,14 +89,6 @@ export const GlobalMap: React.FC = ({ showFullscreenControl = tr
}
}, [mapInstance])
- // useEffect(() => {
- // const protocol = new Protocol()
- // maplibregl.addProtocol('pmtiles', protocol.tile)
- // return () => {
- // maplibregl.removeProtocol('pmtiles')
- // }
- // }, [])
-
return (
)
}
-const getVisitorLocation = async (): Promise<{ longitude: number, latitude: number } | undefined> => {
- try {
- const res = await fetch('/api/geo')
- return await res.json()
- } catch (err) {
- console.log('ERROR', err)
- return undefined
- }
-}
+export const LazyGlobalMap = dynamic(async () => await import('./GlobalMap').then(
+ module => module.GlobalMap), {
+ ssr: false
+})
diff --git a/src/components/maps/utils.ts b/src/components/maps/utils.ts
new file mode 100644
index 000000000..1493c76ac
--- /dev/null
+++ b/src/components/maps/utils.ts
@@ -0,0 +1,27 @@
+import { MapAreaFeatureProperties, SimpleClimbType } from './GlobalMap'
+
+export interface TileProps {
+ id: string
+ name: string
+ ancestors: string
+ pathTokens: string
+ content: {
+ description: string
+ }
+ climbs: string
+}
+
+/**
+ * Map tile properties can only contain primitive types.
+ * This function converts stringified json data back to json objects
+ */
+export const transformTileProps = (p: TileProps): MapAreaFeatureProperties => {
+ const { name, ancestors, pathTokens } = p
+ return {
+ ...p,
+ areaName: name,
+ ancestors: JSON.parse(ancestors) as string[],
+ pathTokens: JSON.parse(pathTokens) as string[],
+ climbs: JSON.parse(p.climbs) as SimpleClimbType[]
+ }
+}