feat(exam): S4-11 marking flow, results table, CSV, ResultsWidget
app-ci-deploy / test-build-deploy (push) Has been cancelled
app-ci-deploy / test-build-deploy (push) Has been cancelled
- /exam-marker/:batchId/mark — ExamMarkingPage: student queue, per-part mark entry, upsert marks - /exam-marker/:batchId/results — ExamResultsPage: results table with absent rows, CSV download - ResultsWidget on ClassDetailPage: last batch summary, class average, absent count, batch creation - New types: MarkingBatch, StudentSubmission, BatchQueueResponse, BatchResultsResponse, MarkUpsertPayload - New repo methods: createBatch, listBatches, getBatchQueue, getBatchResults, getBatchCsv, upsertMark Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
ab35193be1
commit
3389fdcb5b
@@ -11,12 +11,17 @@ import { API_BASE } from '../../config/apiConfig';
|
||||
import { logger } from '../../debugConfig';
|
||||
import { supabase } from '../../supabaseClient';
|
||||
import type {
|
||||
BatchQueueResponse,
|
||||
BatchResultsResponse,
|
||||
CreateBatchPayload,
|
||||
CreateTemplatePayload,
|
||||
ExamBoundary,
|
||||
ExamQuestion,
|
||||
ExamResponseArea,
|
||||
ExamTemplate,
|
||||
ExamTemplateDetail,
|
||||
MarkingBatch,
|
||||
MarkUpsertPayload,
|
||||
Neo4jSyncResult,
|
||||
PatchQuestionPayload,
|
||||
SpecPoint,
|
||||
@@ -209,6 +214,48 @@ export const examRepository = {
|
||||
const res = await axios.post<Neo4jSyncResult>(`${EXAM_BASE}/templates/${templateId}/neo4j-sync`, {}, { headers });
|
||||
return res.data;
|
||||
},
|
||||
|
||||
async createBatch(payload: CreateBatchPayload): Promise<MarkingBatch> {
|
||||
const headers = await authHeaders();
|
||||
const res = await axios.post<MarkingBatch>(`${EXAM_BASE}/batches`, payload, { headers });
|
||||
return res.data;
|
||||
},
|
||||
|
||||
async listBatches(params: { includeArchived?: boolean; templateId?: string } = {}): Promise<MarkingBatch[]> {
|
||||
const headers = await authHeaders();
|
||||
const res = await axios.get<{ batches: MarkingBatch[] }>(`${EXAM_BASE}/batches`, {
|
||||
headers,
|
||||
params: {
|
||||
include_archived: params.includeArchived ?? false,
|
||||
template_id: params.templateId,
|
||||
},
|
||||
});
|
||||
return res.data.batches ?? [];
|
||||
},
|
||||
|
||||
async getBatchQueue(batchId: string): Promise<BatchQueueResponse> {
|
||||
const headers = await authHeaders();
|
||||
const res = await axios.get<BatchQueueResponse>(`${EXAM_BASE}/batches/${batchId}/queue`, { headers });
|
||||
return res.data;
|
||||
},
|
||||
|
||||
async getBatchResults(batchId: string): Promise<BatchResultsResponse> {
|
||||
const headers = await authHeaders();
|
||||
const res = await axios.get<BatchResultsResponse>(`${EXAM_BASE}/batches/${batchId}/results`, { headers });
|
||||
return res.data;
|
||||
},
|
||||
|
||||
async getBatchCsv(batchId: string): Promise<string> {
|
||||
const headers = await authHeaders();
|
||||
const res = await axios.get<string>(`${EXAM_BASE}/batches/${batchId}/csv`, { headers, responseType: 'text' });
|
||||
return res.data;
|
||||
},
|
||||
|
||||
async upsertMark(markId: string, payload: MarkUpsertPayload): Promise<unknown> {
|
||||
const headers = await authHeaders();
|
||||
const res = await axios.put(`${EXAM_BASE}/marks/${markId}`, payload, { headers });
|
||||
return res.data;
|
||||
},
|
||||
};
|
||||
|
||||
export default examRepository;
|
||||
|
||||
Reference in New Issue
Block a user