Update specs with waypoint hover, day interaction, per-day export

Proposal: Added waypoint highlighting, Journal day interaction, and
per-day GPX export to What Changes and Impact sections.

Design: Added D13 (sidebar waypoint hover → map marker scale), D14
(Journal day segment hover with fly-to-bounds), D15 (per-day GPX
export endpoint with ?day=N query param).

Tasks: Added sections 8 (Planner waypoint hover, 2 tasks), 9 (Journal
day interaction, 5 tasks). Renumbered testing to section 10.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ullrich Schäfer 2026-04-11 00:52:40 +02:00
parent 7e89de0f0e
commit d325127a06
No known key found for this signature in database
GPG key ID: A32FF691A0F752D9
3 changed files with 64 additions and 10 deletions

View file

@ -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

View file

@ -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 `<type>overnight</type>`
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 `<type>overnight</type>` 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

View file

@ -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