Files
lms-adm-fe/src/lib/students.ts
T

110 lines
3.0 KiB
TypeScript

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<InstructorStudentsResponse> {
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<InstructorStudentsResponse>;
}
export async function createInstructorStudent(
accessToken: string,
input: CreateInstructorStudentInput,
): Promise<InstructorStudentsResponse> {
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<InstructorStudentsResponse>;
}
export async function removeInstructorStudent(
accessToken: string,
studentId: string,
): Promise<InstructorStudentsResponse> {
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<InstructorStudentsResponse>;
}