# FamilyDashboard Bildschirmzeit workflows

Use when adding or debugging FamilyDashboard screen-time features: countdown timers, per-day allowances, earned screen-time tasks, Shop exchanges, Admin weekly reports, and sidebar remaining-time badges.

## Durable patterns

1. **Allowance model**
   - Keep daily allowance separate from sessions: `base_minutes + bonus_minutes + adjustment_minutes`.
   - Default allowance is an `AppSetting` (`screen_time_default_daily_minutes`) and should be read when creating missing per-child/day rows.
   - When changing the default (e.g. 60 → 40), update both the seed/default setting and existing untouched allowance rows where safe (`base_minutes` old default and no bonus/adjustment). Do not overwrite rows with admin changes, earned bonus, or adjustments.

2. **Timer semantics**
   - Backend `remaining_seconds` is the canonical snapshot at response time.
   - Frontend countdown should decrement from the received snapshot time, not parse a server timestamp as local/UTC truth. Server datetimes may be SQLite naive strings; parsing them in JS can make timers jump to zero.
   - In the UI, store `snapshotMs = Date.now()` whenever `remaining_seconds`, `used_seconds`, `is_running`, or active session id changes; while running, compute `displayRemaining = remaining_seconds - elapsedSinceSnapshot`.
   - On stop, calculate `duration_seconds` **before** setting `ended_at`, otherwise helper functions that treat ended sessions as fixed-duration can persist `0` seconds.

3. **Earned screen-time tasks**
   - Model these as separate rules (e.g. `ScreenTimeEarnRule`) and completions, not as coin tasks.
   - Seed default rules additively: `20 Minuten Buch lesen → +10 Min +1 Coin`, `20 Minuten Sport → +10 Min +1 Coin`.
   - Rules have both `reward_minutes` and `coin_reward`; Admin can create more rules and adjust both values. Persist each completion’s recorded `reward_minutes` and `coin_reward` so later admin changes do not rewrite past rewards.
   - Completion should be idempotent per child/rule/day and add to the day allowance `bonus_minutes` exactly once. If `coin_reward > 0`, append a normal positive `CoinTransaction` as well.
   - Earned bonus screen-time must be **reversible from the child home page**, analogous to ordinary required-task undo: if a child taps a rule by mistake, the UI should show a clear “Zurücknehmen” state and an undo endpoint should delete that completion, subtract only that completion’s recorded `reward_minutes` from `bonus_minutes`, and append a negative undo coin transaction for that completion’s recorded `coin_reward`.
   - Child dashboard display belongs below Pflicht/Bonus sections as “Bildschirmzeit verdienen”.
   - Admin portal should list/toggle/manage rules in the Bildschirmzeit tab, separate from ordinary task templates. Define static routes such as `/admin/screen-time/earn-rules/{rule_id}` before broad dynamic routes like `/admin/screen-time/{child_id}/{target_date}` so FastAPI does not parse `earn-rules` as `child_id`.

4. **Child-facing copy outside Admin**
   - Any page outside Adminportal is for the children first. Write instructions directly to the child using “du/deine”, not developer/parent/system phrasing.
   - Avoid copy like “Jedes Kind…”, “Der Timer läuft…”, “Admin-Verwaltung…”, or abstract implementation descriptions. Prefer action text: “Du hast heute 40 Minuten”, “Drück auf Starten…”, “Wenn du fertig bist, stoppst du ihn wieder”, “Tausch deine Coins ein”.
   - Keep Adminportal copy parent/admin-oriented; this rule applies to Home, Bildschirmzeit, Shop, tasks, and other child-facing pages.

5. **Parent weekly report**
   - Build from the same per-day summaries used by Admin weekly allowance view.
   - Per child, show planned minutes, used minutes, earned/bonus minutes, and locked day count.
   - Keep report values minute-rounded for parent readability; raw seconds are for API/internal logic only.

6. **Production hygiene**
   - Back up production DB before schema/setting/data changes.
   - Never run tests against the production bind mount; use `/tmp/familydashboard-test.db` before importing app DB modules.
   - If earlier buggy timer sessions polluted today’s usage, remove only clearly synthetic/test sessions and verify the live API returns the intended remaining seconds; do not blanket-reset real family history without user intent.

## Verification checklist

- Backend unit/API tests cover:
  - default allowance starts at configured default minutes;
  - start/stop records positive duration;
  - shop exchange subtracts coins and adds minutes once;
  - admin week range and per-day adjustment;
  - earned screen-time completion adds bonus minutes once;
  - earned screen-time undo removes the completion and subtracts its bonus minutes;
  - weekly report counts earned minutes.
- Frontend copy review for child-facing pages confirms instructions address the child directly and do not mention developer/admin/system concerns outside Adminportal.
- Frontend `npm run build` passes after adding new types/components.
- Live smoke after deploy:
  - `GET /api/screen-time?date=YYYY-MM-DD` returns expected `remaining_seconds` (e.g. 2400 for 40 min);
  - start → after ~2s remaining decreases by ~2 → stop stores duration;
  - `/api/admin/screen-time/report` returns parent summaries;
  - sidebar badge and child “Bildschirmzeit verdienen” section render after PWA refresh.
