diff --git a/openspec/changes/multi-day-routes/design.md b/openspec/changes/multi-day-routes/design.md index 48aad3b..30c8f98 100644 --- a/openspec/changes/multi-day-routes/design.md +++ b/openspec/changes/multi-day-routes/design.md @@ -280,6 +280,36 @@ function computeDays( The Planner's `useDays()` hook maps its Yjs waypoints + EnrichedRoute into this same shape before calling `computeDays`. +### D13: Sidebar waypoint hover highlights map marker + +Hovering a waypoint row in the `WaypointSidebar` passes the waypoint index +up to `SessionView` via an `onWaypointHover` callback. `PlannerMap` receives +a `highlightedWaypoint` index and renders the corresponding marker with a +CSS `scale(1.17)` transform (0.2s ease transition). This reuses the existing +`waypointIcon` function with a `highlighted` parameter — no extra DOM +elements or Leaflet layers needed. + +### D14: Journal route detail — day segment hover interaction + +Hovering a day row in the route detail day breakdown triggers two effects: + +1. **Map segment highlighting**: The hovered day's polyline thickens (weight 5, + opacity 1) while other days dim (weight 2, opacity 0.3). Implemented via + `highlightedDay` state passed to `DayColoredRoute`. + +2. **Fly-to-segment**: A `FlyToSegment` component calls `map.flyToBounds()` + on the hovered segment's bounds (200ms animation). On mouse leave it flies + back to the full route bounds. The full route bounds are cached on first + render to avoid recomputation. + +### D15: Per-day GPX export endpoint + +The existing `/api/routes/:id/gpx` endpoint gains an optional `?day=N` query +parameter. When present, it parses the stored GPX, runs `computeDays()` to +find the track point range for that day, and returns a GPX containing only +that day's track segment. The filename includes the day number +(`route_day1.gpx`). + ## Risks / Trade-offs - **Segment boundary alignment**: The day computation relies on diff --git a/openspec/changes/multi-day-routes/proposal.md b/openspec/changes/multi-day-routes/proposal.md index e09b6b3..6f36536 100644 --- a/openspec/changes/multi-day-routes/proposal.md +++ b/openspec/changes/multi-day-routes/proposal.md @@ -26,6 +26,12 @@ and deriving per-day stats from the segment data we already have. "Day 1 . 120 km". - **GPX export**: Day-break waypoints exported with a `overnight` element so the structure survives round-trips. +- **Waypoint highlighting**: Hovering a waypoint in the sidebar highlights + the corresponding marker on the map with a smooth scale animation. +- **Journal day interaction**: Hovering a day in the Journal route detail + highlights that segment on the map and flies the map to fit it. +- **Per-day GPX export**: Each day in the Journal route detail has a GPX + download button that exports just that day's track segment. All state lives in Yjs. No database changes are needed -- the Planner remains stateless. The visual design is already specified in the `visual-redesign` @@ -46,7 +52,9 @@ the data model, computation logic, and integration wiring. - `gpx-export`: Day-break metadata in exported GPX waypoints - `gpx-import`: Parse `overnight` waypoints to restore day breaks - `route-management`: Populate `dayBreaks` column on save, expose per-day stats -- `journal-route-detail`: Day breakdown display with per-day stats and map segments +- `journal-route-detail`: Day breakdown display with per-day stats, map segment + highlighting, fly-to-segment on hover, per-day GPX export +- `planner-sidebar`: Waypoint hover highlights corresponding map marker ## Non-Goals @@ -78,6 +86,9 @@ the data model, computation logic, and integration wiring. - **Journal route storage**: `updateRoute` populates `dayBreaks` column from parsed waypoint indices when saving GPX - **Journal route detail**: Day breakdown section with per-day stats (distance, - ascent, descent) when `dayBreaks` is non-empty + ascent, descent) when `dayBreaks` is non-empty. Hover highlights segment on + map and flies to fit. Per-day GPX download via `?day=N` query param. +- **Sidebar hover**: Hovering waypoint rows highlights the marker on the map + with CSS `scale(1.17)` transition (0.2s ease) - **i18n**: New keys for day labels, overnight toggle, per-day stats (en + de) in both planner and journal namespaces diff --git a/openspec/changes/multi-day-routes/tasks.md b/openspec/changes/multi-day-routes/tasks.md index 6efd24e..0bcc587 100644 --- a/openspec/changes/multi-day-routes/tasks.md +++ b/openspec/changes/multi-day-routes/tasks.md @@ -40,12 +40,25 @@ - [x] 7.1 Add Planner translation keys for en + de: day labels ("Day 1", "Tag 1"), overnight toggle ("Mark as overnight stop" / "Als Übernachtung markieren"), per-day stats, route summary - [x] 7.2 Add Journal translation keys for en + de: day breakdown header, per-day stats labels -## 8. Testing +## 8. Planner Waypoint Hover -- [x] 8.1 Unit tests for `computeDays()`: single day (no overnight), two days, three days, empty route, single waypoint, overnight on first/last waypoint edge cases -- [x] 8.2 Unit tests for `overnight.ts` helpers: set/clear/check overnight on Y.Map -- [x] 8.3 Unit tests for GPX roundtrip: generate with `isDayBreak`, parse back, verify `isDayBreak` preserved -- [x] 8.4 Unit tests for `dayBreaks` extraction in route update logic -- [x] 8.5 E2E test: add waypoints, toggle overnight on one, verify sidebar shows day breakdown with correct stats -- [x] 8.6 E2E test: export GPX with day breaks, verify downloaded file contains overnight metadata -- [x] 8.7 E2E test: save multi-day route to Journal, verify day breakdown displays on route detail page +- [x] 8.0a Add `onWaypointHover` callback to `WaypointSidebar`, emit waypoint index on row hover +- [x] 8.0b Pass `highlightedWaypoint` index to `PlannerMap`, render highlighted marker with CSS `scale(1.17)` and 0.2s ease transition + +## 9. Journal Day Interaction + +- [x] 9.1 Add `highlightedDay` state to route detail page, pass to `RouteMapThumbnail` +- [x] 9.2 Highlight hovered day segment on map: thicken active (weight 5), dim others (opacity 0.3) +- [x] 9.3 Fly map to hovered day segment bounds (200ms), fly back to full route on mouse leave +- [x] 9.4 Add per-day GPX download button on each day row in route detail breakdown +- [x] 9.5 Extend `/api/routes/:id/gpx` with `?day=N` query param to export single day's track segment + +## 10. Testing + +- [x] 10.1 Unit tests for `computeDays()`: single day (no overnight), two days, three days, empty route, single waypoint, overnight on first/last waypoint edge cases +- [x] 10.2 Unit tests for `overnight.ts` helpers: set/clear/check overnight on Y.Map +- [x] 10.3 Unit tests for GPX roundtrip: generate with `isDayBreak`, parse back, verify `isDayBreak` preserved +- [x] 10.4 Unit tests for `dayBreaks` extraction in route update logic +- [x] 10.5 E2E test: add waypoints, toggle overnight on one, verify sidebar shows day breakdown with correct stats +- [x] 10.6 E2E test: export GPX with day breaks, verify downloaded file contains overnight metadata +- [x] 10.7 E2E test: save multi-day route to Journal, verify day breakdown displays on route detail page