import type { SessionAnswerResponse, SessionQuestionsResponse, SessionRequest, SessionResponse, SubmitAnswer, } from "../types/session"; import type { PracticeSheet } from "../types/sheet"; const API_URL = "https://ed-dev-api.omukk.dev"; export interface LoginRequest { email: string; password: string; } export interface User { email: string; name: string; role: "STUDENT" | "TEACHER" | "ADMIN"; avatar_url: string; id: string; status: "ACTIVE" | "INACTIVE"; joined_at: string; last_active: string; } export interface LoginResponse { token: string; token_type: string; user: User; } export interface ApiError { detail?: string; message?: string; } class ApiClient { private baseURL: string; constructor(baseURL: string) { this.baseURL = baseURL; } private async request( endpoint: string, options: RequestInit = {}, ): Promise { const url = `${this.baseURL}${endpoint}`; const config: RequestInit = { ...options, headers: { "Content-Type": "application/json", ...options.headers, }, }; try { const response = await fetch(url, config); if (!response.ok) { const error: ApiError = await response.json().catch(() => ({ message: "An error occurred", })); throw new Error(error.detail || error.message || "Request failed"); } return await response.json(); } catch (error) { if (error instanceof Error) { throw error; } throw new Error("Network error occurred"); } } // Auth endpoints async login(credentials: LoginRequest): Promise { return this.request("/auth/login/", { method: "POST", body: JSON.stringify(credentials), }); } // Authenticated request helper async authenticatedRequest( endpoint: string, token: string, options: RequestInit = {}, ): Promise { return this.request(endpoint, { ...options, headers: { ...options.headers, Authorization: `Bearer ${token}`, }, }); } // Example: Get user profile (authenticated endpoint) async getUserProfile(token: string): Promise { return this.authenticatedRequest("/auth/me/", token); } async getPracticeSheets( token: string, page: number, limit: number, ): Promise { const queryParams = new URLSearchParams({ page: page.toString(), limit: limit.toString(), }).toString(); return this.authenticatedRequest( `/practice-sheets/?${queryParams}`, token, ); } async getPracticeSheetById( token: string, sheetId: string, ): Promise { return this.authenticatedRequest( `/practice-sheets/${sheetId}`, token, ); } async startSession( token: string, sessionData: SessionRequest, ): Promise { return this.authenticatedRequest(`/sessions/`, token, { method: "POST", body: JSON.stringify(sessionData), }); } async fetchSessionQuestions( token: string, sessionId: string, ): Promise { return this.authenticatedRequest( `/sessions/${sessionId}/questions/`, token, ); } async submitAnswer( token: string, sessionId: string, answerSubmissionData: SubmitAnswer, ): Promise { return this.authenticatedRequest( `/sessions/${sessionId}/answer/`, token, { method: "POST", body: JSON.stringify(answerSubmissionData), }, ); } async fetchNextModule(token: string, sessionId: string): Promise { return this.authenticatedRequest( `/sessions/${sessionId}/next-module/`, token, { method: "POST", }, ); } async fetchSessionStateById( token: string, sessionId: string, ): Promise { return this.authenticatedRequest( `/sessions/${sessionId}`, token, ); } } export const api = new ApiClient(API_URL);