Fix map route not rendering; fix health date filter timezone mismatch
This commit is contained in:
@@ -39,55 +39,82 @@ function decodePolyline(encoded) {
|
||||
return coords
|
||||
}
|
||||
|
||||
function drawRoute(map, polyline, sportType, trackRef) {
|
||||
if (trackRef.current) {
|
||||
trackRef.current.remove()
|
||||
trackRef.current = null
|
||||
}
|
||||
if (!polyline) return
|
||||
|
||||
const coords = decodePolyline(polyline)
|
||||
if (!coords.length) return
|
||||
|
||||
trackRef.current = L.polyline(coords, {
|
||||
color: sportColor(sportType),
|
||||
weight: 3,
|
||||
opacity: 0.9,
|
||||
}).addTo(map)
|
||||
|
||||
map.fitBounds(trackRef.current.getBounds(), { padding: [20, 20] })
|
||||
|
||||
const dot = (color) => L.divIcon({
|
||||
html: `<div style="width:12px;height:12px;background:${color};border:2px solid white;border-radius:50%"></div>`,
|
||||
iconSize: [12, 12], iconAnchor: [6, 6], className: '',
|
||||
})
|
||||
L.marker(coords[0], { icon: dot('#22c55e') }).addTo(map)
|
||||
L.marker(coords[coords.length - 1], { icon: dot('#ef4444') }).addTo(map)
|
||||
}
|
||||
|
||||
export default function ActivityMap({ polyline, dataPoints, hoveredDistance, sportType, mapType = 'dark' }) {
|
||||
const mapRef = useRef(null)
|
||||
const mapInstanceRef = useRef(null)
|
||||
const markerRef = useRef(null)
|
||||
const trackRef = useRef(null)
|
||||
const tileLayerRef = useRef(null)
|
||||
const polylineRef = useRef(polyline)
|
||||
const sportTypeRef = useRef(sportType)
|
||||
|
||||
useEffect(() => { polylineRef.current = polyline }, [polyline])
|
||||
useEffect(() => { sportTypeRef.current = sportType }, [sportType])
|
||||
|
||||
useEffect(() => {
|
||||
if (!mapRef.current || mapInstanceRef.current) return
|
||||
mapInstanceRef.current = L.map(mapRef.current, { zoomControl: true, attributionControl: true })
|
||||
const tile = TILE_LAYERS['dark']
|
||||
tileLayerRef.current = L.tileLayer(tile.url, { attribution: tile.attribution, maxZoom: 19 })
|
||||
.addTo(mapInstanceRef.current)
|
||||
return () => { mapInstanceRef.current?.remove(); mapInstanceRef.current = null }
|
||||
|
||||
mapInstanceRef.current = L.map(mapRef.current, {
|
||||
zoomControl: true,
|
||||
attributionControl: true,
|
||||
})
|
||||
|
||||
const tile = TILE_LAYERS.dark
|
||||
tileLayerRef.current = L.tileLayer(tile.url, {
|
||||
attribution: tile.attribution,
|
||||
maxZoom: 19,
|
||||
}).addTo(mapInstanceRef.current)
|
||||
|
||||
return () => {
|
||||
mapInstanceRef.current?.remove()
|
||||
mapInstanceRef.current = null
|
||||
}
|
||||
}, [])
|
||||
|
||||
// Switch tile layer when mapType changes
|
||||
useEffect(() => {
|
||||
if (!mapInstanceRef.current) return
|
||||
const tile = TILE_LAYERS[mapType] || TILE_LAYERS.dark
|
||||
if (tileLayerRef.current) {
|
||||
tileLayerRef.current.remove()
|
||||
}
|
||||
tileLayerRef.current = L.tileLayer(tile.url, { attribution: tile.attribution, maxZoom: 19 })
|
||||
.addTo(mapInstanceRef.current)
|
||||
if (tileLayerRef.current) tileLayerRef.current.remove()
|
||||
tileLayerRef.current = L.tileLayer(tile.url, {
|
||||
attribution: tile.attribution,
|
||||
maxZoom: 19,
|
||||
}).addTo(mapInstanceRef.current)
|
||||
drawRoute(mapInstanceRef.current, polylineRef.current, sportTypeRef.current, trackRef)
|
||||
}, [mapType])
|
||||
|
||||
// Draw route
|
||||
useEffect(() => {
|
||||
if (!mapInstanceRef.current || !polyline) return
|
||||
if (trackRef.current) trackRef.current.remove()
|
||||
const coords = decodePolyline(polyline)
|
||||
if (!coords.length) return
|
||||
trackRef.current = L.polyline(coords, { color: sportColor(sportType), weight: 3, opacity: 0.9 })
|
||||
.addTo(mapInstanceRef.current)
|
||||
mapInstanceRef.current.fitBounds(trackRef.current.getBounds(), { padding: [20, 20] })
|
||||
if (coords.length > 0) {
|
||||
const dot = (color) => L.divIcon({
|
||||
html: `<div style="width:12px;height:12px;background:${color};border:2px solid white;border-radius:50%"></div>`,
|
||||
iconSize: [12, 12], iconAnchor: [6, 6], className: '',
|
||||
})
|
||||
L.marker(coords[0], { icon: dot('#22c55e') }).addTo(mapInstanceRef.current)
|
||||
L.marker(coords[coords.length - 1], { icon: dot('#ef4444') }).addTo(mapInstanceRef.current)
|
||||
}
|
||||
if (!mapInstanceRef.current) return
|
||||
drawRoute(mapInstanceRef.current, polyline, sportType, trackRef)
|
||||
}, [polyline, sportType])
|
||||
|
||||
// Position marker on timeline hover
|
||||
useEffect(() => {
|
||||
if (!mapInstanceRef.current || !dataPoints || !hoveredDistance) return
|
||||
if (!mapInstanceRef.current || !dataPoints || hoveredDistance == null) return
|
||||
const point = dataPoints.find(p => p.distance_m >= hoveredDistance)
|
||||
if (!point?.latitude || !point?.longitude) return
|
||||
if (markerRef.current) {
|
||||
@@ -97,9 +124,10 @@ export default function ActivityMap({ polyline, dataPoints, hoveredDistance, spo
|
||||
html: '<div style="width:14px;height:14px;background:#fff;border:3px solid #3b82f6;border-radius:50%;box-shadow:0 0 6px rgba(59,130,246,0.8)"></div>',
|
||||
iconSize: [14, 14], iconAnchor: [7, 7], className: '',
|
||||
})
|
||||
markerRef.current = L.marker([point.latitude, point.longitude], { icon }).addTo(mapInstanceRef.current)
|
||||
markerRef.current = L.marker([point.latitude, point.longitude], { icon })
|
||||
.addTo(mapInstanceRef.current)
|
||||
}
|
||||
}, [hoveredDistance, dataPoints])
|
||||
|
||||
return <div ref={mapRef} style={{ height: '100%', width: '100%', background: '#1a1a2e' }} />
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user