// Flashcards API service export interface Flashcard { id: string; word: string; translation: string; definition: string; partOfSpeech: string; pronunciation: string; example: string; exampleTranslation?: string; masteryLevel: number; timesReviewed: number; isFavorite: boolean; nextReviewDate: string; difficultyLevel: string; createdAt: string; updatedAt?: string; // 設為可選,因為模擬資料可能沒有 // 移除 cardSet 屬性 } export interface CreateFlashcardRequest { word: string; translation: string; definition: string; pronunciation: string; partOfSpeech: string; example: string; exampleTranslation?: string; difficultyLevel?: string; // A1, A2, B1, B2, C1, C2 } export interface ApiResponse { success: boolean; data?: T; error?: string; message?: string; } class FlashcardsService { private readonly baseURL = `${process.env.NEXT_PUBLIC_API_URL || 'http://localhost:5008'}/api`; private async makeRequest(endpoint: string, options: RequestInit = {}): Promise { const response = await fetch(`${this.baseURL}${endpoint}`, { headers: { 'Content-Type': 'application/json', ...options.headers, }, ...options, }); if (!response.ok) { const errorData = await response.json().catch(() => ({ error: 'Network error' })); throw new Error(errorData.error || errorData.details || `HTTP ${response.status}`); } return response.json(); } // 詞卡查詢方法 (支援進階篩選、排序和分頁) async getFlashcards( search?: string, favoritesOnly: boolean = false, cefrLevel?: string, partOfSpeech?: string, masteryLevel?: string, sortBy?: string, sortOrder?: 'asc' | 'desc', page?: number, limit?: number ): Promise> { try { const params = new URLSearchParams(); if (search) params.append('search', search); if (favoritesOnly) params.append('favoritesOnly', 'true'); if (cefrLevel) params.append('cefrLevel', cefrLevel); if (partOfSpeech) params.append('partOfSpeech', partOfSpeech); if (masteryLevel) params.append('masteryLevel', masteryLevel); // 排序和分頁參數 if (sortBy) params.append('sortBy', sortBy); if (sortOrder) params.append('sortOrder', sortOrder); if (page) params.append('page', page.toString()); if (limit) params.append('limit', limit.toString()); const queryString = params.toString(); const endpoint = `/flashcards${queryString ? `?${queryString}` : ''}`; return await this.makeRequest>(endpoint); } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Failed to fetch flashcards', }; } } async createFlashcard(data: CreateFlashcardRequest): Promise> { try { return await this.makeRequest>('/flashcards', { method: 'POST', body: JSON.stringify(data), }); } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Failed to create flashcard', }; } } async deleteFlashcard(id: string): Promise> { try { return await this.makeRequest>(`/flashcards/${id}`, { method: 'DELETE', }); } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Failed to delete flashcard', }; } } async getFlashcard(id: string): Promise> { try { return await this.makeRequest>(`/flashcards/${id}`); } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Failed to get flashcard', }; } } async updateFlashcard(id: string, data: CreateFlashcardRequest): Promise> { try { return await this.makeRequest>(`/flashcards/${id}`, { method: 'PUT', body: JSON.stringify(data), }); } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Failed to update flashcard', }; } } async toggleFavorite(id: string): Promise> { try { return await this.makeRequest>(`/flashcards/${id}/favorite`, { method: 'POST', }); } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Failed to toggle favorite', }; } } } export const flashcardsService = new FlashcardsService();