Files
F-r-ldraledigplannerare/frontend_mvp_complete.md
T
2026-06-14 09:58:30 +02:00

111 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Junior Developer — Frontend MVP Completion TODO
**Owner:** Junior developer
**Status:** Ready to implement (tackle **after** `frontend_polish.md`)
**Goal:** Close the gap between the bare happy path and the app described in `ARCHITECTURE.md` — a usable shell with navigation, a working settings page, calendar planning, the manual-data fallback, and partner planning.
> **Why this plan exists:** the current dashboard has no header nav, no logged-in user, no child indicator, no logout, and no reachable settings — so features that already exist in code (Calendar, Tips, Settings, manual entry) are stranded. The backend endpoints for all of this already exist; this is almost entirely **frontend wiring**.
>
> Work in tiers, top to bottom. **Tier 1 is the highest value** (it's what makes the app feel like an app). Keep `tsc`/lint/tests green per task. CSS stays optional — structure and function over looks.
---
## TIER 1 — App shell: navigation, identity, working settings
### T1.1 — Real header (user, current child + switcher, nav, logout)
**Problem:** `components/layout/Header.tsx` already accepts `onLogout` / `onWorkspaceSelect`, but pages only pass `{ title }`, so the nav is empty. There's no way to log out, switch pages, or see who/which child you're viewing.
**Do — extend `Header` and wire it via `Layout` on every page:**
- **Logged-in identity:** show the current parent's name. ⚠️ `GET /api/auth/context` does **not** currently return the parent's display name (only `personal_data_uuid`, `workspace_id`, `children`). Either show the email from `GET /api/auth/me`, or **ask the senior to add `name` to the `/auth/context` payload** (small, preferred). Don't hardcode.
- **Current child + switcher:** `useWorkspace()` exposes `children`, `selectedChildId`, `selectChild()`. Render a `<select>` of children; changing it calls `selectChild(id)`. Show the selected child's name in the header. (If only one child, a static label is fine.)
- **Nav links:** Översikt (`/`), Kalender (`/calendar`), Tips (`/tips`), Inställningar (`/settings`) using `react-router` `<Link>`/`NavLink`. These routes already exist in `App.tsx`.
- **Logout:** a "Logga ut" button → `useAuth().logout()` then `navigate('/auth', { replace: true })`.
- Apply the header consistently: pass the nav/user/logout props through `Layout` so every page gets the same shell (Dashboard, Calendar, Tips, Settings).
**Acceptance:** Every authenticated page shows a header with the parent's name, a child selector reflecting/affecting `selectedChildId`, working nav links to all four pages, and a logout button that returns you to `/auth`.
---
### T1.2 — Make Settings reachable and actually save
**Problem:** `pages/Settings.tsx` renders the right inputs but most saves are no-ops or broken. Notably `handleSaveVacationDays` sends `personalDataUuid: 'current-user'` (a hardcoded string, not a UUID); the **parent profile** (salary_type / employment_status) and **planning goal** have no save handlers at all; child birth/preschool date in settings doesn't persist. The page is also unreachable (fixed by T1.1 nav).
**Do — wire each section to its real endpoint** (all exist; use the IDs from `useWorkspace()` context — `personalDataUuid`, `workspace.id`, `selectedChildId`):
| Setting | Endpoint | Notes |
|---|---|---|
| Parent profile (salary_type, employment_status) | `PUT /api/settings/parent/{personal_data_uuid}` | Drives the salary-gated tips (§6). Add a save handler — currently local state only. |
| Planning goal (max_time / max_money / balanced) | `PUT /api/workspace/{workspace_id}` | Add a save handler. Note the value strings the backend expects (check `WorkspaceUpdate` schema) — the page currently defaults to `'balance'`, confirm it's `'balanced'`. |
| Vacation days / year | `POST /api/vacation-days` | **Fix the `'current-user'` bug** → pass the real `personalDataUuid`. |
| Child birth date + **preschool start date** | `PUT /api/settings/child/{child_id}` | Preschool date powers the studiedagar tip. |
| Break periods | `POST/PUT/DELETE /api/break-periods` | Mostly wired already — verify add/remove persist and reload. |
- Load current values into the form (don't always default to 25 vacation days / `'balance'` — read from the fetched workspace/parent/vacation data).
- Give each section its own save button + success/error message, and re-fetch after save so the UI reflects persisted state.
**Acceptance:** From Inställningar you can set salary type, employment status, planning goal, annual vacation days, and the child's birth/preschool dates; each persists (survives reload) and shows a success message. No `'current-user'` placeholder.
---
## TIER 2 — Planning & data entry
### T2.1 — Calendar: add / edit / delete planned days
**Problem:** `pages/Calendar.tsx` renders a month grid but day clicks do nothing (per the round-3 report). Planning days is the core of the app.
**Do:**
- Clicking a day opens a small day-planner (reuse/extend the existing inputs): choose **day type** (sjukpenning / lägstanivå / vacation), and for two-parent workspaces, which parent + whether it's a dubbeldag.
- Persist via `POST /api/planned-days`; allow delete via `DELETE /api/planned-days/{id}`; edit via the PUT route.
- **Validate against remaining days** before saving (ARCHITECTURE feature): don't let planned FP exceed `days_left` from the latest snapshot; surface the analytics/validation error (the backend has dubbeldagar validation — show its message).
- Refresh the calendar + the dashboard breakdown after changes.
**Acceptance:** You can add, edit, and delete planned days from the calendar; the day shows its type; over-planning is blocked with a clear message; the dashboard's "Planerade dagar" reflects changes.
---
### T2.2 — Manual data-entry fallback
**Problem:** ARCHITECTURE §2.3 mandates a manual-entry path that *always works* even if scraping is unavailable. The backend has it (`POST /api/parental-leave/manual`, `api.saveManualFetch`), but there's no UI — the only way to get data in is the scraper.
**Do:**
- Add a "Ange uppgifter manuellt" form (near the FK fetch button or in Settings) collecting the same fields the user sees on FK: `total_days`, `days_used`, reserved total/left, transferable left, dubbeldagar left, and the tier breakdown. Use the field bounds from the backend schema (`total_days` 0–480, `dubbeldagar_left` 0–60, etc.).
- Save via `api.saveManualFetch` (`source='manual'`), then refresh the overview. The provenance line from P1 will then show "Manuellt angiven …".
**Acceptance:** A user can enter their FK numbers by hand and see the overview populate, with no scraper involved.
---
## TIER 3 — Partner planning & tips (rounds it out)
### T3.1 — Add a partner (solo planning path)
**Problem:** The product premise is planning *with a partner*, but there's no UI to add a second parent. The backend supports the no-login "solo planning" path: `POST /api/workspace/{workspace_id}/parents` adds a placeholder parent profile (just a name).
**Do:**
- In Settings, add "Lägg till partner" → creates a placeholder `PersonalData` via that endpoint, then re-fetch context so the second parent appears.
- Let per-parent settings (T1.2) and calendar planning (T2.1) target either parent.
- **Optional / stretch:** collaborative planning via invitations (`POST /api/workspace/{id}/invitations`, `POST /api/invitations/redeem`) — list it but defer unless time allows.
**Acceptance:** A user can add a partner profile and plan/configure days for both parents in one workspace.
### T3.2 — Verify Tips end-to-end
**Problem:** `pages/Tips.tsx` + `TipCard` exist and the backend tips engine is implemented, but the page was unreachable.
**Do:** Now reachable via T1.1 nav — verify it loads tips for the selected workspace/child (`GET /api/tips/{workspace_id}`), renders severity badges, and that the salary-/goal-gated tips actually appear once T1.2 lets users set salary type and planning goal. Fix any contract mismatches you find.
**Acceptance:** Tips page shows real tips driven by the user's configured settings.
---
## Suggested order & notes
1. **T1.1 → T1.2** first: navigation + working settings unlock everything else and deliver the most visible improvement.
2. Then **T2.1 (calendar)** — the biggest single chunk; budget accordingly.
3. **T2.2 (manual fallback)** is small and satisfies an architectural must-have — good quick win.
4. **Tier 3** rounds out the partner story; invitations are optional.
**One backend dependency to flag to the senior:** the parent display name isn't in `GET /api/auth/context` (T1.1). Everything else uses endpoints that already exist — read each router's actual `@router` decorator and request/response schema before wiring, and don't invent paths (see the path-mismatch lesson from the last round).
**Out of scope:** real CSS/visual design, responsive/mobile, accessibility audit, real-time updates — separate passes once the functionality is complete.