164 lines
4.5 KiB
TypeScript
164 lines
4.5 KiB
TypeScript
/**
|
|
* 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<T> {
|
|
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<PaginatedResponse<Material>> {
|
|
const response = await apiClient.get<PaginatedResponse<Material>>('/materials/materials/', {
|
|
params,
|
|
});
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Получить материал по ID
|
|
*/
|
|
export async function getMaterialById(id: number): Promise<Material> {
|
|
const response = await apiClient.get<Material>(`/materials/materials/${id}/`);
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Создать материал
|
|
*/
|
|
export async function createMaterial(
|
|
data: {
|
|
title: string;
|
|
description?: string;
|
|
file?: File;
|
|
category?: number;
|
|
is_public?: boolean;
|
|
}
|
|
): Promise<Material> {
|
|
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<Material>('/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<Material> {
|
|
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<Material>(`/materials/materials/${id}/`, formData, {
|
|
headers: {
|
|
'Content-Type': 'multipart/form-data',
|
|
},
|
|
});
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Удалить материал
|
|
*/
|
|
export async function deleteMaterial(id: number): Promise<void> {
|
|
await apiClient.delete(`/materials/materials/${id}/`);
|
|
}
|
|
|
|
/**
|
|
* Предоставить доступ к материалу
|
|
*/
|
|
export async function shareMaterial(id: number, userIds: string[]): Promise<void> {
|
|
await apiClient.post(`/materials/materials/${id}/share/`, {
|
|
user_ids: userIds,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Получить категории материалов
|
|
*/
|
|
export async function getMaterialCategories(): Promise<MaterialCategory[]> {
|
|
const response = await apiClient.get<MaterialCategory[]>('/materials/categories/');
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Мои материалы (для экрана завершения занятия — привязка к ДЗ).
|
|
*/
|
|
export async function getMyMaterials(): Promise<Material[]> {
|
|
const response = await apiClient.get<Material[] | PaginatedResponse<Material>>(
|
|
'/materials/materials/my_materials/'
|
|
);
|
|
const data = response.data;
|
|
if (Array.isArray(data)) return data;
|
|
return (data as PaginatedResponse<Material>)?.results ?? [];
|
|
}
|