Add GPS location column to plan

Browser captures GPS coords on step 1, server reverse-geocodes
via Nominatim, and location is stored in session + written to
both Excel rows.

https://claude.ai/code/session_015myTTMs6yDsAGarATe5ePZ
This commit is contained in:
Claude 2026-03-18 18:27:41 +00:00
parent cede60cfa9
commit 0953abda86
No known key found for this signature in database

29
PLAN.md
View file

@ -20,16 +20,17 @@
| Backend | Rust + Axum | | Backend | Rust + Axum |
| AI / OCR | Claude API (vision) | | AI / OCR | Claude API (vision) |
| Spreadsheet | rust_xlsxwriter (Excel) | | Spreadsheet | rust_xlsxwriter (Excel) |
| Geocoding | browser Geolocation API + reverse-geocode REST API |
| Frontend | Mobile-friendly HTML | | Frontend | Mobile-friendly HTML |
--- ---
## Excel sheet columns ## Excel sheet columns
| Date | Time | Odometer start (km) | Odometer end (km) | Trip (km) | Notes | | Date | Time | Odometer start (km) | Odometer end (km) | Trip (km) | Location | Notes |
|------------|-------|---------------------|-------------------|-----------|-------| |------------|-------|---------------------|-------------------|-----------|-----------------|--------|
| 2026-03-18 | 08:14 | 84 273 | 84 320 | 47 | Ride 1 | | 2026-03-18 | 08:14 | 84 273 | 84 320 | 47 | Amsterdam, NL | Ride 1 |
| 2026-03-18 | 09:05 | 84 320 | 84 391 | 71 | Ride 2 | | 2026-03-18 | 09:05 | 84 320 | 84 391 | 71 | Haarlem, NL | Ride 2 |
--- ---
@ -58,6 +59,7 @@ session {
reading_1: Option<u32> # start of ride 1 reading_1: Option<u32> # start of ride 1
reading_2: Option<u32> # end of ride 1 / start of ride 2 reading_2: Option<u32> # end of ride 1 / start of ride 2
reading_3: Option<u32> # end of ride 2 reading_3: Option<u32> # end of ride 2
location: Option<String> # reverse-geocoded from GPS at step 1
} }
``` ```
@ -70,8 +72,9 @@ session is cleared.
``` ```
Step 1: "Take photo of odometer — START of ride 1" Step 1: "Take photo of odometer — START of ride 1"
[Camera button] → upload [Camera button] → upload (browser also sends GPS coords)
↓ server reads: 84 273 ✓ ↓ server reads: 84 273 ✓
↓ GPS reverse-geocoded: "Amsterdam, NL" ✓
Step 2: "Take photo of odometer — END of ride 1 / START of ride 2" Step 2: "Take photo of odometer — END of ride 1 / START of ride 2"
[Camera button] → upload [Camera button] → upload
@ -92,10 +95,11 @@ Done screen: summary + [Download Excel] + [Start new session]
## Flow (technical) ## Flow (technical)
``` ```
POST /upload?step=1 → read photo → store reading_1 in session POST /upload?step=1 → read photo + GPS coords → reverse-geocode location
→ store reading_1 + location in session
POST /upload?step=2 → read photo → store reading_2 → calc ride1 delta → show POST /upload?step=2 → read photo → store reading_2 → calc ride1 delta → show
POST /upload?step=3 → read photo → store reading_3 → calc ride2 delta POST /upload?step=3 → read photo → store reading_3 → calc ride2 delta
→ write 2 rows to Excel → return summary → write 2 rows to Excel (both with same location) → return summary
GET /download → serve mileage_log.xlsx GET /download → serve mileage_log.xlsx
``` ```
@ -104,10 +108,11 @@ GET /download → serve mileage_log.xlsx
## Implementation steps ## Implementation steps
1. Set up Axum server with in-memory session state (DashMap or Mutex<HashMap>) 1. Set up Axum server with in-memory session state (DashMap or Mutex<HashMap>)
2. Create a single `/upload` endpoint that accepts `step=1|2|3` + multipart image 2. Create a single `/upload` endpoint that accepts `step=1|2|3` + multipart image + optional lat/lon form fields
3. Send each uploaded image (base64) to Claude Vision API: "What is the odometer reading in km? Reply with only the number." 3. Send each uploaded image (base64) to Claude Vision API: "What is the odometer reading in km? Reply with only the number."
4. Parse the integer from the response and store it in the session 4. Parse the integer from the response and store it in the session
5. After step 2: calculate ride 1 km, return intermediate confirmation 5. At step 1: reverse-geocode lat/lon via a free API (e.g. nominatim.openstreetmap.org) → store city/address in session
6. After step 3: calculate ride 2 km, append both rows to the Excel file, clear session 6. After step 2: calculate ride 1 km, return intermediate confirmation
7. Mobile-friendly step-by-step HTML UI (progress indicator, camera capture) 7. After step 3: calculate ride 2 km, append both rows (with location) to the Excel file, clear session
8. `GET /download` endpoint to serve the Excel file 8. Mobile-friendly step-by-step HTML UI: request GPS on load, attach coords to each upload, progress indicator
9. `GET /download` endpoint to serve the Excel file