Commit graph

4 commits

Author SHA1 Message Date
Ullrich Schäfer
14b179bb0c Fix waypoint loading in Edit in Planner flow
Three issues fixed:

1. GPX parser used browser DOMParser which doesn't exist in Node/Vite SSR.
   Added async parseGpxAsync() using linkedom for server-side parsing.

2. Server-side session initialization stored waypoints in a Yjs doc
   instance separate from the Vite WebSocket plugin's doc store.
   Moved waypoint initialization to client-side: API returns parsed
   waypoints, client adds them to Yjs after sync.

3. GPX was encoded in URL params causing HTTP 431. Now the Journal
   creates a Planner session via API (POST body), and only passes
   compact waypoint coordinates in URL params.

Verified: Journal route → Edit in Planner → 4 waypoints loaded,
route computed (79.3km), elevation profile, Save to Journal ready.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 20:22:58 +00:00
Ullrich Schäfer
55806fc84a
Fix waypoint drag, host election, segment routing, debug panel
Waypoint drag:
- Use observeDeep instead of observe to detect Y.Map property changes

Host election:
- Extracted to host-election.ts with 8 unit tests
- Simple rule: lowest real client ID is always host, deterministic
- Always sets role (host or participant), no missing roles
- Filters server docs (empty awareness state) from election

BRouter routing:
- Route segment-by-segment like bikerouter.de (one request per
  waypoint pair), guarantees route passes through every waypoint
- Merge GeoJSON segments with accumulated stats
- 8 unit tests for segment merging and waypoint splitting

Awareness cleanup:
- Track client IDs per WebSocket connection
- Immediately remove awareness on WebSocket close

Debug panel:
- Visibility + expanded state persisted in localStorage
- Hotkey (Shift+Cmd+Option+T) toggles visibility
- Labels server docs as (server)
- All logic self-contained in YjsDebugPanel.tsx

User identity:
- Color and name persisted in localStorage across reloads

Tests: 32 total (16 existing + 8 host election + 8 routing)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 08:52:52 +01:00
Ullrich Schäfer
230094b956
Fix Yjs WebSocket in dev mode
- Add Vite plugin implementing y-protocols sync server for dev mode
- Fix useYjs hook: move provider creation into useEffect to survive
  React StrictMode remounts
- Fix WebSocket URL: use /sync as base (y-websocket appends room name)
- Verified in browser: Connected status, Host badge, awareness working

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 01:12:13 +01:00
Ullrich Schäfer
af70c822ee
Implement Planner map UI with collaborative editing (Groups 5+6)
Core Planner experience:
- Full-screen Leaflet map with OSM/OpenTopoMap/CyclOSM layers
- Click to add waypoints, drag to move, right-click to delete
- Waypoint sidebar with reorder, delete, route stats
- Real-time Yjs sync between participants
- Live cursors showing other users' mouse positions on the map

Routing:
- Host election via Yjs awareness (lowest client ID)
- Auto-failover when host disconnects
- Debounced BRouter route computation (500ms)
- Route polyline display from BRouter GeoJSON
- Route stats (distance, elevation gain/loss)

Client-side architecture:
- useYjs hook: WebSocket connection, awareness, document management
- useRouting hook: host election, route computation, stats parsing
- PlannerMap component: Leaflet + Yjs integration
- WaypointSidebar component: list with reorder/delete
- Lazy-loaded components for code splitting

Remaining: elevation chart, profile selector, GPX export (tasks 6.7-6.9)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 00:32:51 +01:00