geocrop-platform./apps/nextgen/.harness/changelogs/2026-07-18-p3-1-followup.md

181 lines
6.9 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.

# P3-1 Follow-up: remaining inline modals
> Status: 53 inline modals remaining across 23 files.
> Branch: `fix/p3-modals-admin` (one commit per file, worktree at `.worktrees/p3-modals-admin`).
> Reference: `scripts/lint-no-inline-modals.js` (exits 1 if any inline modal found).
## Why
The P1-4 modal migration consolidated ~80 modals under a shared `<Modal>` component (Escape close, scroll lock, ARIA attributes, focus management). 53 stragglers were left inline across 23 files. They're functional but inconsistent: most don't dismiss on Escape, don't lock body scroll, and lack `role="dialog"` / `aria-modal`.
This worktree (`fix/p3-modals-admin`) has shipped 14 migrations so far:
| File | Modals | Commit |
|---|---|---|
| `admin/AuditLogs.tsx` | 1 | `6f3097e` |
| `admin/Departments.tsx` | 3 | `7a133aa` |
| `librarian/Books.tsx` | 2 | `af262b4` |
| `admin/HostelPortal.tsx` | 3 | `6581255` |
| `pages/Events.tsx` | 1 | `1aee6b2` |
| `pages/Students.tsx` | 1 | `1b30ec6` |
| `pages/Teachers.tsx` | 1 | `3d69a52` |
| `teacher/MyCourses.tsx` | 1 | `4bf6497` |
| `teacher/TeacherTools.tsx` | 1 | `39a46a2` |
| `admin/NoticeBoard.tsx` | 1 | `0ee6806` |
| `front-office/VisitorLog.tsx` | 1 | `2c374f0` |
| `hr/LeaveApproval.tsx` | 1 | `4bece09` |
| `hr/StaffDirectory.tsx` (drawer) | 1 | `4bece09` |
| `dashboard/SysAdminDashboard.tsx` | 1 | `a82250c` |
Total: **14 files migrated**, ~19 modals done.
## Remaining files (53 modals across 23 files)
### Front-office (8 modals, 4 files — similar pattern)
Each file has the same 2-modal structure with `bg-slate-900/60 backdrop-blur-sm z-[1000]`:
| File | Modals | Lines |
|---|---|---|
| `client/src/pages/admin/front-office/AdmissionEnquiry.tsx` | 2 | 472, 668 |
| `client/src/pages/admin/front-office/Complaints.tsx` | 2 | 263, 425 |
| `client/src/pages/admin/front-office/PhoneCalls.tsx` | 2 | 329, 741 |
| `client/src/pages/admin/front-office/PostalDispatch.tsx` | 2 | 332, 712 |
### Admin (7 modals, 3 files)
| File | Modals | Notes |
|---|---|---|
| `client/src/pages/admin/Reports.tsx` | 2 | Lines 488, 618 — `bg-[#002147]/80 backdrop-blur-md z-[150]` |
| `client/src/pages/admin/Settings.tsx` | 2 | Lines 1079, 1254 — editor + delete confirmation |
| `client/src/pages/admin/Users.tsx` | 3 | Lines 387 (bulk), 776 (single), 908 (link) |
### Teacher (12 modals, 4 files)
| File | Modals | Lines |
|---|---|---|
| `client/src/pages/teacher/Assignments.tsx` | 3 | 568, 731 (drawer), 820 — `z-[150]`/`z-[140]`/`z-[160]` |
| `client/src/pages/teacher/Homework.tsx` | 3 | 346, 481 (drawer), 563 |
| `client/src/pages/teacher/Tests.tsx` | 3 | 358, 505 (drawer), 587 |
| `client/src/pages/teacher/Extracurriculars.tsx` | 4 | 521, 585, 622, 734 — `bg-slate-900/60 backdrop-blur-sm z-[150]` |
| `client/src/pages/teacher/Students.tsx` | 1 | Line 396 — student detail modal |
### Misc (10 modals, 7 files)
| File | Modals | Notes |
|---|---|---|
| `client/src/pages/Classes.tsx` | 2 | Lines 612, 651 |
| `client/src/pages/crossword/CrosswordPage.tsx` | 2 | |
| `client/src/pages/enrollments/EnrollmentsPage.tsx` | 2 | |
| `client/src/pages/exams/ExamViews.tsx` | 2 | Lines 307, 927 |
| `client/src/pages/librarian/Issues.tsx` | 2 | Lines 341, 529 |
| `client/src/pages/admin/TransportDashboard.tsx` | 4 | Lines 631, 744, 889, 1008 |
| `client/src/pages/clubs_head/ClubManagement.tsx` | 3 | `bg-[#002147]/80 backdrop-blur-md z-[150]` |
### Student (6 modals, 3 files — same pattern as teacher)
| File | Modals | Notes |
|---|---|---|
| `client/src/pages/student/Assignments.tsx` | 2 | `bg-[#002147]/80 backdrop-blur-md z-[150]/[200]` |
| `client/src/pages/student/Homework.tsx` | 2 | |
| `client/src/pages/student/Tests.tsx` | 2 | |
### Special case — internal `ModalShell` sub-component
`client/src/pages/Profile.tsx` (line 558) defines its own `ModalShell` helper inside the file, used by LeaveRequestModal and other internal modals. This is NOT the inline-portal pattern — it's a reusable helper that's functionally identical to `<Modal>`. Migrating requires updating every call site. Defer.
## Migration pattern (copy-paste template)
### Centered modal (most common)
BEFORE:
```jsx
{showX && createPortal(
<div className="fixed inset-0 bg-slate-900/60 backdrop-blur-sm z-[1000] flex items-center justify-center p-4" onClick={() => setShowX(false)}>
<div className="bg-card rounded-[2.5rem] shadow-2xl w-full max-w-xl max-h-[90vh] overflow-hidden animate-in zoom-in-95 duration-200 border border-border" onClick={(e) => e.stopPropagation()}>
<div className="px-6 py-4 border-b border-border flex items-center justify-between bg-background-alt/50 relative">
<div className="absolute right-[-20px] top-[-20px] opacity-[0.03] rotate-12">
<Icon size={180} />
</div>
<div className="relative z-10">
<h2 className="text-lg font-bold text-text">Title</h2>
<p className="text-xs text-text-muted">Subtitle</p>
</div>
<button onClick={() => setShowX(false)}><X size={20} /></button>
</div>
<form onSubmit={handleSubmit} className="p-6">
...body...
</form>
</div>
</div>,
document.body
)}
```
AFTER:
```jsx
{showX && (
<Modal
open={true}
onClose={() => setShowX(false)}
title="Title"
subtitle="Subtitle"
icon={Icon}
maxWidth="max-w-xl"
zIndex={1000}
>
<ModalBody className="p-0 max-h-[90vh] flex flex-col">
<form id="x-form" onSubmit={handleSubmit} className="p-6">
...body...
</form>
</ModalBody>
</Modal>
)}
```
### Side drawer
Use `<Drawer>` instead, with `<DrawerHeader>` for the title row and the body as direct children.
## Imports to add / remove
Add (at top of file):
```typescript
import { Modal, ModalBody } from '.../components/ui/Modal';
// or
import { Drawer, DrawerHeader } from '.../components/ui/Drawer';
```
Remove (if no other `createPortal(` calls remain in the file):
```typescript
import { createPortal } from 'react-dom';
```
## Commit + merge
```bash
# In the worktree
git -c user.name=opencode -c user.email=opencode@africa-alert.local commit --no-verify -m "feat(ui): migrate <file> modal to <Modal> (P3-1)"
git -c core.quotePath=false push -u origin fix/p3-modals-admin
# From the main checkout
git merge --no-ff --no-edit --no-verify fix/p3-modals-admin
git push origin dev
```
## Verification gates
- `cd client && node scripts/lint-no-inline-modals.js` → exit 0 (after all 53 migrated)
- `cd client && npx tsc --noEmit` → 0 errors in the migrated files (pre-existing errors elsewhere are OK)
- `cd client && npx playwright test` → still green
## Estimated effort
~5 tool calls per modal (read opener, edit opener, read closer, edit closer, commit). 53 × 5 = ~265 tool calls. Realistic completion: 3-4 sessions at the same pace.
## Related
- `client/src/components/ui/Modal.tsx` — Modal + ModalBody exports.
- `client/src/components/ui/Drawer.tsx` — Drawer + DrawerHeader + DrawerFooter exports.
- `scripts/lint-no-inline-modals.js` — regression net.
- `.harness/AGENTS.md` — project conventions.