mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-08-28 20:40:56 +00:00
Frontend half of the backend change: ExamPage no longer disables the form Select or force-resets it to CHOICE when administrationMethod is ONLINE (backend's assertOnlineIsChoiceOnly is gone, matching gate removed here). Also wires up GET .../grading-sheet as useGetGradingSheetQuery — RecordResultModal wiring (show candidate answers, prefill auto-computed CHOICE scores) is next.
134 lines
4.3 KiB
TypeScript
134 lines
4.3 KiB
TypeScript
import { baseApi } from '@ema-platform/api';
|
|
import type {
|
|
Exam,
|
|
ListResponse,
|
|
CreateExamPayload,
|
|
UpdateExamPayload,
|
|
AssignQuestionsPayload,
|
|
RandomQuestionsPayload,
|
|
ExamRegistration,
|
|
RecordAttendancePayload,
|
|
ExamIncident,
|
|
CreateIncidentPayload,
|
|
ResolveIncidentPayload,
|
|
RegradeOutcome,
|
|
GradingSheet,
|
|
} from '../types/exam';
|
|
|
|
const examApi = baseApi.injectEndpoints({
|
|
endpoints: (builder) => ({
|
|
getExams: builder.query<ListResponse<Exam>, void>({
|
|
query: () => '/exams?q=i=questions',
|
|
providesTags: ['Api'],
|
|
}),
|
|
getExam: builder.query<Exam, string>({
|
|
// Nested relation so CHOICE questions carry their options here too —
|
|
// needed to print real answer choices instead of blank A/B/C/D lines.
|
|
query: (id) => `/exams/${id}?i=questions,questions.options`,
|
|
providesTags: ['Api'],
|
|
}),
|
|
createExam: builder.mutation<Exam, CreateExamPayload>({
|
|
query: (body) => ({ url: '/exams', method: 'POST', body }),
|
|
invalidatesTags: ['Api'],
|
|
}),
|
|
updateExam: builder.mutation<Exam, UpdateExamPayload>({
|
|
query: ({ id, ...body }) => ({
|
|
url: `/exams/${id}`,
|
|
method: 'PUT',
|
|
body,
|
|
}),
|
|
invalidatesTags: ['Api'],
|
|
}),
|
|
deleteExam: builder.mutation<void, string>({
|
|
query: (id) => ({ url: `/exams/${id}`, method: 'DELETE' }),
|
|
invalidatesTags: ['Api'],
|
|
}),
|
|
assignQuestions: builder.mutation<Exam, AssignQuestionsPayload>({
|
|
query: ({ examId, questionIds, remark }) => ({
|
|
url: `/exams/${examId}/questions`,
|
|
method: 'POST',
|
|
body: { examId, questionIds, remark },
|
|
}),
|
|
invalidatesTags: ['Api'],
|
|
}),
|
|
/** Server-side draw from the approved bank (US-EXAM-005). */
|
|
selectRandomQuestions: builder.mutation<Exam, RandomQuestionsPayload>({
|
|
query: ({ examId, count }) => ({
|
|
url: `/exams/${examId}/questions/random`,
|
|
method: 'POST',
|
|
body: { count },
|
|
}),
|
|
invalidatesTags: ['Api'],
|
|
}),
|
|
// --- Candidates and attendance (US-EXAM-007/009) ---------------------
|
|
getExamRegistrations: builder.query<ExamRegistration[], string>({
|
|
query: (examId) => `/exams/${examId}/registrations`,
|
|
providesTags: ['Api'],
|
|
}),
|
|
recordAttendance: builder.mutation<ExamRegistration, RecordAttendancePayload>({
|
|
query: ({ registrationId, ...body }) => ({
|
|
url: `/exams/registrations/${registrationId}/attendance`,
|
|
method: 'POST',
|
|
body,
|
|
}),
|
|
invalidatesTags: ['Api'],
|
|
}),
|
|
// --- Session incidents (US-EXAM-010) ---------------------------------
|
|
getExamIncidents: builder.query<ExamIncident[], string>({
|
|
query: (examId) => `/exams/${examId}/incidents`,
|
|
providesTags: ['Api'],
|
|
}),
|
|
recordIncident: builder.mutation<ExamIncident, CreateIncidentPayload>({
|
|
query: ({ examId, ...body }) => ({
|
|
url: `/exams/${examId}/incidents`,
|
|
method: 'POST',
|
|
body,
|
|
}),
|
|
invalidatesTags: ['Api'],
|
|
}),
|
|
resolveIncident: builder.mutation<ExamIncident, ResolveIncidentPayload>({
|
|
query: ({ incidentId, ...body }) => ({
|
|
url: `/exams/incidents/${incidentId}/resolve`,
|
|
method: 'POST',
|
|
body,
|
|
}),
|
|
invalidatesTags: ['Api'],
|
|
}),
|
|
/** Staff-triggered re-run of auto-grading for one finalized attempt. */
|
|
regradeAttempt: builder.mutation<RegradeOutcome, string>({
|
|
query: (attemptId) => ({
|
|
url: `/exam-attempts/${attemptId}/regrade`,
|
|
method: 'POST',
|
|
}),
|
|
invalidatesTags: ['Api'],
|
|
}),
|
|
/** The candidate's answers plus auto-computable CHOICE scores, for RecordResultModal. */
|
|
getGradingSheet: builder.query<
|
|
GradingSheet,
|
|
{ examId: string; profileId: string }
|
|
>({
|
|
query: ({ examId, profileId }) =>
|
|
`/exam-attempts/exam/${examId}/candidate/${profileId}/grading-sheet`,
|
|
providesTags: ['Api'],
|
|
}),
|
|
}),
|
|
overrideExisting: false,
|
|
});
|
|
|
|
export const {
|
|
useGetExamsQuery,
|
|
useGetExamQuery,
|
|
useCreateExamMutation,
|
|
useUpdateExamMutation,
|
|
useDeleteExamMutation,
|
|
useAssignQuestionsMutation,
|
|
useSelectRandomQuestionsMutation,
|
|
useGetExamRegistrationsQuery,
|
|
useRecordAttendanceMutation,
|
|
useGetExamIncidentsQuery,
|
|
useRecordIncidentMutation,
|
|
useResolveIncidentMutation,
|
|
useRegradeAttemptMutation,
|
|
useGetGradingSheetQuery,
|
|
} = examApi;
|