feat: wire up radial menu directions and multi-stop add button

- Radial menu "From here" now sets origin and opens directions panel
- Radial menu "To here" now sets destination, opens directions panel,
  and uses GPS as origin fallback when available
- DirectionsPanel "Add stop" button now creates intermediate stops
- Stops array initialized from routeStart/routeEnd when adding stops

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Matt 2026-05-09 08:23:38 +00:00
commit 2345334bc7
2 changed files with 55 additions and 9 deletions

View file

@ -74,8 +74,43 @@ export default function DirectionsPanel({ onClose }) {
} }
const handleAddStop = () => { const handleAddStop = () => {
// For now, show a message - multi-stop UI is complex // Build stops array from current route endpoints if not already populated
// TODO: Implement full multi-stop UI let newStops = [...stops]
// If stops is empty but we have endpoints, initialize from routeStart/routeEnd
if (newStops.length === 0) {
if (routeStart) {
newStops.push({
id: crypto.randomUUID(),
lat: routeStart.lat,
lon: routeStart.lon,
name: routeStart.name || "Start",
})
}
if (routeEnd) {
newStops.push({
id: crypto.randomUUID(),
lat: routeEnd.lat,
lon: routeEnd.lon,
name: routeEnd.name || "Destination",
})
}
}
// Create placeholder intermediate stop
const newStop = {
id: crypto.randomUUID(),
lat: null,
lon: null,
name: "",
}
// Insert before destination (last position), or at end if no destination
const insertIdx = Math.max(0, newStops.length - 1)
newStops.splice(insertIdx, 0, newStop)
// Update stops array - reorderStops triggers UI update
reorderStops(newStops)
} }
// Check if route has wilderness segments // Check if route has wilderness segments

View file

@ -1672,13 +1672,24 @@ const MapView = forwardRef(function MapView(_, ref) {
lon: radialMenu.lon, lon: radialMenu.lon,
name: radialMenu.centerLabel || radialMenu.lat.toFixed(5) + ", " + radialMenu.lon.toFixed(5), name: radialMenu.centerLabel || radialMenu.lat.toFixed(5) + ", " + radialMenu.lon.toFixed(5),
} }
const { routeStart, setRouteEnd, computeRoute } = useStore.getState() const { routeStart, setRouteStart, setRouteEnd, computeRoute, setDirectionsMode, geoPermission, userLocation } = useStore.getState()
setRouteEnd(place) setRouteEnd(place)
setDirectionsMode(true)
if (routeStart) { if (routeStart) {
computeRoute() computeRoute()
} else { } else if (geoPermission === "granted" && userLocation) {
toast("Set starting point first") // Use GPS as origin fallback
setRouteStart({
lat: userLocation.lat,
lon: userLocation.lon,
name: "Your location",
source: "gps",
})
computeRoute()
} }
// If no origin and no GPS, directions panel opens and origin field auto-focuses
}, },
}, },
{ {
@ -1692,16 +1703,16 @@ const MapView = forwardRef(function MapView(_, ref) {
lon: radialMenu.lon, lon: radialMenu.lon,
name: radialMenu.centerLabel || radialMenu.lat.toFixed(5) + ", " + radialMenu.lon.toFixed(5), name: radialMenu.centerLabel || radialMenu.lat.toFixed(5) + ", " + radialMenu.lon.toFixed(5),
} }
const { clearRoute, setRouteStart, routeEnd, computeRoute } = useStore.getState() const { clearRoute, setRouteStart, routeEnd, computeRoute, setDirectionsMode } = useStore.getState()
clearRoute() clearRoute()
clearRouteDisplay(mapInstance.current) clearRouteDisplay(mapInstance.current)
setRouteStart(place) setRouteStart(place)
// If we already have a destination, compute route immediately setDirectionsMode(true)
if (routeEnd) { if (routeEnd) {
computeRoute() computeRoute()
} else {
toast("Now tap destination")
} }
// If no destination, directions panel opens and destination field auto-focuses
}, },
}, },
{ {