mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-09-07 20:05:42 +00:00
Merge branch 'createNewLicenseType' of https://github.com/Tria-plc/emaui into createNewLicenseType
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { baseApi } from '../../base-api';
|
||||
import type {
|
||||
ExamStateView,
|
||||
AppNotification,
|
||||
ApplicationDetail,
|
||||
ApplicationKind,
|
||||
@@ -27,7 +28,6 @@ import type {
|
||||
CompletionEffect,
|
||||
DocumentDecision,
|
||||
DocumentReview,
|
||||
EligibleExam,
|
||||
ExportResult,
|
||||
LicenseTemplate,
|
||||
Paginated,
|
||||
@@ -867,44 +867,22 @@ export const licensingApi = baseApi
|
||||
}),
|
||||
|
||||
/**
|
||||
* Exam sittings valid for this application's rank — what the
|
||||
* schedule-exam picker offers, instead of every exam in the system.
|
||||
* The examination leg behind one application, as the server reads it.
|
||||
*
|
||||
* The COC detail page used to infer this from the application status
|
||||
* alone, which is how it kept offering "Schedule exam" for a paper the
|
||||
* candidate had already sat and passed.
|
||||
*/
|
||||
getEligibleExams: builder.query<EligibleExam[], string>({
|
||||
query: (id) => ({ url: `/license-application-review/${id}/eligible-exams` }),
|
||||
getExamStateForApplication: builder.query<ExamStateView, string>({
|
||||
query: (id) => ({ url: `/exams/applications/${id}/state` }),
|
||||
providesTags: (_r, _e, id) => [itemTag('LicenseApplication', id)],
|
||||
}),
|
||||
|
||||
/** Places a candidate who has paid the examination fee into a sitting. */
|
||||
scheduleExam: builder.mutation<
|
||||
LicenseApplication,
|
||||
{ id: string; examId: string; admissionNumber?: string; examDate?: string }
|
||||
>({
|
||||
query: ({ id, examDate: _examDate, ...body }) => ({
|
||||
// Matches the controller's `:id/exam-scheduled` route — `examDate`
|
||||
// is UI-only context for the confirmation toast, not part of
|
||||
// `MarkExamScheduledDto`, so it never goes on the wire.
|
||||
url: `/license-application-review/${id}/exam-scheduled`,
|
||||
method: 'POST',
|
||||
body,
|
||||
}),
|
||||
invalidatesTags: (_r, error, { id }) =>
|
||||
error ? [] : [itemTag('LicenseApplication', id), listTag('ApplicationQueue')],
|
||||
}),
|
||||
|
||||
/** Records a published examination result (pass or fail). */
|
||||
recordExamOutcome: builder.mutation<
|
||||
LicenseApplication,
|
||||
{ id: string; passed: boolean; score?: number }
|
||||
>({
|
||||
query: ({ id, ...body }) => ({
|
||||
url: `/license-application-review/${id}/exam-outcome`,
|
||||
method: 'POST',
|
||||
body,
|
||||
}),
|
||||
invalidatesTags: (_r, error, { id }) =>
|
||||
error ? [] : [itemTag('LicenseApplication', id), listTag('ApplicationQueue')],
|
||||
}),
|
||||
// No `getEligibleExams`, `scheduleExam` or `recordExamOutcome`: the
|
||||
// endpoints behind them are gone. Sittings are published as master
|
||||
// schedules and candidates register for one themselves, and an outcome
|
||||
// is what the exam engine computed and a supervisor approved — neither
|
||||
// is the COC queue's to write.
|
||||
|
||||
/**
|
||||
* A failed candidate asks for another sitting. Re-opens the examination
|
||||
@@ -1212,8 +1190,17 @@ export const licensingApi = baseApi
|
||||
url: `/license-application-review/${id}/issue-certificate`,
|
||||
method: 'POST',
|
||||
}),
|
||||
// The certificate this writes is what `License` lists read, so the
|
||||
// issued register and the holder's own licences refresh with it —
|
||||
// without them an officer issues a certificate that nobody's list shows.
|
||||
invalidatesTags: (_r, error, id) =>
|
||||
error ? [] : [itemTag('LicenseApplication', id), listTag('ApplicationQueue')],
|
||||
error
|
||||
? []
|
||||
: [
|
||||
itemTag('LicenseApplication', id),
|
||||
listTag('ApplicationQueue'),
|
||||
listTag('License'),
|
||||
],
|
||||
}),
|
||||
|
||||
// ------------------------------------------------------------- pickup
|
||||
@@ -1434,6 +1421,7 @@ export const {
|
||||
useUpdateLicenseValidityMutation,
|
||||
useGetLicenseTypeRequirementsQuery,
|
||||
useCreateApplicationMutation,
|
||||
useGetExamStateForApplicationQuery,
|
||||
useDiscardApplicationMutation,
|
||||
useGetMyApplicationsQuery,
|
||||
useGetApplicationQuery,
|
||||
@@ -1493,9 +1481,6 @@ export const {
|
||||
useApproveDocumentsMutation,
|
||||
useFinalApproveMutation,
|
||||
useRejectApplicationMutation,
|
||||
useGetEligibleExamsQuery,
|
||||
useScheduleExamMutation,
|
||||
useRecordExamOutcomeMutation,
|
||||
useRetakeExamMutation,
|
||||
useConfirmPaymentMutation,
|
||||
useScheduleIssuanceMutation,
|
||||
|
||||
@@ -86,7 +86,9 @@ export const STATUS_LABELS: Record<LicenseStatus, string> = {
|
||||
ELIGIBILITY_PAYMENT_PENDING: 'Eligibility Fee Due',
|
||||
ELIGIBILITY_PAID: 'Eligibility Under Review',
|
||||
EXAM_PAYMENT_PENDING: 'Exam Fee Due',
|
||||
EXAM_PAID: 'Awaiting Exam Date',
|
||||
// Nobody assigns a date any more — the fee clearing is what makes the
|
||||
// candidate eligible to register for a published sitting themselves.
|
||||
EXAM_PAID: 'Eligible to Register',
|
||||
EXAM_SCHEDULED: 'Exam Scheduled',
|
||||
EXAM_PASSED: 'Exam Passed',
|
||||
EXAM_FAILED: 'Exam Not Passed',
|
||||
|
||||
@@ -940,12 +940,39 @@ export interface PersonalDocumentFilter {
|
||||
locale?: 'en' | 'am';
|
||||
}
|
||||
|
||||
/** One sitting offered to a claimed examined-certificate application, scoped to its rank. */
|
||||
export interface EligibleExam {
|
||||
id: string;
|
||||
title: { en: string; am: string };
|
||||
date: string;
|
||||
venue: string;
|
||||
status: string;
|
||||
certification?: { id: string; name: { en: string; am: string }; rankKey: string | null };
|
||||
// No `EligibleExam`: it typed the schedule-exam picker's options, and
|
||||
// picking a sitting for a named applicant is not something the back office
|
||||
// does any more — candidates register for a published sitting themselves.
|
||||
|
||||
/**
|
||||
* Where a certificate application stands in the examination leg, derived
|
||||
* server-side from the registration, the attempt and the published mark
|
||||
* (ExamStateService). The application status alone cannot answer this — which
|
||||
* is why the back office could show "awaiting exam" over a published pass.
|
||||
*/
|
||||
export type ExamState =
|
||||
| 'NOT_REGISTERED'
|
||||
| 'REGISTERED'
|
||||
| 'ATTENDANCE_CONFIRMED'
|
||||
| 'NOT_SITTING'
|
||||
| 'IN_PROGRESS'
|
||||
| 'UNDER_EVALUATION'
|
||||
| 'PASSED'
|
||||
| 'FAILED';
|
||||
|
||||
export interface ExamStateView {
|
||||
state: ExamState;
|
||||
registrationId: string | null;
|
||||
admissionNumber: string | null;
|
||||
examId: string | null;
|
||||
examTitle: { en?: string; am?: string } | null;
|
||||
examDate: string | null;
|
||||
attendanceStatus: string | null;
|
||||
attemptStatus: 'IN_PROGRESS' | 'SUBMITTED' | 'EXPIRED' | null;
|
||||
/** Only once the mark is published — before that it is not the candidate's. */
|
||||
score: number | null;
|
||||
outcome: 'PASSED' | 'FAILED' | null;
|
||||
publishedAt: string | null;
|
||||
/** Whether the exam engine produced the mark, or a person did. */
|
||||
autoGraded: boolean | null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user