Closes #129
Adds "Verspätung" (Late) as a selectable absence reason in the Abmelden form.
What changed
absentReasonsnow includesLate(beforeSonstiges) + hourglass Icon- New
Latebranch: a single "Voraussichtliche Ankunft — heute um" time input, no day pickers. - Default arrival time is now rounded up to the next 15 minutes (9:12 → 9:15), so the common "kommt gleich" case is one tap.
from_dateis implicit and never shown:max(today 00:00, last checkout today). Recorded at creation time; editing an existing Verspätung keeps the storedfrom_dateand only movesuntil_date.- Choosing an arrival before the pupil's checkout surfaces the existing "Bitte wähle einen gültigen Zeitraum aus." validation error instead of silently adjusting the range.
The API already supports AbsentReason::Late (#147).
Verified
yarn checkpasses (lint + types + tests).- Live walkthrough against the dev API:
- pupil without a checkout today:
POST /absent→from_date= today 00:00 local,until_date= today at the chosen time,reason: "Late"(201); - pupil checked in and out today:
POST /absent→from_date= the exact checkout timestamp (201); - default time correctly rounded up (11:42 → 11:45, 11:47 → 12:00); changing the time works;
- arrival before the checkout → validation error, no request sent;
- edit: only
until_datemoves,from_dateunchanged (PUT 200); delete works (DELETE 204); - absence badge shows the Late icon ("bis 12:30 ⌛") on the pupil card.
- pupil without a checkout today:
Closes #129
Adds "Verspätung" (Late) as a selectable absence reason in the Abmelden form.
## What changed
- `absentReasons` now includes `Late` (before `Sonstiges`) + hourglass Icon
- New `Late` branch: a single "Voraussichtliche Ankunft — heute um" time input, no day pickers.
- Default arrival time is *now rounded up to the next 15 minutes* (9:12 → 9:15), so the common "kommt gleich" case is one tap.
- `from_date` is implicit and never shown: `max(today 00:00, last checkout today)`. Recorded at creation time; editing an existing Verspätung keeps the stored `from_date` and only moves `until_date`.
- Choosing an arrival before the pupil's checkout surfaces the existing "Bitte wähle einen gültigen Zeitraum aus." validation error instead of silently adjusting the range.
The API already supports `AbsentReason::Late` (#147).
## Verified
- `yarn check` passes (lint + types + tests).
- Live walkthrough against the dev API:
- pupil without a checkout today: `POST /absent` → `from_date` = today 00:00 local, `until_date` = today at the chosen time, `reason: "Late"` (201);
- pupil checked in and out today: `POST /absent` → `from_date` = the exact checkout timestamp (201);
- default time correctly rounded up (11:42 → 11:45, 11:47 → 12:00); changing the time works;
- arrival before the checkout → validation error, no request sent;
- edit: only `until_date` moves, `from_date` unchanged (PUT 200); delete works (DELETE 204);
- absence badge shows the Late icon ("bis 12:30 ⌛") on the pupil card.