- Implemented `html-import.ts` to parse Handlebars/HTML certificates into canvas blocks.
- Introduced `htmlToPlacements` function to convert parsed HTML into structured placements.
- Added inline style parsing and unit conversion for various CSS lengths.
- Created test suite in `html-import.spec.ts` to validate the import logic and edge cases.
- Ensured compatibility with existing template field placements and background image handling.
- COC queue status cell shows the server-derived exam state (registered,
present, sat, passed, failed) instead of the lagging application status.
- Portal examStageFor prefers the server's examState so portal and back
office never disagree; NOT_SITTING stage added.
- Exam roster shows each candidate's result and lock; Regrade hidden once
a result exists.
- Record Result modal: only unmarked candidates, empty score boxes (no
silent zeros), reason required, backend refusals translated.
- Result page: auto-graded marks read-only, per-applicant publish.
- Exam page: session window fields, Add Question menu (bank / Excel /
scratch), wait metrics panel; PUBLISHED exam status removed.
- Portal: exam window shown, early launch and eligibility refusals explained.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The label was reverted to "Exam Paid" but the name survived as the internal
stage key, so the concept was still in the codebase to be reintroduced by
accident. The stage is named after the status it derives from now.
The COC detail page read the application status alone, so a candidate who had
registered, been marked present, sat the paper and had a PASSED mark published
still appeared to be awaiting an exam — and the officer was offered "Schedule
exam" and "Record exam result" for work already done.
ExamStatePanel reads GET /exams/applications/:id/state, which the server
derives from the registration, the attempt and the published mark. Session,
date and admission number while the exam is ahead; score, outcome and whether
the exam engine or an examiner produced the mark once it is settled. Polled,
because attendance is recorded and papers are marked while the officer has the
page open. Same derivation the applicant's portal reads, so the two cannot
disagree.
The eligible-exams query, the scheduling mutation and the outcome mutation are
gone from the RTK layer along with the endpoints behind them.