feat: expand admin and instructor tools
This commit is contained in:
@@ -18,6 +18,12 @@ export interface ManagedUser {
|
||||
isActive: boolean;
|
||||
createdAt: string;
|
||||
}
|
||||
export interface ManagedUserDetail extends ManagedUser {
|
||||
completedLessons: number;
|
||||
lastLearningAt: string | null;
|
||||
}
|
||||
export interface PlatformAnalytics { totalUsers: number; activeUsers: number; publishedCourses: number; completedLessons: number; comments: number; }
|
||||
export interface InstructorAnalytics { courses: number; lessons: number; learners: number; completedLessons: number; comments: number; }
|
||||
|
||||
interface Session {
|
||||
token: string;
|
||||
@@ -75,9 +81,16 @@ export const authApi = {
|
||||
async me() {
|
||||
return apiRequest<{ user: ApiUser }>('/auth/me');
|
||||
},
|
||||
async acceptInvitation(token: string, name: string, password: string) {
|
||||
return apiRequest<Session>('/auth/accept-invitation', { method: 'POST', body: JSON.stringify({ token, name, password }) });
|
||||
},
|
||||
async resetPassword(token: string, password: string) {
|
||||
return apiRequest<void>('/auth/reset-password', { method: 'POST', body: JSON.stringify({ token, password }) });
|
||||
},
|
||||
};
|
||||
|
||||
export const adminApi = {
|
||||
async dashboard() { return apiRequest<{ data: PlatformAnalytics }>('/admin/dashboard'); },
|
||||
async listUsers() {
|
||||
return apiRequest<{ data: ManagedUser[] }>('/admin/users');
|
||||
},
|
||||
@@ -87,4 +100,15 @@ export const adminApi = {
|
||||
body: JSON.stringify(update),
|
||||
});
|
||||
},
|
||||
async invite(email: string, role: 'student' | 'instructor') {
|
||||
return apiRequest<{ data: { inviteUrl: string } }>('/admin/invitations', { method: 'POST', body: JSON.stringify({ email, role }) });
|
||||
},
|
||||
async passwordReset(userId: string) {
|
||||
return apiRequest<{ data: { resetUrl: string } }>(`/admin/users/${userId}/password-reset`, { method: 'POST' });
|
||||
},
|
||||
async userDetail(userId: string) { return apiRequest<{ data: ManagedUserDetail }>(`/admin/users/${userId}`); },
|
||||
};
|
||||
|
||||
export const instructorApi = {
|
||||
async analytics() { return apiRequest<{ data: InstructorAnalytics }>('/manage/courses/analytics'); },
|
||||
};
|
||||
|
||||
@@ -101,6 +101,7 @@ const toCoursePayload = (course: Course) => ({
|
||||
status: 'published' as const,
|
||||
assets: (course.attachments || []).filter((attachment) => attachment.url && attachment.url !== '#').map(toAssetPayload),
|
||||
lessons: course.lessons.map((lesson) => ({
|
||||
id: /^[0-9a-f]{8}-[0-9a-f-]{27}$/i.test(lesson.id) ? lesson.id : undefined,
|
||||
title: lesson.title,
|
||||
description: lesson.description || '',
|
||||
durationSeconds: toSeconds(lesson.duration),
|
||||
@@ -182,6 +183,14 @@ export const saveComment = async (comment: Pick<Comment, 'courseId' | 'lessonId'
|
||||
return toComment(response.data);
|
||||
};
|
||||
|
||||
export const replyToComment = async (commentId: string, text: string): Promise<void> => {
|
||||
await apiRequest(`/comments/${commentId}/reply`, { method: 'PUT', body: JSON.stringify({ text }) });
|
||||
};
|
||||
|
||||
export const moderateComment = async (commentId: string): Promise<void> => {
|
||||
await apiRequest(`/comments/${commentId}`, { method: 'DELETE' });
|
||||
};
|
||||
|
||||
export const getCompletedLessonIds = async (courseId: string): Promise<string[]> => {
|
||||
const response = await apiRequest<{ data: Array<{ lessonId: string; completedAt: string | null }> }>(`/courses/${courseId}/progress`);
|
||||
return response.data.filter((progress) => progress.completedAt).map((progress) => progress.lessonId);
|
||||
|
||||
Reference in New Issue
Block a user