# 2026-07-18 — P1-4 modal migration: admin/HRManagement.tsx complete (9 of 9)

Branch: `feat/p1-4-modals-hr`
Worktree: `.worktrees/feat-p1-4-modals-hr`

## Why

P1-4 from the readiness audit asks for every inline modal to use the
shared `<Modal>` component. Continues the previous partial (1/9) with
the remaining 8 modals in this 2000-line file.

## Changes

### `client/src/pages/admin/HRManagement.tsx`

Migrated 8 more modals to `<Modal>` + `<ModalBody>`, completing the
file at 9/9:

- **Staff Profile** — multi-section profile view + edit form (the
  inline header had an avatar circle that's now superseded by the
  Modal title).
- **Staff Documents** — file list + Exit Directory button.
- **Leave Audit Intel** — read-only leave request details with
  approve / reject actions.
- **New Payroll Run** — month + year + description form.
- **Create Job Vacancy** — title + department + dates + description
  form.
- **Vacancy Details / Edit Career Opening** — same form as Create but
  populated for editing.
- **Review Candidate** — applicant status update form.
- **Register Candidate** — new applicant onboarding form (the
  longest — multi-section: identity, contact, references, docs).

Each modal uses `<ModalBody>` directly (no `className` override) since
the original inline body already had `p-8` / `p-10` etc. — Modal's
own padding isn't visible underneath. The `form id=…-form` is set so
the footer-style action buttons (still inline at the body bottom)
work via `type="submit" form="…"` on the outer submit button. The
inline `<button className="…">X</button>` close buttons and
watermark icon `<div className="absolute right-…">` are stripped;
`<Modal>` injects its own header + close.

## Verification

- `node scripts/lint-no-inline-modals.js` → `HRManagement.tsx`
  count: 8 → 0.
- `npx tsc --noEmit` clean for `HRManagement.tsx`.
