mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-08-28 02:00:57 +00:00
Backend now supports MCQ options + a separate answer-key table (PUT /questions/:id/options). Frontend side of that, authoring only — no candidate exam-taking UI. - Question type gains options?: QuestionOption[] (no correctness field — the API never returns one, matching the backend's split-table design) - New question-api hooks: getQuestionWithOptions, setQuestionOptions - New QuestionOptionsEditor component (separate file, not inlined into QuestionPage) — add/remove/reorder options, mark correct, bilingual text - Wired into the question edit form, shown only for an existing CHOICE question (options attach to an id, matching the backend's replace endpoint) - en/am i18n strings for the new editor Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
81 lines
2.5 KiB
TypeScript
81 lines
2.5 KiB
TypeScript
import { baseApi } from '@ema-platform/api';
|
|
import type {
|
|
Question,
|
|
QuestionOption,
|
|
ListResponse,
|
|
CreateQuestionPayload,
|
|
UpdateQuestionPayload,
|
|
ReviewQuestionPayload,
|
|
SetQuestionOptionsPayload,
|
|
} from '../types/question';
|
|
|
|
const questionApi = baseApi.injectEndpoints({
|
|
endpoints: (builder) => ({
|
|
getQuestions: builder.query<ListResponse<Question>, void>({
|
|
query: () => '/questions',
|
|
providesTags: ['Api'],
|
|
}),
|
|
getQuestion: builder.query<Question, string>({
|
|
query: (id) => `/questions/${id}`,
|
|
providesTags: ['Api'],
|
|
}),
|
|
/** Same question, with `options` populated — the MCQ authoring editor. */
|
|
getQuestionWithOptions: builder.query<Question, string>({
|
|
query: (id) => `/questions/${id}?i=options`,
|
|
providesTags: ['Api'],
|
|
}),
|
|
createQuestion: builder.mutation<Question, CreateQuestionPayload>({
|
|
query: (body) => ({ url: '/questions', method: 'POST', body }),
|
|
invalidatesTags: ['Api'],
|
|
}),
|
|
updateQuestion: builder.mutation<Question, UpdateQuestionPayload>({
|
|
query: ({ id, ...body }) => ({
|
|
url: `/questions/${id}`,
|
|
method: 'PUT',
|
|
body,
|
|
}),
|
|
invalidatesTags: ['Api'],
|
|
}),
|
|
deleteQuestion: builder.mutation<void, string>({
|
|
query: (id) => ({ url: `/questions/${id}`, method: 'DELETE' }),
|
|
invalidatesTags: ['Api'],
|
|
}),
|
|
/** Hand a drafted or corrected item to the supervisor (US-EXAM-003). */
|
|
submitQuestion: builder.mutation<Question, string>({
|
|
query: (id) => ({ url: `/questions/${id}/submit`, method: 'POST' }),
|
|
invalidatesTags: ['Api'],
|
|
}),
|
|
/** Approve, reject or retire a bank item (US-EXAM-003). */
|
|
reviewQuestion: builder.mutation<Question, ReviewQuestionPayload>({
|
|
query: ({ id, ...body }) => ({
|
|
url: `/questions/${id}/review`,
|
|
method: 'POST',
|
|
body,
|
|
}),
|
|
invalidatesTags: ['Api'],
|
|
}),
|
|
/** Full replace of a CHOICE question's options + correct-answer set (Phase 2). */
|
|
setQuestionOptions: builder.mutation<QuestionOption[], SetQuestionOptionsPayload>({
|
|
query: ({ id, ...body }) => ({
|
|
url: `/questions/${id}/options`,
|
|
method: 'PUT',
|
|
body,
|
|
}),
|
|
invalidatesTags: ['Api'],
|
|
}),
|
|
}),
|
|
overrideExisting: false,
|
|
});
|
|
|
|
export const {
|
|
useGetQuestionsQuery,
|
|
useGetQuestionQuery,
|
|
useGetQuestionWithOptionsQuery,
|
|
useCreateQuestionMutation,
|
|
useUpdateQuestionMutation,
|
|
useDeleteQuestionMutation,
|
|
useSubmitQuestionMutation,
|
|
useReviewQuestionMutation,
|
|
useSetQuestionOptionsMutation,
|
|
} = questionApi;
|