Files
magistr/frontend/react/admin/classrooms-service.js
dipatrik10 97bf3cc50a 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
2026-09-28 23:15:04 +03:00

88 lines
3.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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))
}));
}