- Create recent_events.py helper for rendering event lists with humanized
timestamps and deleted event styling (line-through + opacity)
- Query events with ORDER BY ts_utc DESC to show newest first
- Join event_tombstones to detect deleted events
- Fix move form to read animal_ids (not resolved_ids) from entity_refs
- Fix feed purchase format to use total_kg from entity_refs
- Use hx_get with #event-panel-content target for slide-over panel
- Add days-since-last stats for move and feed forms
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
POST routes were returning HTMLResponse(content=to_xml(...)) which
bypassed FastHTML's toast middleware. The middleware only injects
toasts for tuple, FT, or FtResponse responses.
Changed 12 routes to return render_page() directly:
- actions.py: 7 routes (cohort, hatch, tag-add, tag-end, attrs, outcome, status-correct)
- eggs.py: 2 routes (product-collected, product-sold)
- feed.py: 2 routes (feed-given, feed-purchased)
- move.py: 1 route (animal-move)
Updated tests to check for toast content in response body instead of
session cookie, since middleware now renders toasts inline.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Three major features implemented:
1. Event Detail Slide-Over Panel
- Click timeline events to view details in slide-over
- New /events/{event_id} route and event_detail.py template
- Type-specific payload rendering for all event types
2. Toast System Refactor
- Switch from custom addEventListener to FastHTML's add_toast()
- Replace HX-Trigger headers with session-based toasts
- Add event links in toast messages
- Replace addEventListener with hx_on_* in templates
3. Checkbox Selection for Animal Subsets
- New animal_select.py component with checkbox list
- New /api/compute-hash and /api/selection-preview endpoints
- Add subset_mode support to SelectionContext validation
- Update 5 forms: outcome, move, tag-add, tag-end, attrs
- Users can select specific animals from filtered results
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add Move Animals form with selection context validation and concurrent
change handling via optimistic locking. When selection changes between
client resolution and submit, the user is shown a diff panel and can
confirm to proceed with the current server resolution.
Key changes:
- Add move template with form and diff panel components
- Add move routes (GET /move, POST /actions/animal-move)
- Register move routes in app
- Fix to_xml() usage for HTMLResponse (was using str())
- Use max(current_time, form_ts) for confirmed re-resolution
Tests:
- 15 route tests covering form rendering, success, validation, mismatch
- 7 E2E tests for optimistic lock flow (spec §21.8)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>