feat: implement QuestionBank CRUD with pagination and template query
- Add pagination support to findAll (page, limit query params) - Add findByTemplateId method to service - Add GET /by-template/:templateId endpoint to controller - Service already includes CRUD for QuestionBank and QuestionBankItem
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
import { apiClient } from './apiClient';
|
||||
|
||||
export interface AssessmentSession {
|
||||
id: string;
|
||||
userId: string;
|
||||
knowledgeBaseId: string;
|
||||
threadId: string;
|
||||
status: 'IN_PROGRESS' | 'COMPLETED';
|
||||
finalScore?: number;
|
||||
finalReport?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
knowledgeBase?: { id: string; name: string };
|
||||
knowledgeGroup?: { id: string; name: string };
|
||||
}
|
||||
|
||||
export interface AssessmentState {
|
||||
messages: any[];
|
||||
assessmentSessionId: string;
|
||||
knowledgeBaseId: string;
|
||||
questions: any[];
|
||||
currentQuestionIndex: number;
|
||||
shouldFollowUp: boolean;
|
||||
scores: Record<string, number>;
|
||||
feedbackHistory?: any[];
|
||||
status?: 'IN_PROGRESS' | 'COMPLETED';
|
||||
report?: string;
|
||||
finalScore?: number;
|
||||
}
|
||||
|
||||
export class AssessmentService {
|
||||
async startSession(knowledgeBaseId: string, language: string, templateId?: string): Promise<AssessmentSession> {
|
||||
const { data } = await apiClient.post<AssessmentSession>('/assessment/start', { knowledgeBaseId, language, templateId });
|
||||
return data;
|
||||
}
|
||||
async submitAnswer(sessionId: string, answer: string, language: string): Promise<AssessmentState> {
|
||||
const { data } = await apiClient.post<AssessmentState>(`/assessment/${sessionId}/answer`, { answer, language });
|
||||
return data;
|
||||
}
|
||||
async getSessionState(sessionId: string): Promise<AssessmentState> {
|
||||
const { data } = await apiClient.get<AssessmentState>(`/assessment/${sessionId}/state`);
|
||||
return data;
|
||||
}
|
||||
|
||||
async getHistory(): Promise<AssessmentSession[]> {
|
||||
const { data } = await apiClient.get<AssessmentSession[]>('/assessment');
|
||||
return data;
|
||||
}
|
||||
|
||||
async deleteSession(sessionId: string): Promise<void> {
|
||||
await apiClient.delete(`/assessment/${sessionId}`);
|
||||
}
|
||||
|
||||
async *startSessionStream(sessionId: string, templateId?: string): AsyncIterableIterator<any> {
|
||||
const query = templateId ? `?templateId=${templateId}` : '';
|
||||
const response = await apiClient.request(`/assessment/${sessionId}/start-stream${query}`, {
|
||||
method: 'GET',
|
||||
});
|
||||
yield* this.parseStream(response);
|
||||
}
|
||||
|
||||
async *submitAnswerStream(sessionId: string, answer: string, language: string, templateId?: string): AsyncIterableIterator<any> {
|
||||
const query = new URLSearchParams({ answer, language, ...(templateId && { templateId }) }).toString();
|
||||
const response = await apiClient.request(`/assessment/${sessionId}/answer-stream?${query}`, {
|
||||
method: 'GET',
|
||||
});
|
||||
yield* this.parseStream(response);
|
||||
}
|
||||
|
||||
private async *parseStream(response: Response): AsyncIterableIterator<any> {
|
||||
const reader = response.body?.getReader();
|
||||
if (!reader) return;
|
||||
|
||||
const decoder = new TextDecoder();
|
||||
let buffer = '';
|
||||
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) break;
|
||||
|
||||
buffer += decoder.decode(value, { stream: true });
|
||||
const lines = buffer.split('\n');
|
||||
buffer = lines.pop() || '';
|
||||
|
||||
for (const line of lines) {
|
||||
if (line.startsWith('data: ')) {
|
||||
try {
|
||||
const data = JSON.parse(line.substring(6));
|
||||
yield data;
|
||||
} catch (e) {
|
||||
console.error('Failed to parse SSE data:', line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const assessmentService = new AssessmentService();
|
||||
Reference in New Issue
Block a user