feat: завершить миграцию фронтенда на React (этапы 1-5)
Админка, настройки, логин, кабинеты преподавателя и студента полностью переведены на React 19 (модель strangler, docs/REACT_MIGRATION.md). - 15 вкладок админки: lazy-загрузка, общий error boundary, сервисный слой - Удалены legacy-views и переходный слой LegacyTabView (45 файлов) - Сборка esbuild (frontend/scripts/build-react.mjs) с бюджетами gzip на чанки - CSP-хэши, кэширование: chunk'и immutable, CSS/HTML no-cache (react-cache.conf) - Фиксы: lazy-импорт именованных экспортов (краш после авторизации), растяжение #admin-root/#settings-root на всю ширину, возврат subjects/lessonTypes из справочников (краш просмотра расписаний), отказ от заведомо широкого поиска расписания без выбранной цели, центрирование карточки логина - Тесты: 237/237 (npm run check), регрессионные на lazy-вкладки и ширину - Документация: REACT_MIGRATION.md, REACT_MIGRATION_RESULT.md, FRONTEND.md
This commit is contained in:
87
frontend/react/admin/classrooms-service.js
Normal file
87
frontend/react/admin/classrooms-service.js
Normal file
@@ -0,0 +1,87 @@
|
||||
import { apiClient } from '../shared/api-client.js';
|
||||
|
||||
export async function fetchEquipments(client = apiClient) {
|
||||
try {
|
||||
return await client.get('/api/equipments');
|
||||
} catch {
|
||||
console.error('Не удалось загрузить список оборудования');
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export function fetchClassrooms(client = apiClient) {
|
||||
return client.get(
|
||||
'/api/classrooms?includeArchived=true',
|
||||
{ errorMessage: 'Не удалось загрузить список аудиторий' }
|
||||
);
|
||||
}
|
||||
|
||||
export function createClassroom({ name, capacity, equipmentIds }, client = apiClient) {
|
||||
return client.post(
|
||||
'/api/classrooms',
|
||||
{ name, capacity, equipmentIds, isAvailable: true },
|
||||
{ errorMessage: 'Ошибка создания' }
|
||||
);
|
||||
}
|
||||
|
||||
export function updateClassroom(id, payload, client = apiClient) {
|
||||
return client.put(`/api/classrooms/${id}`, payload, { errorMessage: 'Ошибка обновления' });
|
||||
}
|
||||
|
||||
export function toggleClassroomAvailability(id, isAvailable, client = apiClient) {
|
||||
return updateClassroom(id, { isAvailable }, client);
|
||||
}
|
||||
|
||||
export function archiveClassroom(id, client = apiClient) {
|
||||
return client.delete(`/api/classrooms/${id}`, { errorMessage: 'Не удалось архивировать аудиторию' });
|
||||
}
|
||||
|
||||
export function restoreClassroom(id, client = apiClient) {
|
||||
return client.post(
|
||||
`/api/classrooms/${id}/restore`,
|
||||
{},
|
||||
{ errorMessage: 'Не удалось восстановить аудиторию' }
|
||||
);
|
||||
}
|
||||
|
||||
export function createEquipment(name, client = apiClient) {
|
||||
return client.post('/api/equipments', { name }, { errorMessage: 'Ошибка добавления' });
|
||||
}
|
||||
|
||||
export function deleteEquipment(id, client = apiClient) {
|
||||
return client.delete(`/api/equipments/${id}`, { errorMessage: 'Не удалось удалить оборудование' });
|
||||
}
|
||||
|
||||
export function parseCapacity(value) {
|
||||
return parseInt(value, 10);
|
||||
}
|
||||
|
||||
export function activeClassrooms(classrooms) {
|
||||
return (classrooms || []).filter(classroom => classroom.isAvailable && classroom.status !== 'ARCHIVED');
|
||||
}
|
||||
|
||||
export function classroomStatusLabel(classroom) {
|
||||
if (classroom.status === 'ARCHIVED') return 'Архив';
|
||||
return classroom.isAvailable ? 'Доступна' : 'Не доступна';
|
||||
}
|
||||
|
||||
export function equipmentNamesText(classroom) {
|
||||
const names = (classroom.equipments || []).map(equipment => equipment.name);
|
||||
return names.length ? names.join(', ') : null;
|
||||
}
|
||||
|
||||
export function equipmentSelectLabel(selectedNames) {
|
||||
const names = selectedNames || [];
|
||||
if (names.length === 0) return 'Выберите оборудование...';
|
||||
if (names.length === 1) return names[0];
|
||||
return `Выбрано: ${names.length}`;
|
||||
}
|
||||
|
||||
export function equipmentIdSelection(equipments, selectedIds) {
|
||||
const selected = new Set((selectedIds || []).map(String));
|
||||
return (equipments || []).map(equipment => ({
|
||||
id: equipment.id,
|
||||
name: equipment.name,
|
||||
checked: selected.has(String(equipment.id))
|
||||
}));
|
||||
}
|
||||
Reference in New Issue
Block a user