Update route-coloring spec with all 10 modes, create follow-up changes

Spec updates:
- route-coloring: Added speed limit, smoothness, track type, cycleway,
  and bike route modes. Added OSM wiki links, BRouter profile patching,
  dropdown order, bike route human-readable legends.

New follow-up changes (proposals only):
- elevation-map-interaction: Bidirectional chart ↔ map interaction
  (route hover → chart, chart click → pan, chart drag → zoom)
- e2e-test-reorganization: Mock BRouter by default, split tests by
  feature, shared helpers
- journal-poi-details: Surface POI metadata in Journal route detail
  (phone, address, website, opening hours from snapped waypoints)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ullrich Schäfer 2026-04-11 11:20:17 +02:00
parent 80404b2494
commit a44beb87ef
No known key found for this signature in database
GPG key ID: A32FF691A0F752D9
7 changed files with 148 additions and 43 deletions

View file

@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-04-11

View file

@ -0,0 +1,21 @@
## Why
The planner E2E test file (`e2e/planner.test.ts`) has grown to 42+ tests in a single describe block. Tests that need a computed route manually call `mockBRouter(page)` — this is opt-in and easy to forget, leading to flaky tests when BRouter is slow. Test setup is duplicated across tests (create session, goto URL, wait for connected).
## What Changes
- **Mock BRouter by default**: Use a shared Playwright fixture or `beforeEach` that mocks BRouter for all planner tests. Only integration tests that explicitly test the real BRouter pipeline should use the real endpoint.
- **Split by feature**: Break `planner.test.ts` into focused files: `planner-session.test.ts`, `planner-routing.test.ts`, `planner-multiday.test.ts`, `planner-overlays.test.ts`, `planner-coloring.test.ts`
- **Shared test helpers**: Extract common patterns (create session + goto + wait for connected) into a reusable helper
## Capabilities
### Modified Capabilities
- Testing infrastructure only — no user-facing changes
## Impact
- `e2e/planner.test.ts` → split into 5-6 files
- `e2e/fixtures/brouter-mock.ts` → becomes default fixture
- New `e2e/helpers/planner.ts` for shared setup
- `playwright.config.ts` may need testMatch updates

View file

@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-04-11

View file

@ -0,0 +1,21 @@
## Why
The elevation chart and map currently have one-directional interaction: hovering the chart shows a red dot on the map. But hovering the route on the map doesn't highlight the chart, clicking the chart doesn't pan the map, and there's no way to zoom into a section of the route from the chart. This makes it hard to correlate what you see on the map with what you see in the elevation profile.
## What Changes
- **Route hover → chart marker**: Hovering over the route polyline on the map shows the corresponding position on the elevation chart with a crosshair
- **Chart click → map pan**: Clicking on the elevation chart pans the map to center on that point along the route
- **Chart drag → map zoom**: Dragging/selecting a range on the elevation chart zooms the map to fit that section of the route
## Capabilities
### Modified Capabilities
- `route-coloring`: Elevation chart gains bidirectional interaction with the map
- `map-display`: Route polyline hover reports position back to the chart
## Impact
- `ElevationChart.tsx`: Add click handler (pan map), drag-select handler (zoom map), accept highlighted index from map hover
- `PlannerMap.tsx` / `ColoredRoute.tsx`: Route polyline hover finds closest point and reports index/position back to SessionView
- `SessionView.tsx`: Wire bidirectional state between chart and map

View file

@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-04-11

View file

@ -0,0 +1,23 @@
## Why
Waypoints snapped to POIs in the Planner store OSM metadata (osmId, phone, address, website, opening hours) on the Yjs Y.Map. This data travels through GPX export and Journal save but is never displayed. When planning a multi-day bike tour, seeing campsite contact details, water point locations, or bike shop opening hours on the Journal route detail page would be valuable.
## What Changes
- **GPX export with POI metadata**: Include osmId and key tags as GPX waypoint extensions so they survive the GPX roundtrip
- **Journal route detail**: Show POI details (phone, address, website, opening hours) for waypoints that have POI metadata
- **Journal waypoint list**: Display POI icons and names alongside waypoint coordinates
## Capabilities
### Modified Capabilities
- `gpx-export`: Waypoint extensions for POI metadata
- `journal-route-detail`: POI details display for waypoints
- `route-management`: Store and retrieve POI metadata
## Impact
- `packages/gpx/src/generate.ts`: Add GPX extensions for POI tags
- `packages/gpx/src/parse.ts`: Parse POI extensions back
- `apps/journal/app/routes/routes.$id.tsx`: Display POI details per waypoint
- `@trails-cool/types`: Extend Waypoint type with optional POI fields

