09-Sep-2026 — OS Maps routes page - search-first landing, real map thumbnails, mobile-responsive card #99
build 885 — commit 66a062c
maps: OS Maps routes page (#99)
The problem
The routes page loaded and displayed every saved route at once (630+ on a busy account) in a plain table - overwhelming, slow to scan, and none of it worked on a phone.
Search-first landing, capped results
Nothing is shown until you type a search or choose a filter; the landing state explains how many routes there are and prompts you to search. Results are capped to the first 50 matches, with a note showing the total and asking you to narrow the search when there are more. Sorting moved to a Sort by control with a direction toggle.
Real map thumbnails
For routes that have already been converted, the real GPX geometry is already held in S3, so each card fetches it (reusing GpxParserService, RouteFollowPayloadService.gpxDownloadUrl and MapTilesService's base layer - the same machinery the app's full map views already use) and draws an actual small Leaflet map: real OpenStreetMap tiles, the route line in its saved colour, fitted to the route's bounds. A checkmark badge on the thumbnail corner shows imported status, matching OS Maps' own visual language, instead of a separate text field. Not-yet-imported routes, which have no geometry anywhere in our system, keep an icon placeholder.
Getting the map's lifecycle right took a few passes: Angular's structural @if was recreating the map's container on every data change, and the leaflet directive gave no way to guard against Leaflet's "container is being reused" error when @for reused a DOM node across component instances faster than the old map's teardown ran. Fixed by taking direct control of L.map() construction in ngAfterViewInit, with an explicit clear of any stale internal marker before creating a new map.
Card layout matching OS Maps' own design
Distance, date, a source badge and an imported-status line were crammed into one free-flowing row, so a longer title or date pushed everything after it sideways - a jagged, misaligned look row to row. Rebuilt to match OS Maps' own card design instead: one short metadata line (distance + a compact date, not the full weekday form), source as an icon-only tooltip rather than a text badge, imported status moved to the thumbnail badge. The title (for already-imported routes) and the thumbnail now open this app's own edit page directly, since "Open in OS Maps" already covers the external link and having both was redundant; the separate edit icon button is gone.
Also added the real OS Maps logo (already used elsewhere in the app for attribution) to the "Open in OS Maps" link, in place of a generic icon.
Mobile
- The thumbnail stretches to fill the card's actual height rather than sitting at a fixed size while wrapped titles make mobile cards much taller - capped at 140px so a very tall card doesn't stretch it into a sliver.
- Back to walks admin / Convert selected to GPX / Load routes from OS Maps go full width and stack on narrow screens; Last loaded and the refresh button stay grouped as one unit.
- Search / Show / Sort by each take the full row width on narrow screens.
- Tightened row gaps that were adding more vertical space than the shorter, single-line content needed.
Diagnostics
Added a one-off debug log of the real OS Maps routes/search response shape (route names redacted) - the fields we map today (id, title, date, distance) are a small slice of what that response might carry, and this lets a future pass build a real preview for not-yet-imported routes against the actual payload instead of a guess.