167 lines
4.5 KiB
TypeScript
167 lines
4.5 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',
|
||
// 開發階段:不發送無效的token,讓後端使用測試用戶
|
||
// '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(); |