Files
samplez/rippr-src/docs/v2/11-trip-detail.md
uhryniuk 280fd7f988 Add Rippr source snapshot and full-history bundle
Two copies for two jobs. rippr-src/ is a browsable git archive export of
the tracked tree at 2f76983 - no build outputs, no local.properties, no
nested .git - which is convenient to read in gitea but carries no history
and will drift.

rippr-full-history.bundle is the real backup: all 18 commits, verified as
"records a complete history" and test-cloned before committing. This
matters because ~/dojo/rippr has no git remote and otherwise exists only
on one machine.

rippr-src/SNAPSHOT.md explains the difference and how to restore.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 08:30:25 -05:00

87 lines
3.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# T11 — Trip detail screen (stats only)
**Phase** 4 · **Depends on** T05, T08 · **Status** Done
## Goal
A full breakdown of a single ride — summary figures, elevation profile, speed
distribution — with a deliberate placeholder where the map will go. Done when every
statistic renders correctly and the screen is verifiable before osmdroid lands.
## Context
Splitting this from the map is intentional. osmdroid brings tile caching, `MapView`
lifecycle, and coordinate projection — three sources of subtle failure. Building the
screen first means that when the map misbehaves in T13, the surrounding screen is already
known-good and the bug has nowhere to hide.
Data comes from `RideStatistics.compute()` (T05) over `pointsForTrip(id)` and
`segmentsForTrip(id)`. Unlike the list screen, this one **does** load points — a few
thousand rows for one trip is fine, and the derived series need them.
## Design
Sections top to bottom:
1. **Header** — name (inline-editable in T12) and start date/time
2. **Map placeholder** — a bordered box captioned "Map coming in T13", replaced wholesale
by T13/T14. Reserving the space now means the layout does not shift later.
3. **Summary grid** — distance, moving time, elapsed time, max speed, average moving
speed, elevation gain
4. **Elevation profile** — line chart over distance-along-path
5. **Speed distribution** — histogram in 10 km/h buckets
6. **Segments** — listed only when there is more than one, showing where the ride paused
Charts are drawn with **Compose `Canvas`**, not a charting library. Two simple series do
not justify a dependency, and hand-drawn keeps them consistent with the existing visual
language.
Both charts need: an explicit empty/insufficient-data state, axis labels with units, and
`tabular-nums` on any numeric label.
**Point loading happens off the main thread** in the ViewModel, with a loading state. A
three-hour ride is ~21,600 rows; loading that synchronously would jank the transition
into the screen.
## Implementation
1. `TripDetailViewModel` loading trip, points, and segments on `Dispatchers.IO`, exposing
`Loading | Ready(summary, profile, histogram, segments) | NotFound`.
2. Summary grid from `RideSummary`.
3. `ElevationChart` composable — `Canvas`, path stroke, min/max labels.
4. `SpeedHistogram` composable — `Canvas`, bars, bucket labels.
5. Segment list, shown conditionally.
6. Map placeholder box.
7. `NotFound` state for a deleted trip.
## Acceptance criteria
- [x] All summary figures match `RideStatistics.compute()`
- [ ] Charts render for a real ride and degrade gracefully with <2 points
- [x] Segments section appears only when the ride was paused
- [x] Loading state shown while points load; no main-thread I/O
- [ ] Deleted trip shows `NotFound` rather than crashing
- [x] Map placeholder occupies the space the real map will take
> **Not verified.** The unchecked items above, and the Compose UI tests below, were
> not done. Verification for T08–T11 was manual on the emulator (screenshots through
> the full flow) plus the existing unit and instrumented suites. Compose UI tests are
> outstanding — tracked in T18.
## Tests
Compose UI tests: loading, ready, not-found, single-segment vs multi-segment.
Unit tests for the chart data-preparation helpers (scaling, bucketing) — the drawing
itself is verified by screenshot on the emulator.
## Risks / gotchas
- **Main-thread point loading is the obvious trap here.** Keep it in the ViewModel on IO.
- **Chart division by zero** when all altitudes or speeds are identical — a flat ride
gives a zero-height range. Guard the scaling.
- **Do not start integrating the map in this task.** The separation is the point.
## Out of scope
The map (T13, T14), rename/delete/merge (T12), export (T16).