feat: improve learning and platform operations
This commit is contained in:
@@ -24,6 +24,7 @@ export interface ManagedUserDetail extends ManagedUser {
|
||||
}
|
||||
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; }
|
||||
export interface AuditEntry { id: string; action: string; subjectType: string; subjectId: string | null; metadata: Record<string, unknown>; createdAt: string; actorName: string; }
|
||||
|
||||
interface Session {
|
||||
token: string;
|
||||
@@ -107,6 +108,7 @@ export const adminApi = {
|
||||
return apiRequest<{ data: { resetUrl: string } }>(`/admin/users/${userId}/password-reset`, { method: 'POST' });
|
||||
},
|
||||
async userDetail(userId: string) { return apiRequest<{ data: ManagedUserDetail }>(`/admin/users/${userId}`); },
|
||||
async auditLog() { return apiRequest<{ data: AuditEntry[] }>('/admin/audit-log'); },
|
||||
};
|
||||
|
||||
export const instructorApi = {
|
||||
|
||||
@@ -17,6 +17,9 @@ type ApiCourse = {
|
||||
description: string;
|
||||
category: string;
|
||||
coverImageUrl: string | null;
|
||||
status: 'draft' | 'published' | 'archived';
|
||||
progress?: number;
|
||||
lastActivity?: string | null;
|
||||
instructor: { name: string };
|
||||
lessons: Array<{
|
||||
id: string;
|
||||
@@ -57,6 +60,9 @@ const toCourse = (course: ApiCourse): Course => ({
|
||||
category: course.category,
|
||||
thumbnail: course.coverImageUrl || 'https://images.unsplash.com/photo-1460925895917-afdab827c52f?auto=format&fit=crop&w=800&q=80',
|
||||
instructor: course.instructor.name,
|
||||
status: course.status === 'draft' ? 'draft' : 'published',
|
||||
progress: course.progress,
|
||||
lastActivity: course.lastActivity || undefined,
|
||||
duration: `${course.lessons.length} Aulas`,
|
||||
lessons: course.lessons.map((lesson): Lesson => ({
|
||||
id: lesson.id,
|
||||
@@ -98,7 +104,7 @@ const toCoursePayload = (course: Course) => ({
|
||||
description: course.description,
|
||||
category: course.category,
|
||||
coverImageUrl: course.thumbnail && !course.thumbnail.startsWith('blob:') ? course.thumbnail : null,
|
||||
status: 'published' as const,
|
||||
status: course.status || 'published',
|
||||
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,
|
||||
@@ -123,6 +129,11 @@ export const getManagedCourses = async (): Promise<Course[]> => {
|
||||
return response.data.map(toCourse);
|
||||
};
|
||||
|
||||
export const getMyLearningCourses = async (): Promise<Course[]> => {
|
||||
const response = await apiRequest<{ data: ApiCourse[] }>('/courses/me/learning');
|
||||
return response.data.map(toCourse);
|
||||
};
|
||||
|
||||
export const getCourseById = async (id: string): Promise<Course | null> => {
|
||||
try {
|
||||
const response = await apiRequest<{ data: ApiCourse }>(`/courses/${id}`);
|
||||
@@ -192,15 +203,26 @@ export const moderateComment = async (commentId: string): Promise<void> => {
|
||||
};
|
||||
|
||||
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);
|
||||
const progress = await getLessonProgress(courseId);
|
||||
return progress.filter((item) => item.completedAt).map((item) => item.lessonId);
|
||||
};
|
||||
|
||||
export const saveLessonCompletion = async (lessonId: string, completed: boolean): Promise<void> => {
|
||||
export type LessonProgress = { lessonId: string; watchedSeconds: number; completedAt: string | null };
|
||||
|
||||
export const getLessonProgress = async (courseId: string): Promise<LessonProgress[]> => {
|
||||
const response = await apiRequest<{ data: LessonProgress[] }>(`/courses/${courseId}/progress`);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const saveLessonCompletion = async (lessonId: string, completed: boolean, watchedSeconds?: number): Promise<void> => {
|
||||
await apiRequest(`/lessons/${lessonId}/progress`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({ completed }),
|
||||
body: JSON.stringify({ completed, watchedSeconds }),
|
||||
});
|
||||
};
|
||||
|
||||
export const saveLessonProgress = async (lessonId: string, watchedSeconds: number): Promise<void> => {
|
||||
await apiRequest(`/lessons/${lessonId}/progress`, { method: 'PUT', body: JSON.stringify({ watchedSeconds }) });
|
||||
};
|
||||
|
||||
export const incrementViews = async (_courseId: string): Promise<void> => undefined;
|
||||
|
||||
Reference in New Issue
Block a user