export type InstructorStudentIssue = { type: 'MISSING_SUBMISSION' | 'COMPLETED_WITHOUT_SUBMISSION' | 'LOW_AVERAGE_SCORE'; title: string; detail: string; week?: number; }; export type InstructorStudent = { id: string; name: string; email: string; group: string; week: string; progress: number; commits: number; issues: number; issueItems: InstructorStudentIssue[]; lastActive: string; online: boolean; courseTitle?: string; }; export type InstructorStudentsSummary = { totalStudents: number; onlineStudents: number; averageProgress: number; unresolvedIssues: number; }; export type InstructorStudentsResponse = { organization: { id?: string; name: string; } | null; summary: InstructorStudentsSummary; students: InstructorStudent[]; }; export type CreateInstructorStudentInput = { courseId?: string | null; email: string; name: string; groupId?: string | null; }; const LMS_API_BASE_URL = (import.meta.env.VITE_API_BASE_URL ?? 'https://workspace.autonomystudio.net/lms-api/api').replace(/\/+$/, ''); export async function listInstructorStudents(accessToken: string, courseId?: string | null): Promise { const query = courseId ? `?courseId=${encodeURIComponent(courseId)}` : ''; const response = await fetch(`${LMS_API_BASE_URL}/instructor/students${query}`, { headers: { Authorization: `Bearer ${accessToken}`, }, }); if (!response.ok) { throw new Error(`수강생 현황을 불러오지 못했습니다. (${response.status})`); } return response.json() as Promise; } export async function createInstructorStudent( accessToken: string, input: CreateInstructorStudentInput, ): Promise { const response = await fetch(`${LMS_API_BASE_URL}/instructor/students`, { method: 'POST', headers: { Authorization: `Bearer ${accessToken}`, 'content-type': 'application/json', }, body: JSON.stringify(input), }); if (!response.ok) { const payload = await response.json().catch((): null => null); const message = payload && typeof payload === 'object' && 'message' in payload ? String(payload.message) : `수강생을 등록하지 못했습니다. (${response.status})`; throw new Error(message); } return response.json() as Promise; } export async function removeInstructorStudent( accessToken: string, studentId: string, ): Promise { const response = await fetch(`${LMS_API_BASE_URL}/instructor/students/${studentId}`, { method: 'DELETE', headers: { Authorization: `Bearer ${accessToken}`, }, }); if (!response.ok) { const payload = await response.json().catch((): null => null); const message = payload && typeof payload === 'object' && 'message' in payload ? String(payload.message) : `수강생을 제외하지 못했습니다. (${response.status})`; throw new Error(message); } return response.json() as Promise; }