/** * API модуль для материалов */ import apiClient from '@/lib/api-client'; export interface Material { id: number; title: string; description?: string; file?: string; file_url?: string; // полный URL для превью (изображения, видео) file_type?: string; file_name?: string; file_size?: number; material_type?: 'image' | 'video' | 'audio' | 'document' | 'presentation' | 'archive' | 'other'; category?: number; category_name?: string; mentor?: number; owner?: { id: number; first_name?: string; last_name?: string; email?: string }; is_public?: boolean; created_at?: string; updated_at?: string; shared_with?: { id: number; first_name?: string; last_name?: string; email?: string }[]; } export interface MaterialCategory { id: number; name: string; description?: string; } export interface PaginatedResponse { count: number; next: string | null; previous: string | null; results: T[]; } /** * Получить список материалов */ export async function getMaterials(params?: { page?: number; page_size?: number; category?: number; search?: string; mentor?: number; }): Promise> { const response = await apiClient.get>('/materials/materials/', { params, }); return response.data; } /** * Получить материал по ID */ export async function getMaterialById(id: number): Promise { const response = await apiClient.get(`/materials/materials/${id}/`); return response.data; } /** * Создать материал */ export async function createMaterial( data: { title: string; description?: string; file?: File; category?: number; is_public?: boolean; } ): Promise { const formData = new FormData(); formData.append('title', data.title); if (data.description) { formData.append('description', data.description); } if (data.file) { formData.append('file', data.file); } if (data.category) { formData.append('category', data.category.toString()); } if (data.is_public !== undefined) { formData.append('is_public', data.is_public.toString()); } const response = await apiClient.post('/materials/materials/', formData, { headers: { 'Content-Type': 'multipart/form-data', }, }); return response.data; } /** * Обновить материал */ export async function updateMaterial( id: number, data: Partial<{ title: string; description: string; file: File; category: number; is_public: boolean; }> ): Promise { const formData = new FormData(); if (data.title) formData.append('title', data.title); if (data.description !== undefined) formData.append('description', data.description); if (data.file) formData.append('file', data.file); if (data.category) formData.append('category', data.category.toString()); if (data.is_public !== undefined) { formData.append('is_public', data.is_public.toString()); } const response = await apiClient.patch(`/materials/materials/${id}/`, formData, { headers: { 'Content-Type': 'multipart/form-data', }, }); return response.data; } /** * Удалить материал */ export async function deleteMaterial(id: number): Promise { await apiClient.delete(`/materials/materials/${id}/`); } /** * Предоставить доступ к материалу */ export async function shareMaterial(id: number, userIds: string[]): Promise { await apiClient.post(`/materials/materials/${id}/share/`, { user_ids: userIds, }); } /** * Получить категории материалов */ export async function getMaterialCategories(): Promise { const response = await apiClient.get('/materials/categories/'); return response.data; } /** * Мои материалы (для экрана завершения занятия — привязка к ДЗ). */ export async function getMyMaterials(): Promise { const response = await apiClient.get>( '/materials/materials/my_materials/' ); const data = response.data; if (Array.isArray(data)) return data; return (data as PaginatedResponse)?.results ?? []; }