2.0 KiB
2026-07-17 — P1-4 modal migration: Fees.tsx (Track A continuation)
Branch: feat/p1-4-modals-fees
Worktree: .worktrees/feat-p1-4-modals-fees
Why
P1-4 from the readiness audit asks for every inline modal to use the
shared <Modal> component Track A introduced. BankingAccounts.tsx and
8 finance/* files already migrated. This PR continues the sweep with
the top-level Fees.tsx (4 modals).
Changes
client/src/pages/Fees.tsx
Migrated 4 modals to <Modal> + <ModalBody>:
- Create Fee Group — 2-field form (name, amount)
- Assign Fees — 2 dropdowns (student, fee group)
- Record Payment — dropdown + amount input
- Edit Fee Group — name / description / amount / due date
Notes
The page's open <button className="text-2xl font-light">×</button>
header close button is removed — <Modal> injects its own close button
inside <ModalHeader> (already part of <Modal> when no icon
prop is supplied). Same back-button-on-Escape + click-outside-to-close
behaviour comes for free.
Each form uses an explicit id="…-form" so the footer-submit button
can use form="…" to post outside the form element. This preserves
the exact button placement at the modal footer (matching the
Footer slot in Track A's reference).
The createPortal-based row context menu (lines ~517 in the source)
is NOT a modal — it's a row-popover — and was left untouched. Lint
script counts it as 0 because it uses neither fixed inset-0 nor
backdrop-blur-sm.
Out of scope
The remaining 14 inline modals split across:
HRManagement.tsx(7)Inventory.tsx(4)Library.tsx(3)parent/AcademicProgress.tsx(4)- 6 in
finance/*(StudentGroups × 3, StudentGroupDetail, and side-drawers in Invoices + Payslips needing a sibling<Drawer>component)
…land in subsequent PRs.
Verification
node scripts/lint-no-inline-modals.js→Fees.tsxcount dropped 4 → 0.npx tsc --noEmitclean forFees.tsx(no new TS errors).