# Local family dashboard calendar + exams pattern

Use for local family/PWA dashboards that add school calendars, exams, study plans, and child-facing calendar views after the Home/Todo + task ledger slice exists.

## Durable implementation pattern

1. **Calendar API shape**
   - Provide a bounded range endpoint such as `GET /api/calendar?start=YYYY-MM-DD&weeks=3`.
   - Clamp `weeks` to a safe small range; the iPad MVP usually needs exactly 21 day cards.
   - Return day buckets, not raw flat rows: each day should include `date`, `is_today`, `is_weekend`, `exams`, `study_items`, and `special_days`.
   - Include child display metadata (`child_name`, `child_color`) in chips so the frontend does not need N+1 lookups.

2. **Exam admin API and Admin-calendar UX**
   - Add minimal admin endpoints before building full Admin UI: list active exams, create, update/patch, cancel, and optionally `DELETE /admin/exams/{id}` as a cancellation alias for UI ergonomics.
   - Exam create should call the study-plan generator in the same transaction.
   - Exam update should regenerate or reconcile study items when `exam_date`, `study_sessions`, `include_weekends`, or status changes.
   - Cancel/delete should mark the exam cancelled and hide it from the child-facing calendar.
   - Put exam create/list/delete controls inside the Admin menu under a **Kalender / Prüfung** section. Outside Admin, the Calendar view stays read-only: no edit buttons, no delete actions, no accidental child-facing mutations.
   - When the user asks to remove all previously entered exams from an existing local database, treat it as destructive data cleanup: get explicit confirmation/approval, then remove/cancel the existing `Exam` rows plus linked `StudyPlanItem` rows and generated `TaskInstance(source="study-plan")` entries; do not silently retry through another mechanism if approval blocks the cleanup.
   - **Guard the timetable while cleaning exams.** Exam cleanup must never touch `ScheduleBlock`, `ScheduleDay`, or `ScheduleTimeSlot`. Before and after cleanup, record counts for `scheduleblock`, `scheduleday`, `scheduletimeslot`, `exam`, `studyplanitem`, and study-plan `taskinstance` rows. If the user later says the admin-entered timetable disappeared, first verify DB/API reality (`/api/schedule/current`, Docker `/data/familydashboard.db`, local `backend/data/familydashboard.db`, backups, volumes) before telling them to re-enter anything. Often the data exists but the admin/view/filter is misleading.

3. **Study plan generation**
   - Generate study dates backwards from the day before the exam.
   - Support `include_weekends`; when false, skip Saturday/Sunday.
   - Create `StudyPlanItem` rows plus linked `TaskInstance` rows of kind `study` so learning appears on Home/Todo.
   - Keep generation idempotent using a uniqueness constraint on `(exam_id, child_id, study_date)`.

4. **Cancellation semantics**
   - Do not delete historical study-plan rows by default.
   - Mark `StudyPlanItem.cancelled = true`.
   - For linked study tasks that are not already done, set `TaskInstance.status = cancelled`.
   - Calendar output should exclude cancelled exams and cancelled study items.

5. **Frontend 3-week view**
   - Build a `Calendar3WeekView` with `repeat(7, minmax(0, 1fr))` so 21 cards render as 3 rows on iPad landscape.
   - Highlight today strongly, weekends softly, and render exams/study/special days as compact chips.
   - Wire navigation through existing side nav before adding a full router if the app is still MVP-simple.

6. **Verification strategy**
   - Backend tests should cover: exam with 3 study sessions, weekend inclusion, weekend exclusion, cancellation hiding calendar entries and cancelling tasks, and study tasks appearing on Home/Todo.
   - Add an API smoke that creates an exam in a temporary DB, asserts `calendar_days == 21`, `exam_chips == 1`, `study_chips == 3`, and confirms a study task title appears in `/api/dashboard` for a study date.
   - If Docker lifecycle commands are approval-blocked after build/start, report the block separately and do not claim endpoint smoke success.

## Pitfalls

- Do not let study-plan task generation collide with template-generated tasks: study tasks should have `task_template_id=None` and `source="study-plan"`.
- Do not treat cancelled study tasks as open on Home/Todo; Dashboard serialization should keep open/done filters explicit.
- Avoid overbuilding the Admin UI in this phase; the Bauplan’s admin CRUD/full layout usually comes later.
