184 lines
5.9 KiB
TypeScript
184 lines
5.9 KiB
TypeScript
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
|
|
import { getConfigValue } from '@brojs/cli'
|
|
|
|
import { keycloak } from '../kc'
|
|
import type {
|
|
ChallengeTask,
|
|
ChallengeChain,
|
|
ChallengeSubmission,
|
|
SystemStats,
|
|
SystemStatsV2,
|
|
UserStats,
|
|
CreateTaskRequest,
|
|
UpdateTaskRequest,
|
|
CreateChainRequest,
|
|
UpdateChainRequest,
|
|
SubmitRequest,
|
|
TestSubmissionResult,
|
|
APIResponse,
|
|
} from '../../types/challenge'
|
|
|
|
export const api = createApi({
|
|
reducerPath: 'api',
|
|
baseQuery: fetchBaseQuery({
|
|
baseUrl: getConfigValue('challenge-admin.api'),
|
|
fetchFn: async (
|
|
input: RequestInfo | URL,
|
|
init?: RequestInit | undefined,
|
|
) => {
|
|
const response = await fetch(input, init)
|
|
|
|
if (response.status === 403) keycloak.login()
|
|
|
|
return response
|
|
},
|
|
headers: {
|
|
'Content-Type': 'application/json;charset=utf-8',
|
|
},
|
|
prepareHeaders: (headers) => {
|
|
headers.set('Authorization', `Bearer ${keycloak.token}`)
|
|
},
|
|
}),
|
|
tagTypes: ['Task', 'Chain', 'User', 'Submission', 'Stats'],
|
|
endpoints: (builder) => ({
|
|
// Tasks
|
|
getTasks: builder.query<ChallengeTask[], void>({
|
|
query: () => '/challenge/tasks',
|
|
transformResponse: (response: { body: ChallengeTask[] }) => response.body,
|
|
providesTags: ['Task'],
|
|
}),
|
|
getTask: builder.query<ChallengeTask, string>({
|
|
query: (id) => `/challenge/task/${id}`,
|
|
transformResponse: (response: { body: ChallengeTask }) => response.body,
|
|
providesTags: (_result, _error, id) => [{ type: 'Task', id }],
|
|
}),
|
|
createTask: builder.mutation<ChallengeTask, CreateTaskRequest>({
|
|
query: (body) => ({
|
|
url: '/challenge/task',
|
|
method: 'POST',
|
|
body,
|
|
}),
|
|
transformResponse: (response: { body: ChallengeTask }) => response.body,
|
|
invalidatesTags: ['Task'],
|
|
}),
|
|
updateTask: builder.mutation<ChallengeTask, { id: string; data: UpdateTaskRequest }>({
|
|
query: ({ id, data }) => ({
|
|
url: `/challenge/task/${id}`,
|
|
method: 'PUT',
|
|
body: data,
|
|
}),
|
|
transformResponse: (response: { body: ChallengeTask }) => response.body,
|
|
invalidatesTags: (_result, _error, { id }) => [{ type: 'Task', id }, 'Task'],
|
|
}),
|
|
deleteTask: builder.mutation<void, string>({
|
|
query: (id) => ({
|
|
url: `/challenge/task/${id}`,
|
|
method: 'DELETE',
|
|
}),
|
|
invalidatesTags: ['Task', 'Chain'],
|
|
}),
|
|
|
|
// Chains
|
|
getChains: builder.query<ChallengeChain[], void>({
|
|
query: () => '/challenge/chains/admin',
|
|
transformResponse: (response: { body: ChallengeChain[] }) => response.body,
|
|
providesTags: ['Chain'],
|
|
}),
|
|
getChain: builder.query<ChallengeChain, string>({
|
|
query: (id) => `/challenge/chain/${id}`,
|
|
transformResponse: (response: { body: ChallengeChain }) => response.body,
|
|
providesTags: (_result, _error, id) => [{ type: 'Chain', id }],
|
|
}),
|
|
createChain: builder.mutation<ChallengeChain, CreateChainRequest>({
|
|
query: (body) => ({
|
|
url: '/challenge/chain',
|
|
method: 'POST',
|
|
body,
|
|
}),
|
|
transformResponse: (response: { body: ChallengeChain }) => response.body,
|
|
invalidatesTags: ['Chain'],
|
|
}),
|
|
updateChain: builder.mutation<ChallengeChain, { id: string; data: UpdateChainRequest }>({
|
|
query: ({ id, data }) => ({
|
|
url: `/challenge/chain/${id}`,
|
|
method: 'PUT',
|
|
body: data,
|
|
}),
|
|
transformResponse: (response: { body: ChallengeChain }) => response.body,
|
|
invalidatesTags: (_result, _error, { id }) => [{ type: 'Chain', id }, 'Chain'],
|
|
}),
|
|
deleteChain: builder.mutation<void, string>({
|
|
query: (id) => ({
|
|
url: `/challenge/chain/${id}`,
|
|
method: 'DELETE',
|
|
}),
|
|
invalidatesTags: ['Chain'],
|
|
}),
|
|
|
|
// Statistics
|
|
getSystemStats: builder.query<SystemStats, void>({
|
|
query: () => '/challenge/stats',
|
|
transformResponse: (response: { body: SystemStats }) => response.body,
|
|
providesTags: ['Stats'],
|
|
}),
|
|
getSystemStatsV2: builder.query<SystemStatsV2, string | undefined>({
|
|
query: (chainId) => ({
|
|
url: '/challenge/stats/v2',
|
|
params: chainId ? { chainId } : undefined,
|
|
}),
|
|
transformResponse: (response: { body: SystemStatsV2 }) => response.body,
|
|
providesTags: ['Stats'],
|
|
}),
|
|
getUserStats: builder.query<UserStats, string>({
|
|
query: (userId) => `/challenge/user/${userId}/stats`,
|
|
transformResponse: (response: { body: UserStats }) => response.body,
|
|
providesTags: (_result, _error, userId) => [{ type: 'User', id: userId }],
|
|
}),
|
|
|
|
// Submissions
|
|
getUserSubmissions: builder.query<ChallengeSubmission[], { userId: string; taskId?: string }>({
|
|
query: ({ userId, taskId }) => {
|
|
const params = taskId ? `?taskId=${taskId}` : ''
|
|
return `/challenge/user/${userId}/submissions${params}`
|
|
},
|
|
transformResponse: (response: { body: ChallengeSubmission[] }) => response.body,
|
|
providesTags: ['Submission'],
|
|
}),
|
|
|
|
// Test submission (LLM check without creating a real submission)
|
|
testSubmission: builder.mutation<TestSubmissionResult, SubmitRequest>({
|
|
query: ({ userId, taskId, result, isTest = true, hiddenInstructions }) => ({
|
|
url: '/challenge/submit',
|
|
method: 'POST',
|
|
body: {
|
|
userId,
|
|
taskId,
|
|
result,
|
|
isTest,
|
|
hiddenInstructions,
|
|
},
|
|
}),
|
|
transformResponse: (response: APIResponse<TestSubmissionResult>) => response.data,
|
|
}),
|
|
}),
|
|
})
|
|
|
|
export const {
|
|
useGetTasksQuery,
|
|
useGetTaskQuery,
|
|
useCreateTaskMutation,
|
|
useUpdateTaskMutation,
|
|
useDeleteTaskMutation,
|
|
useGetChainsQuery,
|
|
useGetChainQuery,
|
|
useCreateChainMutation,
|
|
useUpdateChainMutation,
|
|
useDeleteChainMutation,
|
|
useGetSystemStatsQuery,
|
|
useGetSystemStatsV2Query,
|
|
useGetUserStatsQuery,
|
|
useGetUserSubmissionsQuery,
|
|
useTestSubmissionMutation,
|
|
} = api
|
|
|