# Junior Developer — Frontend Polish TODO **Owner:** Junior developer **Status:** Ready to implement **Goal:** Clean up the rough edges left after the MVP happy path — surface the data we already fetch, fix placeholder math, kill the duplicate heading, drop the `any` casts, and backfill tests for the new code. **Do this first**, then move on to `frontend_mvp_complete.md`. > Keep `npx tsc --noEmit`, `npm run lint`, and `npm test` green after every task. Don't redesign anything — this is tidy-up, not new features. CSS is still out of scope (MVP can look plain). --- ## P1 — Show the richer FK breakdown on the overview **Problem:** The scraper fetches and persists a lot more than we display. The overview only shows three combined analytics numbers (Days Used / Days Left / Expiring at Age 4). The persisted `ParentalLeaveFetch` also has reserved vs. transferable days, dubbeldagar left, and the sjukpenning/lägstanivå tier split — all currently invisible. **Do:** - In `Dashboard.tsx`, use the existing `useParentalLeave(personalDataUuid, selectedChildId)` hook (both IDs come from `useWorkspace()` context) to load the latest snapshot for the selected child. - Render a section showing: `reserved_days_left` / `reserved_days_total`, `transferable_days_left`, `dubbeldagar_left`, and the tier breakdown (`sjukpenning_left`, `lagsta_niva_left`). Reuse `DaysBreakdown` or a simple list — no new styling needed. - Show data provenance + freshness per ARCHITECTURE §2.3: "Hämtad från Försäkringskassan {fetched_at}" vs "Manuellt angiven {fetched_at}" based on `source`. - Handle the empty case gracefully: if there's no snapshot yet (new child, never fetched), show "Ingen data hämtad ännu — tryck på Hämta från Försäkringskassan." rather than blanks. - After a successful FK fetch, refresh this too (the modal's `onDone` currently calls `refreshAnalytics()` — also call the parental-leave hook's `refresh()`). **Acceptance:** After a fetch, the overview shows reserved/transferable/dubbeldagar/tier numbers and a "fetched on" line; before any fetch it shows a clear empty message. --- ## P2 — Remove the duplicate "Overview" heading **Problem:** The dashboard renders `

Overview

` and then `OverviewMetrics` renders its *own* `

Overview

` (visible as two stacked "Overview" headings in the capture). **Do:** Remove the redundant wrapper `

` in `Dashboard.tsx` (keep the one inside `OverviewMetrics`, or pass a meaningful title). While you're there, make the section headings Swedish to match the rest of the app ("Översikt", "Planerade dagar", "Återstående till 4 års ålder") — small consistency win, the header already says "Översikt". **Acceptance:** Exactly one "Översikt" heading for that section; headings are consistently Swedish. --- ## P3 — Fix the ProgressChart math (currently placeholder) **Problem:** `Dashboard.tsx` feeds `ProgressChart` placeholder values: `currentWeeks={Math.floor(totalPlanned / 5)}` against a hardcoded `targetWeeks={50}`. That's not a real progress metric. **Do:** Drive it from real data. The intent (per ARCHITECTURE) is progress toward the age-4 deadline. Use the analytics projection — e.g. days used (or planned) vs. total entitlement (`combinedDaysUsed` / `combinedDaysUsed + combinedDaysLeft`), or days elapsed vs. days until the child turns 4. Pick the interpretation that matches what `OverviewMetrics` already shows and label it honestly. Remove the hardcoded `50`. **Acceptance:** The progress bar reflects a real ratio from analytics data; no hardcoded target weeks. --- ## P4 — Drop the `any` casts **Problem:** `Dashboard.tsx` (and `Settings.tsx`) use `(d: any)` / `(period: any)` casts and an ESLint exception was added for pages. These hide type errors. **Do:** Replace the casts with the real types from `@/types` (`PlannedLeaveDay`, `BreakPeriod`, etc.). Fix the field-name access to match the typed shape. Once the casts are gone, remove the temporary `@typescript-eslint/no-explicit-any` exception for `pages/` from `eslint.config.js` (keep the test-file exception if still needed). **Acceptance:** No `any` in `pages/`; the pages-level ESLint exception is removed; `tsc`/lint green. --- ## P5 — Backfill tests for the new code **Problem:** The happy-path round added real code with no new tests — the count stayed at 167 (`useScraperFetch`, `QRCodeModal`, the Dashboard empty-state add-child form, and the FK-fetch button are untested). **Do:** Add focused tests following the existing patterns: - `useScraperFetch` — start → poll transitions → done/error/cancel; timers mocked. - `QRCodeModal` — renders QR when `awaiting_scan`, spinner on `authenticating`/`fetching`, result on `done`, message on `error`; close disabled while running. - `Dashboard` — empty state (no children) shows the add-child form; populated state shows metrics + the FK button (disabled when no child selected). **Acceptance:** New tests cover the above; full suite green and the test count goes up. --- ### Definition of done Overview shows the full FK breakdown with a freshness line; one clean Swedish heading; a real progress metric; zero `any` in pages; new tests for the scraper hook/modal/dashboard. `tsc` + lint + tests all green.