PR-4 of the Fristen+Termine unification, closing out t-paliad-110.
Fristen rail (was 5 cards):
- Erledigt card removed (status=completed stays reachable via the EventsPage
filter dropdown — no card on the rail per the new model)
- Später card added (pending deadlines past Mon-week-after, click filters
to /deadlines?status=later)
- 4+1 final shape: Überfällig (conditional alarm) · Heute · Diese Woche ·
Nächste Woche · Später
Termine rail (new): 3 cards — Heute · Diese Woche · Später. No Überfällig
(past appointments aren't urgent), no Nächste Woche (low-value distinction
for appointments per the design rationale). Cards click through to
/appointments?status=… so users land in the matching EventsPage view.
Backend (DashboardService.loadSummary):
- DeadlineSummary.CompletedThisWeek dropped, .Later added
- AppointmentSummary added (Today / ThisWeek / Later)
- One CTE-based query computes both rails alongside MatterSummary; bucket
cutoffs share computeDeadlineBucketBounds with /api/events/summary +
/api/deadlines/summary so all three surfaces stay in lockstep
Frontend:
- dashboard.tsx: Erledigt card removed, Später card + Termine section added
- client/dashboard.ts: types updated, renderAppointmentSummary added
- 4 new i18n keys (DE+EN): dashboard.summary.later +
dashboard.appointment_summary.heading
- CSS: .dashboard-card-later (muted blue) + 3 .dashboard-card-appt-* rules
reusing the existing --bucket-* tokens
go build/vet/test ./... clean. bun run build clean (1396 keys).