- `note` field on Waypoint type, stored in Yjs Y.Map and exported as `<desc>` inside `<wpt>` in GPX - Inline textarea note editing in WaypointSidebar with auto-resize, character counter (500 max), save-on-blur, Escape cancel - Note indicator dot on map markers; note tooltip on hover - `useNearbyPois` hook: fetches POIs within 500m of selected waypoint via Overpass proxy, 500ms debounce, AbortController, 60s rate-limit suppression - NearbyPoiMarkers component: renders POI markers on map for selected waypoint with snap-to-POI on click - Nearby section in WaypointSidebar: list with snap buttons, spinner, empty/rate-limited states, "Show more" toggle (5 → all) - Unit tests for fetchNearbyPois bbox geometry and snap-to-POI Yjs transaction behaviour Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
49 lines
1.4 KiB
TypeScript
49 lines
1.4 KiB
TypeScript
import L from "leaflet";
|
|
import { Marker, Tooltip } from "react-leaflet";
|
|
import type { Poi } from "~/lib/overpass";
|
|
import type { PoiCategory } from "@trails-cool/map-core";
|
|
|
|
interface NearbyPoiMarkersProps {
|
|
pois: Poi[];
|
|
categories: PoiCategory[];
|
|
onSnap: (poi: Poi) => void;
|
|
}
|
|
|
|
function nearbyPoiIcon(color: string, icon: string): L.DivIcon {
|
|
return L.divIcon({
|
|
className: "",
|
|
html: `<div style="
|
|
width:18px;height:18px;border-radius:50%;
|
|
background:${color};color:white;
|
|
display:flex;align-items:center;justify-content:center;
|
|
font-size:10px;
|
|
border:1.5px solid white;box-shadow:0 1px 3px rgba(0,0,0,0.25);
|
|
transform:translate(-9px,-9px);
|
|
">${icon}</div>`,
|
|
iconSize: [0, 0],
|
|
});
|
|
}
|
|
|
|
export function NearbyPoiMarkers({ pois, categories, onSnap }: NearbyPoiMarkersProps) {
|
|
return (
|
|
<>
|
|
{pois.map((poi) => {
|
|
const cat = categories.find((c) => c.id === poi.category);
|
|
if (!cat) return null;
|
|
return (
|
|
<Marker
|
|
key={poi.id}
|
|
position={[poi.lat, poi.lon]}
|
|
icon={nearbyPoiIcon(cat.color, cat.icon)}
|
|
eventHandlers={{ click: () => onSnap(poi) }}
|
|
zIndexOffset={900}
|
|
>
|
|
<Tooltip direction="top" offset={[0, -10]} opacity={0.95}>
|
|
<span>{poi.name ?? cat.icon} {cat.icon !== poi.name ? cat.icon : ""}</span>
|
|
</Tooltip>
|
|
</Marker>
|
|
);
|
|
})}
|
|
</>
|
|
);
|
|
}
|