281 lines
8.5 KiB
TypeScript
281 lines
8.5 KiB
TypeScript
/**
|
||
* API модуль для студентов
|
||
*/
|
||
|
||
import apiClient from '@/lib/api-client';
|
||
|
||
export interface Student {
|
||
id: string | number;
|
||
user: {
|
||
id: string;
|
||
email: string;
|
||
first_name: string;
|
||
last_name: string;
|
||
avatar?: string;
|
||
avatar_url?: string | null;
|
||
};
|
||
grade?: string;
|
||
school?: string;
|
||
learning_goals?: string;
|
||
total_lessons?: number;
|
||
completed_lessons?: number;
|
||
scheduled_lessons?: number;
|
||
enrollment_date?: string;
|
||
}
|
||
|
||
export interface PaginatedResponse<T> {
|
||
count: number;
|
||
next: string | null;
|
||
previous: string | null;
|
||
results: T[];
|
||
}
|
||
|
||
/**
|
||
* Получить список студентов (клиентов)
|
||
* Использует эндпоинт для менторов: /api/manage/clients/
|
||
*/
|
||
export async function getStudents(params?: {
|
||
page?: number;
|
||
page_size?: number;
|
||
search?: string;
|
||
}): Promise<PaginatedResponse<Student>> {
|
||
const response = await apiClient.get<PaginatedResponse<Student>>('/manage/clients/', {
|
||
params,
|
||
});
|
||
return response.data;
|
||
}
|
||
|
||
/**
|
||
* Получить студента по ID
|
||
*/
|
||
export async function getStudentById(id: number): Promise<Student> {
|
||
const response = await apiClient.get<Student>(`/users/clients/${id}/`);
|
||
return response.data;
|
||
}
|
||
|
||
/**
|
||
* Создать студента
|
||
*/
|
||
export async function createStudent(data: {
|
||
email: string;
|
||
first_name?: string;
|
||
last_name?: string;
|
||
phone?: string;
|
||
}): Promise<Student> {
|
||
const response = await apiClient.post<Student>('/users/clients/', data);
|
||
return response.data;
|
||
}
|
||
|
||
/**
|
||
* Обновить студента
|
||
*/
|
||
export async function updateStudent(id: number, data: Partial<Student>): Promise<Student> {
|
||
const response = await apiClient.patch<Student>(`/users/clients/${id}/`, data);
|
||
return response.data;
|
||
}
|
||
|
||
/**
|
||
* Удалить студента
|
||
*/
|
||
export async function deleteStudent(id: number): Promise<void> {
|
||
await apiClient.delete(`/users/clients/${id}/`);
|
||
}
|
||
|
||
/**
|
||
* Проверить пользователя по email (для ментора): зарегистрирован ли, является ли клиентом.
|
||
*/
|
||
export async function checkUserByEmail(email: string): Promise<{ exists: boolean; is_client: boolean }> {
|
||
const response = await apiClient.get<{ exists: boolean; is_client: boolean }>(
|
||
'/manage/clients/check-user/',
|
||
{ params: { email: email.trim().toLowerCase() } }
|
||
);
|
||
return response.data;
|
||
}
|
||
|
||
/**
|
||
* Отправить приглашение студенту (по email или 8-символьному коду).
|
||
*/
|
||
export async function addStudentInvitation(payload: {
|
||
email?: string;
|
||
universal_code?: string;
|
||
}): Promise<{ status: string; message: string; invitation_id?: number }> {
|
||
const response = await apiClient.post<{ status: string; message: string; invitation_id?: number }>(
|
||
'/manage/clients/add_client/',
|
||
payload
|
||
);
|
||
return response.data;
|
||
}
|
||
|
||
/** Запрос на менторство (студент → ментор) / связь ментор—студент */
|
||
export interface MentorshipRequestItem {
|
||
id: number;
|
||
status: 'pending_mentor' | 'pending_student' | 'pending_parent' | 'accepted' | 'rejected' | 'pending';
|
||
created_at: string | null;
|
||
student: {
|
||
id: number | null;
|
||
user_id: number;
|
||
email: string;
|
||
first_name: string;
|
||
last_name: string;
|
||
avatar?: string | null;
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Получить ожидающие запросы на менторство (для ментора).
|
||
*/
|
||
export async function getMentorshipRequestsPending(): Promise<MentorshipRequestItem[]> {
|
||
const response = await apiClient.get<MentorshipRequestItem[]>(
|
||
'/mentorship-requests/pending/'
|
||
);
|
||
return response.data;
|
||
}
|
||
|
||
/**
|
||
* Принять запрос на менторство.
|
||
*/
|
||
export async function acceptMentorshipRequest(id: number): Promise<{ status: string; message: string }> {
|
||
const response = await apiClient.post<{ status: string; message: string }>(
|
||
`/mentorship-requests/${id}/accept/`
|
||
);
|
||
return response.data;
|
||
}
|
||
|
||
/**
|
||
* Отклонить запрос на менторство.
|
||
*/
|
||
export async function rejectMentorshipRequest(id: number): Promise<{ status: string; message: string }> {
|
||
const response = await apiClient.post<{ status: string; message: string }>(
|
||
`/mentorship-requests/${id}/reject/`
|
||
);
|
||
return response.data;
|
||
}
|
||
|
||
/**
|
||
* Отправить запрос на менторство (студент → ментор по коду).
|
||
*/
|
||
export async function sendMentorshipRequest(mentorCode: string): Promise<{
|
||
id: number;
|
||
status: string;
|
||
mentor: { id: number; first_name: string; last_name: string; email: string };
|
||
message: string;
|
||
}> {
|
||
const response = await apiClient.post(
|
||
'/mentorship-requests/send/',
|
||
{ mentor_code: mentorCode.trim().toUpperCase() }
|
||
);
|
||
return response.data;
|
||
}
|
||
|
||
/**
|
||
* Получить список своих отправленных запросов (для студента).
|
||
*/
|
||
export async function getMyMentorshipRequests(): Promise<Array<{
|
||
id: number;
|
||
status: string;
|
||
created_at: string | null;
|
||
updated_at: string | null;
|
||
mentor: { id: number; email: string; first_name: string; last_name: string };
|
||
}>> {
|
||
const response = await apiClient.get('/mentorship-requests/my-requests/');
|
||
return response.data;
|
||
}
|
||
|
||
/** Ментор из client.mentors (подключённый) */
|
||
export interface MyMentor {
|
||
id: number;
|
||
email: string;
|
||
first_name: string;
|
||
last_name: string;
|
||
avatar_url?: string | null;
|
||
}
|
||
|
||
/**
|
||
* Получить список подключённых менторов студента (включая из приглашений).
|
||
*/
|
||
export async function getMyMentors(): Promise<MyMentor[]> {
|
||
const response = await apiClient.get<MyMentor[]>('/mentorship-requests/my-mentors/');
|
||
return response.data;
|
||
}
|
||
|
||
/** Входящее приглашение от ментора (MentorClientInvitation) */
|
||
export interface MentorInvitation {
|
||
id: number;
|
||
mentor: { id: number; email: string; first_name: string; last_name: string };
|
||
student: { id: number; email: string } | null;
|
||
status: string;
|
||
created_at: string | null;
|
||
student_confirmed_at: string | null;
|
||
}
|
||
|
||
/**
|
||
* Получить входящие приглашения от менторов (для студента).
|
||
*/
|
||
export async function getMyInvitations(): Promise<MentorInvitation[]> {
|
||
const response = await apiClient.get<MentorInvitation[]>('/invitation/my-invitations/');
|
||
return response.data;
|
||
}
|
||
|
||
/**
|
||
* Подтвердить приглашение от ментора (студент принимает).
|
||
*/
|
||
export async function confirmInvitationAsStudent(invitationId: number): Promise<{ status: string; requires_parent?: boolean }> {
|
||
const response = await apiClient.post<{ status: string; requires_parent?: boolean }>(
|
||
'/invitation/confirm-as-student/',
|
||
{ invitation_id: invitationId }
|
||
);
|
||
return response.data;
|
||
}
|
||
|
||
/**
|
||
* Отклонить приглашение от ментора (студент отклоняет).
|
||
*/
|
||
export async function rejectInvitationAsStudent(invitationId: number): Promise<{ status: string }> {
|
||
const response = await apiClient.post<{ status: string }>(
|
||
'/invitation/reject-as-student/',
|
||
{ invitation_id: invitationId }
|
||
);
|
||
return response.data;
|
||
}
|
||
|
||
/**
|
||
* Сгенерировать или обновить ссылку-приглашение
|
||
*/
|
||
export async function generateInvitationLink(): Promise<{
|
||
invitation_link_token: string;
|
||
invitation_link: string;
|
||
}> {
|
||
const response = await apiClient.post<{
|
||
invitation_link_token: string;
|
||
invitation_link: string;
|
||
}>('/manage/clients/generate-invitation-link/');
|
||
return response.data;
|
||
}
|
||
|
||
/**
|
||
* Получить информацию о менторе по токену
|
||
*/
|
||
export async function getMentorInfoByToken(token: string): Promise<{
|
||
mentor_name: string;
|
||
mentor_id: string;
|
||
avatar_url: string | null;
|
||
}> {
|
||
const response = await apiClient.get(`/invitation/info-by-token/?token=${token}`);
|
||
return response.data;
|
||
}
|
||
|
||
/**
|
||
* Регистрация по ссылке
|
||
*/
|
||
export async function registerByLink(data: {
|
||
token: string;
|
||
first_name: string;
|
||
last_name: string;
|
||
email?: string;
|
||
timezone?: string;
|
||
city?: string;
|
||
}): Promise<any> {
|
||
const response = await apiClient.post('/invitation/register-by-link/', data);
|
||
return response.data;
|
||
}
|