fix(exam): reflect authoritative exam state and lock engine-graded results

- 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>
This commit is contained in:
mihretu
2026-09-07 08:12:12 +00:00
parent 29990d3142
commit 24fb51de23
36 changed files with 1888 additions and 99 deletions

View File

@@ -392,6 +392,13 @@ export interface LicenseApplication {
licenseType?: LicenseType;
/** Denormalized from `licenseType.familyKind` at submission time. */
familyKind: FamilyKind;
/**
* The examination leg as the server reads it off the sitting (registration,
* attempt, published mark) — present on queue rows, null where the
* application has no sitting. Outranks `status` for what the exam leg says:
* a published PASSED shows as passed even while `status` still lags.
*/
examState?: ExamState | null;
applicantUserId: string;
parentApplicationId?: string | null;
kind: ApplicationKind;