Files
intotheeast-com/docs/working/2026-06-21-travel-memories-handover.md
T
2026-06-21 21:41:24 +02:00

87 lines
5.1 KiB
Markdown

# travel-memories — Session Handover (2026-06-21)
## What this is
`services/travel-memories/` is a local Flask app that turns Immich photo albums into Grav CMS journal entries and story pages. It runs at **http://localhost:8082** via Docker.
## Current state
All 11 SDD tasks are complete. The app is fully functional end-to-end across all 6 phases. This session was spent fixing bugs discovered during real use and adding triage UX improvements.
**Last commit:** `a265b08` — fix: use amber/sky colors for journal/story borders and badges
## What was built this session
### New triage UX (Phase 2)
**Desktop:**
- **Selection ring**: white ring on currently focused card; first card auto-selected on load
- **Arrow key navigation**: `←` / `→` move the selection ring through photos
- **Enter**: open lightbox for current card; **click**: also opens lightbox
- **Lightbox**: full-screen overlay — `←`/`→` navigate, `J`/`S`/`X` tag without closing, `Esc` close; badge + date shown at bottom
- **Badge**: amber J / sky S / ghost X on every tagged photo; updates dynamically when tag changes
- **Colored borders**: amber (`border-amber-500`) for journal, sky blue (`border-sky-400`) for story, dimmed for skip
- **Skip all untagged** button: bulk-skips everything still untagged
**Mobile (<768px):**
- Tinder-style HammerJS swipe cards: right=journal, left=skip, up=story
- Card tilts + color overlay during drag (amber/sky/grey)
- Three tap buttons (X / J / S) below the card as alternative
- Back button with undo stack (max 10 actions)
- Progress bar synced with header counter
- Horizontal thumbnail strip at bottom: all photos, colored dot per tag, tap to jump to any photo
## Bugs fixed this session
| Bug | Root cause | Fix |
|---|---|---|
| Triage badge not updating on tag change | Badge is server-rendered; JS wasn't updating it | Added `updateBadge(el, tag)` helper called after each tag |
| Arrow keys not working | Alpine modifier is `left`/`right` not `arrowleft`/`arrowright` | Fixed modifier names |
| Dimmed photo stays dimmed after retag | Jinja classes have newlines → `.split(' ')` produces `'opacity-40\n'` not `'opacity-40'` | Changed to `.split(/\s+/).filter(c => c && ...)` |
| Colored border disappears after retag | Filter `!c.startsWith('border-')` strips `border-4` (width) too | Re-add `border-4` alongside color class |
| Borders appear white | DaisyUI `border-success`/`border-info` near-invisible in `forest` theme | Use explicit Tailwind: `border-amber-500`, `border-sky-400` |
| Badge text unreadable | DaisyUI badge semantic classes give poor contrast in `forest` theme | Use `bg-amber-500 text-black border-0 font-bold` etc. |
## Gotchas for next session
- **Docker rebuild required after any template/code change**: `docker compose build travel-memories && docker compose up -d --force-recreate travel-memories`
- **`--force-recreate` required** to pick up `.env` changes (plain `restart` doesn't re-read it)
- **Immich API key needs scopes**: `album.read`, `asset.read`, `asset.download` (Immich calls it `asset.view` in some versions — check the Immich UI)
- **State directory permissions**: if state/ was created as root, run `docker compose exec -u root travel-memories chown 1000:1000 /app/state`
- **Never read `.env`** — contains real Immich credentials; pass to docker commands only
## What's not done yet
Nothing was explicitly left incomplete — the pipeline works end-to-end. Potential next steps:
1. **Full-resolution lightbox**: currently shows Immich preview thumbnail; could load `/proxy/original/<id>` for the full-res image (endpoint may need adding to `routes/proxy.py`)
2. **End-to-end test for triage UX**: the new JS-heavy triage UI has no Playwright coverage
3. **Phase 2 → real trip**: use the app on the actual japan-korea-2026 Immich album
4. **Mobile swipe color consistency**: swipe-right currently shows green overlay (intuitive for "go") — could switch to amber to match journal color, but debatable
## File map
```
services/travel-memories/
├── app/
│ ├── __init__.py Flask factory
│ ├── immich.py Immich API client (x-api-key auth)
│ ├── state.py TripState / Photo models, atomic JSON R/W
│ └── routes/
│ ├── albums.py Phase 1 — album selection + slug sanitisation
│ ├── triage.py Phase 2 — tag/skip-untagged/done endpoints
│ ├── curate.py Phase 3 — reorder/swap
│ ├── group.py Phase 4 — grouping + dividers
│ ├── write.py Phase 5 — titles/captions
│ ├── export.py Phase 6 — write Grav markdown files
│ ├── proxy.py Immich thumbnail proxy
│ └── nav.py Shared nav context + stale propagation
│ └── templates/
│ ├── base.html DaisyUI forest + Alpine + HammerJS CDN
│ ├── phase1.html Album selection
│ ├── phase2.html Triage (desktop grid + mobile swipe + lightbox)
│ └── phase[3-6].html Curate, group, write, export
├── Dockerfile
└── docker-compose.yml Port 8082, UID/GID env vars, state volume
```