View file

@ -1,6 +1,6 @@
## Purpose
Multi-mode route visualization (plain, elevation gradient, surface type, grade, road type) with session-synced color mode selection. Both the route polyline on the map and the elevation chart reflect the selected color mode.
Multi-mode route visualization (plain, elevation, grade, surface, road type, speed limit, smoothness, track type, cycleway, bike route) with session-synced color mode selection. Both the route polyline on the map and the elevation chart reflect the selected color mode. Chart titles link to the corresponding OSM wiki page.
## Requirements
@ -15,24 +15,40 @@ The Planner SHALL support multiple route color modes that visualize per-point da
- **WHEN** a user selects the "Elevation" color mode
- **THEN** the route polyline is colored with a gradient from green (low) through yellow (mid) to red (high), based on the elevation at each point
#### Scenario: Surface color mode
- **WHEN** a user selects the "Surface" color mode and surface data is available from BRouter tiledesc
- **THEN** the route polyline is colored by surface type (e.g., asphalt=gray, gravel=brown, path=green, track=orange)
#### Scenario: Surface data unavailable
- **WHEN** a user selects "Surface" color mode but BRouter did not return surface data
- **THEN** the route falls back to plain color mode
#### Scenario: Grade color mode
- **WHEN** a user selects the "Grade" color mode
- **THEN** the route polyline is colored by steepness: green (<3%), yellow (<6%), orange (<10%), red (<15%), dark red (15%+)
#### Scenario: Road type color mode
- **WHEN** a user selects the "Road Type" color mode and highway data is available from BRouter tiledesc
- **THEN** the route polyline is colored by OSM highway classification using the road type color palette
#### Scenario: Surface color mode
- **WHEN** a user selects the "Surface" color mode and surface data is available from BRouter tiledesc
- **THEN** the route polyline is colored by surface type (e.g., asphalt=gray, gravel=brown, path=green)
#### Scenario: Road type data unavailable
- **WHEN** a user selects "Road Type" color mode but BRouter did not return highway data
#### Scenario: Road type color mode
- **WHEN** a user selects the "Road Type" color mode and highway data is available
- **THEN** the route polyline is colored by OSM highway classification (greens for cycling infra, grays for urban, reds for major roads)
#### Scenario: Speed limit color mode
- **WHEN** a user selects the "Speed Limit" color mode and maxspeed data is available
- **THEN** the route polyline is colored by speed limit: green (≤30), yellow (≤50), orange (≤70), red (≤100), dark red (100+)
#### Scenario: Smoothness color mode
- **WHEN** a user selects the "Smoothness" color mode and smoothness data is available
- **THEN** the route polyline is colored by road smoothness: green (excellent) through to dark red (impassable)
#### Scenario: Track type color mode
- **WHEN** a user selects the "Track Type" color mode and tracktype data is available
- **THEN** the route polyline is colored by track quality: green (grade1, best) through red (grade5, worst)
#### Scenario: Cycleway color mode
- **WHEN** a user selects the "Cycleway" color mode and cycleway data is available
- **THEN** the route polyline is colored by cycleway infrastructure type (track=green, lane=lime, shared_lane=yellow, no=red)
#### Scenario: Bike route color mode
- **WHEN** a user selects the "Bike Route" color mode
- **THEN** the route polyline is colored by bicycle route network level: purple (international), blue (national), teal (regional), emerald (local), gray (none)
#### Scenario: Data unavailable fallback
- **WHEN** a user selects any tag-based color mode but the data is not available from BRouter
- **THEN** the route falls back to plain color mode
### Requirement: Color mode toggle
@ -42,9 +58,9 @@ The Planner SHALL provide a UI control to switch between route color modes.
- **WHEN** a route is displayed
- **THEN** a color mode select dropdown is visible inline with the elevation chart title
#### Scenario: Road type option in toggle
#### Scenario: Dropdown order
- **WHEN** the color mode dropdown is displayed
- **THEN** it SHALL include a "Road Type" option alongside Plain, Elevation, Surface, and Grade
- **THEN** options appear in order: Plain, Elevation, Grade, Surface, Road Type, Speed Limit, Smoothness, Track Type, Cycleway, Bike Route
#### Scenario: Color mode persists in session
- **WHEN** a user changes the color mode
@ -53,24 +69,16 @@ The Planner SHALL provide a UI control to switch between route color modes.
### Requirement: Elevation chart color sync
The elevation profile chart SHALL use the same coloring as the route for each color mode.
#### Scenario: Elevation mode chart coloring
- **WHEN** the color mode is set to "Elevation"
- **THEN** the elevation chart line and fill use the same green→yellow→red gradient as the route polyline
#### Scenario: Surface mode chart coloring
- **WHEN** the color mode is set to "Surface" and surface data is available
- **THEN** the elevation chart segments are colored by surface type, matching the route
#### Scenario: Grade mode chart coloring
- **WHEN** the color mode is set to "Grade"
- **THEN** the elevation chart segments are colored by steepness, matching the route
#### Scenario: Chart coloring matches map
- **WHEN** any color mode is active
- **THEN** the elevation chart segments are colored using the same palette as the route polyline on the map
#### Scenario: Plain mode chart coloring
- **WHEN** the color mode is "Plain"
- **THEN** the elevation chart uses the default blue color
### Requirement: Color legends
The elevation chart SHALL display a legend matching the active color mode.
The elevation chart SHALL display an inline legend matching the active color mode.
#### Scenario: Grade legend
- **WHEN** the color mode is "Grade"
@ -78,27 +86,53 @@ The elevation chart SHALL display a legend matching the active color mode.
#### Scenario: Elevation legend
- **WHEN** the color mode is "Elevation"
- **THEN** the legend shows a gradient bar with the route's minimum and maximum elevation in meters
- **THEN** the legend shows a gradient bar with the route's min and max elevation in meters
#### Scenario: Surface legend
- **WHEN** the color mode is "Surface"
- **THEN** the legend shows the surface types present in the route with colored swatches
#### Scenario: Tag-based legends
- **WHEN** the color mode is Surface, Road Type, Smoothness, Track Type, or Cycleway
- **THEN** the legend shows the unique values present in the route with colored swatches (max 6 with overflow indicator)
#### Scenario: Road type legend
- **WHEN** the color mode is "Road Type"
- **THEN** the legend shows the highway types present in the route with colored swatches, up to 6 entries
#### Scenario: Speed limit legend
- **WHEN** the color mode is "Speed Limit"
- **THEN** the legend shows colored swatches with speed thresholds (≤30, ≤50, ≤70, ≤100, 100+)
#### Scenario: Bike route legend
- **WHEN** the color mode is "Bike Route"
- **THEN** the legend shows International, National, Regional, Local, None with colored swatches
### Requirement: Contextual hover information
The elevation chart hover label SHALL show mode-specific information.
#### Scenario: Hover label
- **WHEN** hovering the chart in any tag-based mode
- **THEN** the label shows elevation, distance, and the tag value (e.g. "340m · 12.3km · asphalt")
#### Scenario: Grade hover
- **WHEN** hovering the chart in "Grade" mode
- **THEN** the label shows elevation, distance, and grade percentage (e.g. "340m · 12.3km · +4.2%")
- **WHEN** hovering in Grade mode
- **THEN** the label additionally shows grade percentage (e.g. "+4.2%")
#### Scenario: Surface hover
- **WHEN** hovering the chart in "Surface" mode
- **THEN** the label shows elevation, distance, and surface type name (e.g. "340m · 12.3km · asphalt")
#### Scenario: Speed limit hover
- **WHEN** hovering in Speed Limit mode
- **THEN** the label shows the speed with "km/h" suffix
#### Scenario: Road type hover
- **WHEN** hovering the chart in "Road Type" mode
- **THEN** the label shows elevation, distance, and highway type name (e.g. "340m · 12.3km · cycleway")
#### Scenario: Bike route hover
- **WHEN** hovering in Bike Route mode
- **THEN** the label shows human-readable network names (International/National/Regional/Local)
### Requirement: OSM wiki links
The elevation chart title SHALL link to the corresponding OSM wiki page for tag-based modes.
#### Scenario: Title links
- **WHEN** the color mode is a tag-based mode (surface, highway, maxspeed, smoothness, tracktype, cycleway, bikeroute)
- **THEN** the chart title is a clickable link to the relevant OSM wiki page
#### Scenario: Non-tag modes
- **WHEN** the color mode is Plain, Elevation, or Grade
- **THEN** the chart title is plain text (no link)
### Requirement: BRouter profile patching
The BRouter Docker image SHALL patch profiles to expose additional tags in WayTags output.
#### Scenario: Maxspeed and tracktype exposure
- **WHEN** the BRouter Docker image is built
- **THEN** all routing profiles are patched with `assign dummyUsage2 = maxspeed=` and `assign dummyUsage3 = tracktype=` to include these tags in tiledesc WayTags