277 lines
8.1 KiB
TypeScript
277 lines
8.1 KiB
TypeScript
/**
|
|
* API модуль для dashboard
|
|
*/
|
|
|
|
import apiClient from '@/lib/api-client';
|
|
|
|
// Типы данных dashboard
|
|
export interface DashboardStats {
|
|
total_clients?: number;
|
|
active_clients?: number;
|
|
lessons_this_month?: number;
|
|
lessons_today?: number;
|
|
lessons_this_week?: number;
|
|
earnings_this_month?: number;
|
|
total_revenue?: number;
|
|
upcoming_lessons?: LessonPreview[];
|
|
recent_homework?: HomeworkPreview[];
|
|
total_lessons?: number;
|
|
completed_lessons?: number;
|
|
homework_pending?: number;
|
|
homework_completed?: number;
|
|
average_grade?: number;
|
|
next_lesson?: LessonPreview | null;
|
|
children_count?: number;
|
|
children_stats?: ChildStats[];
|
|
total_homeworks?: number;
|
|
pending_submissions?: number;
|
|
total_materials?: number;
|
|
unread_notifications?: number;
|
|
}
|
|
|
|
export interface LessonPreview {
|
|
id: string;
|
|
title: string;
|
|
subject: string;
|
|
start_time: string;
|
|
end_time: string;
|
|
mentor?: UserPreview;
|
|
client?: UserPreview;
|
|
status: 'scheduled' | 'in_progress' | 'completed' | 'cancelled';
|
|
room_url?: string;
|
|
}
|
|
|
|
export interface HomeworkPreview {
|
|
id: string;
|
|
title: string;
|
|
subject: string;
|
|
due_date: string;
|
|
status: 'pending' | 'submitted' | 'reviewed' | 'completed';
|
|
grade?: number;
|
|
lesson?: LessonPreview;
|
|
}
|
|
|
|
export interface ChildStats {
|
|
id: string;
|
|
name: string;
|
|
avatar?: string | null;
|
|
avatar_url?: string | null;
|
|
total_lessons: number;
|
|
completed_lessons: number;
|
|
average_grade: number;
|
|
next_lesson?: LessonPreview | null;
|
|
homework_pending: number;
|
|
}
|
|
|
|
export interface UserPreview {
|
|
id: string;
|
|
email?: string;
|
|
name?: string;
|
|
first_name: string;
|
|
last_name: string;
|
|
avatar?: string;
|
|
}
|
|
|
|
export interface MentorDashboardResponse {
|
|
summary: {
|
|
total_clients: number;
|
|
total_lessons: number;
|
|
lessons_this_week: number;
|
|
lessons_this_month: number;
|
|
completed_lessons: number;
|
|
total_homeworks: number;
|
|
pending_submissions: number;
|
|
total_materials: number;
|
|
unread_notifications: number;
|
|
total_revenue: number;
|
|
revenue_this_month: number;
|
|
};
|
|
upcoming_lessons: Array<{
|
|
id: string;
|
|
title: string;
|
|
subject?: string | null;
|
|
client: {
|
|
id: string;
|
|
name: string;
|
|
avatar?: string | null;
|
|
first_name?: string;
|
|
last_name?: string;
|
|
};
|
|
start_time: string;
|
|
end_time: string;
|
|
}>;
|
|
recent_submissions?: Array<{
|
|
id: string;
|
|
homework: {
|
|
id: string;
|
|
title: string;
|
|
};
|
|
subject?: string | null;
|
|
student: {
|
|
id: string;
|
|
name: string;
|
|
avatar?: string | null;
|
|
first_name?: string;
|
|
last_name?: string;
|
|
};
|
|
status: string;
|
|
score?: number | null;
|
|
max_score: number;
|
|
submitted_at: string;
|
|
}>;
|
|
}
|
|
|
|
export interface IncomeChartData {
|
|
date: string;
|
|
income: number;
|
|
lessons: number;
|
|
}
|
|
|
|
export interface MentorIncomeResponse {
|
|
period: string;
|
|
start_date: string;
|
|
end_date: string;
|
|
summary: {
|
|
total_income: number;
|
|
total_lessons: number;
|
|
average_lesson_price: number;
|
|
};
|
|
chart_data: IncomeChartData[];
|
|
}
|
|
|
|
/**
|
|
* Получить статистику для дашборда ментора
|
|
*/
|
|
export async function getMentorDashboard(options?: { signal?: AbortSignal }): Promise<MentorDashboardResponse> {
|
|
const config = options?.signal ? { signal: options.signal } : undefined;
|
|
const response = await apiClient.get<MentorDashboardResponse>('/mentor/dashboard/', config);
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Ответ API прогресса клиента (оценки по предметам, посещаемость и т.д.)
|
|
*/
|
|
export interface ClientProgressResponse {
|
|
total_lessons: number;
|
|
completed_lessons: number;
|
|
cancelled_lessons: number;
|
|
attendance_rate: number;
|
|
average_mentor_grade: number;
|
|
average_school_grade: number;
|
|
total_homework: number;
|
|
completed_homework: number;
|
|
homework_completion_rate: number;
|
|
grades_by_subject: Array<{ subject: string; average_grade: number; lessons_count: number }>;
|
|
recent_grades?: Array<{
|
|
lesson_title: string;
|
|
date: string | null;
|
|
mentor_grade: number;
|
|
school_grade: number;
|
|
}>;
|
|
}
|
|
|
|
/**
|
|
* Получить прогресс клиента (для списка предметов и сводок).
|
|
* GET /api/client/progress/?period=90
|
|
*/
|
|
export async function getClientProgress(params?: { period?: number }): Promise<ClientProgressResponse> {
|
|
const url = params?.period != null ? `/client/progress/?period=${params.period}` : '/client/progress/';
|
|
const response = await apiClient.get<ClientProgressResponse>(url);
|
|
return response.data;
|
|
}
|
|
|
|
/** Ответ API /client/dashboard/ и /parent/{id}/child_dashboard/ — данные в summary */
|
|
interface ClientDashboardApiResponse {
|
|
summary?: {
|
|
total_lessons?: number;
|
|
completed_lessons?: number;
|
|
lessons_this_week?: number;
|
|
total_homeworks?: number;
|
|
completed_homeworks?: number;
|
|
pending_homeworks?: number;
|
|
average_score?: number;
|
|
shared_materials?: number;
|
|
unread_notifications?: number;
|
|
};
|
|
upcoming_lessons?: Array<{
|
|
id: string | number;
|
|
title?: string;
|
|
mentor?: { id: number; name: string };
|
|
start_time?: string | null;
|
|
end_time?: string | null;
|
|
}>;
|
|
}
|
|
|
|
function normalizeClientDashboardResponse(raw: ClientDashboardApiResponse): DashboardStats {
|
|
const s = raw.summary ?? {};
|
|
const upcoming = raw.upcoming_lessons ?? [];
|
|
return {
|
|
total_lessons: s.total_lessons ?? 0,
|
|
completed_lessons: s.completed_lessons ?? 0,
|
|
homework_pending: s.pending_homeworks ?? 0,
|
|
homework_completed: s.completed_homeworks ?? 0,
|
|
average_grade: s.average_score ?? 0,
|
|
next_lesson: upcoming[0] ? {
|
|
id: String(upcoming[0].id),
|
|
title: upcoming[0].title ?? '',
|
|
subject: '',
|
|
start_time: upcoming[0].start_time ?? '',
|
|
end_time: upcoming[0].end_time ?? '',
|
|
status: 'scheduled',
|
|
mentor: upcoming[0].mentor ? { id: String(upcoming[0].mentor.id), first_name: upcoming[0].mentor.name, last_name: '', email: '' } : undefined,
|
|
} : null,
|
|
upcoming_lessons: upcoming.map((l) => ({
|
|
id: String(l.id),
|
|
title: l.title ?? '',
|
|
subject: '',
|
|
start_time: l.start_time ?? '',
|
|
end_time: l.end_time ?? '',
|
|
status: 'scheduled' as const,
|
|
mentor: l.mentor ? { id: String(l.mentor.id), first_name: l.mentor.name, last_name: '', email: '' } : undefined,
|
|
})),
|
|
recent_homework: [],
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Получить статистику для дашборда клиента
|
|
*/
|
|
export async function getClientDashboard(): Promise<DashboardStats> {
|
|
const response = await apiClient.get<ClientDashboardApiResponse>('/client/dashboard/');
|
|
return normalizeClientDashboardResponse(response.data);
|
|
}
|
|
|
|
/**
|
|
* Получить статистику для дашборда родителя
|
|
*/
|
|
export async function getParentDashboard(): Promise<DashboardStats> {
|
|
const response = await apiClient.get<DashboardStats>('/parent/dashboard/');
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Получить дашборд выбранного ребенка для родителя
|
|
*/
|
|
export async function getChildDashboard(childId: string): Promise<DashboardStats> {
|
|
const response = await apiClient.get<ClientDashboardApiResponse>(`/parent/${childId}/child_dashboard/`);
|
|
return normalizeClientDashboardResponse(response.data);
|
|
}
|
|
|
|
/**
|
|
* Получить статистику доходов ментора
|
|
*/
|
|
export async function getMentorIncome(
|
|
period: 'day' | 'week' | 'month' | 'range' = 'week',
|
|
startDate?: string,
|
|
endDate?: string,
|
|
options?: { signal?: AbortSignal }
|
|
): Promise<MentorIncomeResponse> {
|
|
let url = `/mentor/income/?period=${period}`;
|
|
if (period === 'range' && startDate && endDate) {
|
|
url += `&start_date=${startDate}&end_date=${endDate}`;
|
|
}
|
|
const config = options?.signal ? { signal: options.signal } : undefined;
|
|
const response = await apiClient.get<MentorIncomeResponse>(url, config);
|
|
return response.data;
|
|
}
|