dramaling-vocab-learning/frontend/lib/services/studySession.ts

166 lines
4.4 KiB
TypeScript

// 學習會話服務
const API_BASE = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:5008';
// 類型定義
export interface StudySession {
sessionId: string;
totalCards: number;
totalTests: number;
currentCardIndex: number;
currentTestType?: string;
startedAt: string;
}
export interface CurrentTest {
sessionId: string;
testType: string;
card: Card;
progress: ProgressSummary;
}
export interface Card {
id: string;
word: string;
translation: string;
definition: string;
example: string;
exampleTranslation: string;
pronunciation: string;
difficultyLevel: string;
}
export interface ProgressSummary {
currentCardIndex: number;
totalCards: number;
completedTests: number;
totalTests: number;
completedCards: number;
}
export interface TestResult {
testType: string;
isCorrect: boolean;
userAnswer?: string;
confidenceLevel?: number;
responseTimeMs: number;
}
export interface SubmitTestResponse {
success: boolean;
isCardCompleted: boolean;
progress: ProgressSummary;
message: string;
}
export interface NextTest {
hasNextTest: boolean;
testType?: string;
sameCard: boolean;
message: string;
}
export interface Progress {
sessionId: string;
status: string;
currentCardIndex: number;
totalCards: number;
completedTests: number;
totalTests: number;
completedCards: number;
cards: CardProgress[];
}
export interface CardProgress {
cardId: string;
word: string;
plannedTests: string[];
completedTestsCount: number;
isCompleted: boolean;
tests: TestProgress[];
}
export interface TestProgress {
testType: string;
isCorrect: boolean;
completedAt: string;
}
export class StudySessionService {
private async makeRequest<T>(endpoint: string, options: RequestInit = {}): Promise<{ success: boolean; data: T | null; error?: string }> {
try {
const token = localStorage.getItem('auth_token');
const response = await fetch(`${API_BASE}${endpoint}`, {
headers: {
'Content-Type': 'application/json',
'Authorization': token ? `Bearer ${token}` : '',
...options.headers,
},
...options,
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({ error: 'Network error' }));
return { success: false, data: null, error: errorData.error || `HTTP ${response.status}` };
}
const result = await response.json();
return { success: result.Success || false, data: result.Data || null, error: result.Error };
} catch (error) {
console.error('API request failed:', error);
return { success: false, data: null, error: 'Network error' };
}
}
/**
* 開始新的學習會話
*/
async startSession(): Promise<{ success: boolean; data: StudySession | null; error?: string }> {
return await this.makeRequest<StudySession>('/api/study/sessions/start', {
method: 'POST'
});
}
/**
* 獲取當前測驗
*/
async getCurrentTest(sessionId: string): Promise<{ success: boolean; data: CurrentTest | null; error?: string }> {
return await this.makeRequest<CurrentTest>(`/api/study/sessions/${sessionId}/current-test`);
}
/**
* 提交測驗結果
*/
async submitTest(sessionId: string, result: TestResult): Promise<{ success: boolean; data: SubmitTestResponse | null; error?: string }> {
return await this.makeRequest<SubmitTestResponse>(`/api/study/sessions/${sessionId}/submit-test`, {
method: 'POST',
body: JSON.stringify(result)
});
}
/**
* 獲取下一個測驗
*/
async getNextTest(sessionId: string): Promise<{ success: boolean; data: NextTest | null; error?: string }> {
return await this.makeRequest<NextTest>(`/api/study/sessions/${sessionId}/next-test`);
}
/**
* 獲取詳細進度
*/
async getProgress(sessionId: string): Promise<{ success: boolean; data: Progress | null; error?: string }> {
return await this.makeRequest<Progress>(`/api/study/sessions/${sessionId}/progress`);
}
/**
* 完成學習會話
*/
async completeSession(sessionId: string): Promise<{ success: boolean; data: any | null; error?: string }> {
return await this.makeRequest(`/api/study/sessions/${sessionId}/complete`, {
method: 'PUT'
});
}
}
// 導出服務實例
export const studySessionService = new StudySessionService();