Bring the two slotted topbar actions onto the design system so the bar
reads as one cohesive surface:
- SaveToJournalButton: primary Button primitive; "saved" uses the
accent, error uses a new --color-danger token, and the return link
gets secondary token styling.
- ExportButton: token split-button (secondary look, chevron icon,
single divider) and a token dropdown menu (raised surface, soft
shadow, muted descriptions).
- New --color-danger token (#a03c3c, the no-go hue at full strength)
for error text.
Behavior and i18n unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The routeData Y.Map's ~15 string keys (geojson, coordinates,
segmentBoundaries, road metadata, profile, colorMode, baseLayer,
overlays, poiCategories) were read and written raw at ~30 call sites,
each with its own JSON parsing and casts; parseJsonArray existed twice
and waypoint extraction four times. GPX assembly was duplicated between
SaveToJournalButton and ExportButton, so the saved plan and the
exported file could silently diverge.
- new lib/route-data.ts owns the routeData (+ noGoAreas) schema:
typed read/write, JSON encoding internal, ColorMode moves here
(re-exported from ColoredRoute for existing importers)
- new lib/gpx-export.ts owns GPX assembly: buildRouteGpx /
buildPlanGpx / buildDayGpxFiles / hasDayBreaks; multi-day splitting
becomes a pure, tested function
- waypoint-ymap.ts gains extractWaypoints / extractWaypointData; the
four hand-rolled copies (use-routing, use-waypoint-manager,
WaypointSidebar, use-days) now share it, and WaypointSidebar's
moveWaypoint reuses the round-trip helpers instead of re-listing
every waypoint field
- all hooks/components consume the seam; no raw routeData key strings
remain outside route-data.ts
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Introduce waypoint-ymap.ts with typed helpers so all Yjs↔Waypoint
conversions go through one place. New Waypoint fields now only need
to be added once rather than in every consumer.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Waypoints snapped to OSM POIs in the Planner now carry their metadata all
the way through to the Journal:
- Extend Waypoint type with osmId and poiTags fields
- Extract osmId/poiTags from Yjs Y.Map in ExportButton and SaveToJournalButton
- Encode POI metadata as <trails:poi> extensions in GPX <wpt> elements
- Parse <trails:poi> extensions back in the GPX parser
- Display phone, website, opening hours, address on Journal route detail
- E2E test for the full roundtrip; seed endpoint now defaults to public visibility
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Full notes lifecycle:
- GPX: description field in GpxData, <metadata><desc> in generate/parse
- Export: Plan GPX and Save to Journal include notes as description
- Journal: updateRoute extracts description from GPX, stores on route
- Reimport: Edit in Planner passes notes via URL params → Yjs Y.Text
- Drop import: GPX with <desc> restores notes in session
Spec updated: session-notes gains GPX export, Journal sync, and
reimport requirements.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a route has overnight waypoints, the export dropdown shows a
third option: "Export Day Segments" which downloads one GPX file per
day. Each file is named day-N-start-name.gpx with the day's track
segment. Only visible when the route has multiple days.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ExportButton.getWaypoints() wasn't reading the overnight flag from
Yjs Y.Maps, so exported plan GPX was missing <type>overnight</type>.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add description text below each export option explaining the difference
- Fix z-index (z-[1001]) so dropdown renders above the map
- Align dropdown left instead of right to avoid overflow
- Widen dropdown (w-56) to fit descriptions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The document click handler registered on open could catch the same
click event that opened the dropdown, immediately closing it.
Using mousedown avoids the race since it fires before click.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The chevron was too narrow (px-1.5 → px-2.5) and clicks were
caught by the outside-click handler before toggling the dropdown.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Split button with default "Export GPX" (track only) and dropdown:
- Export Route: clean track for use in any app
- Export Plan: track + waypoints + no-go areas in GPX extensions
(trails:planning namespace) for reimporting into the planner
Also:
- Add no-go area serialization to generateGpx (GPX extensions)
- Parse no-go areas from GPX extensions on import
- Initialize no-go areas in Yjs session from imported GPX
- Save to Journal now exports track only (consistent with Export Route)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Initialize i18n via initI18n() in both root.tsx files and replace all
hardcoded user-facing strings with useTranslation() calls. Adds missing
translation keys for planner (profiles, connection states, save flow)
and journal (auth pages, route management, passkey prompts).
Both English and German translations are complete.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>