4.6 KiB
4.6 KiB
Changelog — 2026-07-04 (Phase 1 frontend)
feat(frontend): HR & Finance Phase 1 surfaces — frontend
Branch: feature/hr-finance-phase-1-frontend (off dev).
Depends on: feature/hr-finance-phase-1 backend endpoints (B1–B8).
What ships
Six user-facing pages consuming the Phase 1 backend, plus merged stores preserving Phase 0 state shape so HRManagement.tsx and FinanceManagement consumers keep working.
| Path | Roles | Backend endpoint(s) consumed |
|---|---|---|
/dashboard/hr |
school_admin, systems_admin, principal, hr, bursar, accountant | GET /api/hr/dashboard/summary |
/dashboard/finance |
school_admin, systems_admin, principal, bursar, accountant | GET /api/finance/dashboard/summary |
/finance/expenses |
school_admin, systems_admin, principal, bursar, accountant | GET /api/finance/expenses?status=&category=&date_from=&date_to= |
/finance/expenses/new |
as above | POST /api/finance/expenses |
/finance/expenses/:id/edit |
as above | PATCH /api/finance/expenses/:id (see deviation #1) |
/hr/payslips/:id |
school_admin, systems_admin, principal, hr, bursar, accountant | GET /api/hr/payslips/:id |
Stores
client/src/store/hr.ts— extended to also exposefetchDashboardSummary,fetchPayslip(id), andresetPayslip. NewcurrentPayslipanddashboardSummarystate slots. Legacy Phase 0 records / leaveRequests / payrollRuns / payslips / vacancies / applicants / metadata / staff_records management endpoints + their methods are preserved verbatim.client/src/store/finance.ts— extended withfetchDashboardSummary,fetchCategories,fetchExpenses,fetchExpense(see deviation #1),createExpense,updateExpense,deleteExpense. Phase 0 payroll proxy actions kept intact for the existing Finance payroll UX.
Routing / Nav
- New routes wired into App.tsx's role-aware
getRoutes()switch arms forschool_admin,systems_admin,principal,hr,bursar. - Nav.tsx
NAV_CONFIGblocks for those five roles gain dashboard and expenses entries usinglucide-reacticons (LayoutDashboard,Receipt,Plus). - Role gating is in App.tsx via
<ProtectedRoute>— no in-component role checks.
Deviations from the dispatch
PATCHinstead ofPUTfor expense updates. The Phase 1 backend exposesPATCH /api/finance/expenses/:id, notPUT. Store and form both useapi.patch(...).GET /api/finance/expenses/:iddoes not exist on the backend. The edit page prefills by fetching the list endpoint withlimit=500and matching by id. Caches the row for subsequent visits. Seeclient/src/store/finance.tsfetchExpensefor the rationale.FinanceDashboarduses/api/finance/dashboard/summarydirectly. The dispatch says the backend doesn't expose this endpoint yet and suggests falling back to/api/dashboard/stats; however the Phase 1 branch already shipped that endpoint. We consume it directly. A monthly time-series endpoint remains a TODO for Phase 2 — the current chart synthesises a 2-point series from MTD totals.PayslipDetailuses/api/hr/payslips/:iddirectly. Same as above; the Phase 1 branch already exposed it.
Files added (8)
client/src/store/hr.ts(modified, +139 lines)client/src/store/finance.ts(modified, +282 lines)client/src/App.tsx(modified, +42 lines)client/src/components/Nav.tsx(modified, +13 lines)client/src/pages/dashboard/HRDashboard.tsx(new)client/src/pages/dashboard/FinanceDashboard.tsx(new)client/src/pages/finance/Expenses.tsx(new)client/src/pages/finance/ExpenseNew.tsx(new)client/src/pages/finance/ExpenseEdit.tsx(new)client/src/pages/hr/PayslipView.tsx(new)
Acceptance check
- ✅
npm run buildsucceeds —✓ built in 13.48s, no TS errors. - ✅ Phase 1 backend (
:3001/api/hr/dashboard/summary) returns the four-tile aggregate for admin token. - ✅
/api/finance/dashboard/summaryreturns collected_mtd / outstanding_fees / payroll_last_run / expenses_mtd / pending_expenses. - ✅
/api/finance/expensesGET returns{ expenses, pagination }. - ✅ POST → PATCH → DELETE round-trip on
/api/finance/expensesworks (smoke test created expense #7, patched to 99.99, deleted). - ✅ RBAC denial — student@school.com token gets
403 HR, Finance, Principal or Admin access requiredon/api/hr/dashboard/summary, and403 Finance, Bursar, Accountant, HR, Principal or Admin access requiredon/api/finance/expenses. - ✅ Print stylesheet wired into
PayslipView.tsx(@media printblock scopes the visible content to#paysliponly).