uchill/front_material/api/analytics.ts

147 lines
5.3 KiB
TypeScript

/**
* API аналитики ментора (отдельная страница, не профиль).
* Период по умолчанию на странице аналитики — последние 30 дней.
*/
import apiClient from '@/lib/api-client';
export type AnalyticsPeriod = 'day' | 'week' | 'month' | 'year' | 'custom';
export interface AnalyticsDateRange {
period: AnalyticsPeriod;
start_date: string; // YYYY-MM-DD
end_date: string;
}
export interface AnalyticsOverview {
period: { start: string; end: string };
lessons: { total: number; completed: number; cancelled: number };
revenue: { total: number; average_per_lesson: number };
students: { active: number };
homeworks: { total: number; pending: number };
grades: { average: number };
}
export interface StudentStat {
id: number;
name: string;
email: string;
lessons_total: number;
lessons_completed: number;
average_grade: number;
revenue: number;
}
export interface AnalyticsStudentsResponse {
students: StudentStat[];
total_count: number;
}
export interface AnalyticsRevenueResponse {
total_revenue: number;
by_day: { date: string; revenue: number; lessons_count: number }[];
by_subject: { subject: string; revenue: number; lessons_count: number }[];
}
export interface AnalyticsLessonsStatsResponse {
by_status: { status: string; count: number }[];
by_subject: { subject: string; count: number }[];
by_weekday: { day: string; count: number }[];
}
/** Средняя оценка по дням (успех учеников / продуктивность репетитора) */
export interface AnalyticsGradesByDayResponse {
period: { start: string; end: string };
by_day: {
date: string;
average_grade: number | null;
lessons_count: number;
graded_count: number;
}[];
summary: {
total_lessons: number;
graded_lessons: number;
average_grade: number;
};
}
/** Последние 30 дней (по умолчанию на странице аналитики). */
export function getLast30DaysRange(): { start_date: string; end_date: string } {
const now = new Date();
const end = new Date(now);
const start = new Date(now);
start.setDate(start.getDate() - 29); // 30 дней включительно: сегодня минус 29
const fmt = (d: Date) => d.toISOString().slice(0, 10);
return { start_date: fmt(start), end_date: fmt(end) };
}
export function getCurrentWeekRange(): { start_date: string; end_date: string } {
const now = new Date();
const day = now.getDay();
const diff = day === 0 ? -6 : 1 - day; // понедельник
const monday = new Date(now);
monday.setDate(now.getDate() + diff);
const sunday = new Date(monday);
sunday.setDate(monday.getDate() + 6);
const fmt = (d: Date) => d.toISOString().slice(0, 10);
return { start_date: fmt(monday), end_date: fmt(sunday) };
}
function getWeekRange(): { start: string; end: string } {
const r = getCurrentWeekRange();
return { start: r.start_date, end: r.end_date };
}
export function getDefaultDateRange(): AnalyticsDateRange {
const { start, end } = getWeekRange();
return { period: 'week', start_date: start, end_date: end };
}
/** Преобразовать диапазон дат в AnalyticsDateRange для API (всегда custom) */
export function toAnalyticsRange(r: { start_date: string; end_date: string }): AnalyticsDateRange {
return { period: 'custom', start_date: r.start_date, end_date: r.end_date };
}
function buildParams(range: AnalyticsDateRange): string {
const p = new URLSearchParams();
p.set('period', range.period === 'custom' ? 'custom' : range.period);
p.set('start_date', range.start_date);
p.set('end_date', range.end_date);
return p.toString();
}
export async function getAnalyticsOverview(range: AnalyticsDateRange): Promise<AnalyticsOverview> {
const q = buildParams(range);
const url = q ? `/analytics/overview?${q}` : '/analytics/overview';
const res = await apiClient.get<AnalyticsOverview>(url);
return res.data;
}
export async function getAnalyticsStudents(range: AnalyticsDateRange): Promise<AnalyticsStudentsResponse> {
const q = buildParams(range);
const url = q ? `/analytics/students?${q}` : '/analytics/students';
const res = await apiClient.get<AnalyticsStudentsResponse>(url);
return res.data;
}
export async function getAnalyticsRevenue(range: AnalyticsDateRange): Promise<AnalyticsRevenueResponse> {
const q = buildParams(range);
const url = q ? `/analytics/revenue?${q}` : '/analytics/revenue';
const res = await apiClient.get<AnalyticsRevenueResponse>(url);
return res.data;
}
export async function getAnalyticsLessonsStats(range: AnalyticsDateRange): Promise<AnalyticsLessonsStatsResponse> {
const q = buildParams(range);
const url = q ? `/analytics/lessons_stats?${q}` : '/analytics/lessons_stats';
const res = await apiClient.get<AnalyticsLessonsStatsResponse>(url);
return res.data;
}
export async function getAnalyticsGradesByDay(range: AnalyticsDateRange): Promise<AnalyticsGradesByDayResponse> {
const q = buildParams(range);
const url = q ? `/analytics/grades_by_day?${q}` : '/analytics/grades_by_day';
const res = await apiClient.get<AnalyticsGradesByDayResponse>(url);
return res.data;
}