Archive journal-poi-details change; sync journal-route-detail spec
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
861701e881
commit
faf2227896
6 changed files with 20 additions and 0 deletions
|
|
@ -0,0 +1,2 @@
|
|||
schema: spec-driven
|
||||
created: 2026-04-11
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
# Design: Journal POI Details
|
||||
|
||||
## Data Flow
|
||||
|
||||
POI metadata already flows from Overpass → POI snap → Yjs Y.Map (`osmId`, `poiTags`). The gap is that neither GPX export nor the Journal save extracts these fields.
|
||||
|
||||
```
|
||||
Yjs Y.Map
|
||||
{ lat, lon, name, overnight, osmId, poiTags: { phone, website, ... } }
|
||||
↓ (currently drops osmId + poiTags)
|
||||
Waypoint type → generateGpx → GPX <wpt>
|
||||
↓
|
||||
Journal DB → route.gpx
|
||||
↓ (currently not parsed)
|
||||
Journal route detail page
|
||||
```
|
||||
|
||||
## Changes
|
||||
|
||||
### 1. `@trails-cool/types` — extend `Waypoint`
|
||||
|
||||
Add optional POI fields to the shared `Waypoint` interface:
|
||||
|
||||
```ts
|
||||
export interface Waypoint {
|
||||
lat: number;
|
||||
lon: number;
|
||||
name?: string;
|
||||
isDayBreak?: boolean;
|
||||
osmId?: number;
|
||||
poiTags?: {
|
||||
phone?: string;
|
||||
website?: string;
|
||||
opening_hours?: string;
|
||||
"addr:street"?: string;
|
||||
"addr:housenumber"?: string;
|
||||
"addr:postcode"?: string;
|
||||
"addr:city"?: string;
|
||||
amenity?: string;
|
||||
tourism?: string;
|
||||
shop?: string;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Planner — extract `osmId` + `poiTags` from Yjs
|
||||
|
||||
In `ExportButton.tsx` and `SaveToJournalButton.tsx`, add the two fields to the waypoint mapping:
|
||||
|
||||
```ts
|
||||
osmId: yMap.get("osmId") as number | undefined,
|
||||
poiTags: yMap.get("poiTags") as Waypoint["poiTags"] | undefined,
|
||||
```
|
||||
|
||||
### 3. GPX — encode/decode POI fields as `<extensions>`
|
||||
|
||||
**`generate.ts`**: When a waypoint has `osmId` or `poiTags`, emit a `<extensions><trails:poi ...>` block inside `<wpt>`. Always declare the `trails:` namespace on the root `<gpx>` element (already done for noGoAreas, just extend the condition).
|
||||
|
||||
```xml
|
||||
<wpt lat="52.5" lon="13.4">
|
||||
<name>Fahrradhändler Müller</name>
|
||||
<extensions>
|
||||
<trails:poi osmId="123456">
|
||||
<trails:tag k="phone" v="+49 30 12345"/>
|
||||
<trails:tag k="website" v="https://example.com"/>
|
||||
<trails:tag k="opening_hours" v="Mo-Fr 09:00-18:00"/>
|
||||
</trails:poi>
|
||||
</extensions>
|
||||
</wpt>
|
||||
```
|
||||
|
||||
**`parse.ts`**: In `parseWaypoints`, query `trails:poi` (and unprefixed `poi`) extensions; read the `osmId` attribute and `trails:tag` children.
|
||||
|
||||
### 4. Journal route detail — display POI metadata
|
||||
|
||||
In `routes.$id.tsx`:
|
||||
- Parse waypoints from `route.gpx` in the loader (already done for `dayStats`, can reuse that parse)
|
||||
- Pass waypoints with POI data to the component
|
||||
- Render a `WaypointList` section showing: waypoint name + coords, and if `poiTags` present: phone (tel: link), website (https: link), opening hours, address
|
||||
|
||||
No new DB columns needed — everything lives in the GPX string already stored in `routes.gpx`.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- No new DB columns for POI data
|
||||
- No Overpass lookups in the Journal
|
||||
- No display of `osmId` to the user (internal reference only)
|
||||
- Opening hours parsing/formatting: display raw string as-is
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: POI metadata on route detail waypoints
|
||||
The Journal route detail page SHALL display POI metadata (phone, address, website, opening hours) for waypoints that have associated OpenStreetMap POI data.
|
||||
|
||||
#### Scenario: POI metadata displayed on waypoints
|
||||
- **WHEN** a route detail page is loaded and a waypoint has POI metadata from the Planner
|
||||
- **THEN** the waypoint displays the POI name, icon, and category alongside its coordinates
|
||||
|
||||
#### Scenario: Phone, address, and website shown
|
||||
- **WHEN** a waypoint has POI metadata including phone, address, or website
|
||||
- **THEN** those details are shown in the waypoint detail section with appropriate links (tel: for phone, mailto: or https: for website)
|
||||
|
||||
#### Scenario: Waypoints without POI data display normally
|
||||
- **WHEN** a waypoint on the route detail page has no associated POI metadata
|
||||
- **THEN** the waypoint displays as before with coordinates and name only, with no empty POI sections shown
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
# Tasks: Journal POI Details
|
||||
|
||||
- [x] Extend `Waypoint` type in `packages/types/src/index.ts` with `osmId` and `poiTags` fields
|
||||
- [x] Extract `osmId` and `poiTags` from Yjs Y.Map in `apps/planner/app/components/ExportButton.tsx`
|
||||
- [x] Extract `osmId` and `poiTags` from Yjs Y.Map in `apps/planner/app/components/SaveToJournalButton.tsx`
|
||||
- [x] Encode POI fields as `<trails:poi>` extensions in `packages/gpx/src/generate.ts`
|
||||
- [x] Parse `<trails:poi>` extensions back into waypoints in `packages/gpx/src/parse.ts`
|
||||
- [x] Add unit tests for GPX POI encode/decode roundtrip in `packages/gpx/src/`
|
||||
- [x] Pass parsed waypoints with POI data from the loader in `apps/journal/app/routes/routes.$id.tsx`
|
||||
- [x] Render POI details (phone, website, opening hours, address) for waypoints in the Journal route detail page
|
||||
- [x] Add i18n keys for POI section labels (phone, website, opening hours, address)
|
||||
Loading…
Add table
Add a link
Reference in a new issue