# Track B — Fees & Hardcoded Copy **Owner:** Person B **Branch:** `fix/stubs-fees-and-copy` (worktree at `.worktrees/stubs-fees-and-copy/`) **Files in scope:** `client/src/pages/Fees.tsx`, `client/src/pages/teacher/MyCourses.tsx`, `client/src/pages/dashboard/AdminDashboard.tsx` (limited slices per task). **No backend changes expected.** ## Conventions (from AGENTS.md) - Work in a worktree branched from `dev`. Do not edit the main checkout. - Use the shared axios instance at `client/src/store/api.ts`. - Drop unused lucide-react imports when removing a button. - PWA service worker is only built by `npm run build`. - Do not commit or push without an explicit "go" from the reviewer. ## Tasks ### B1. Fees — Fee-group "More actions" button - **File:** `client/src/pages/Fees.tsx:124-127` - **Current:** The `` icon on each fee group has `onClick={() => { console.warn('MoreVertical on fee group list — not yet implemented'); }}`. The TODO comment in source confirms it. - **Desired:** A real dropdown menu with Edit, Archive, and Duplicate (matches what `Classes.tsx` already offers on class subjects). Edit opens a modal pre-filled with the row's `name`, `description`, `amount`, `due_date`. Archive calls `DELETE /fees/groups/:id` (or `PATCH` with `is_deleted=1` — match what backend exposes) and reloads. - **Acceptance:** Clicking the icon opens a menu. Edit → modal saves. Archive → row disappears after reload. No `console.warn` from this code path. ### B2. Fees — Fee ledger status filter - **File:** `client/src/pages/Fees.tsx:179-187` - **Current:** Filter button does `window.prompt('Filter by status …')`. The free-text answer is logged but never applied. `loadData()` re-fetches the full set regardless. - **Desired:** Replace prompt with a ``. - **Desired:** Replace the mock with `setClasses([])` (or whatever the canonical empty-state in the codebase looks like — check `Events.tsx:57`, `Students.tsx:74`, `Attendance.tsx:90` for the pattern). The Create-Course modal's `