import { api } from '../api.js'; import { escapeHtml, showAlert, hideAlert, initMultiSelect, updateSelectText } from '../utils.js'; async function fetchEquipments() { try { return await api.get('/api/equipments'); } catch (e) { console.error("Failed to fetch equipments", e); return []; } } function renderEquipmentCheckboxes(equipments, containerId, selectTextId, selectedIds = []) { const container = document.getElementById(containerId); if (!container) return; if (!equipments || !equipments.length) { container.innerHTML = '

Оборудование отсутствует

'; updateSelectText(containerId, selectTextId); return; } container.innerHTML = equipments.map(eq => ` `).join(''); updateSelectText(containerId, selectTextId); } export async function initClassrooms() { const classroomsTbody = document.getElementById('classrooms-tbody'); const createClassroomForm = document.getElementById('create-classroom-form'); const equipmentCheckboxes = document.getElementById('equipment-checkboxes'); const editEquipmentCheckboxes = document.getElementById('edit-equipment-checkboxes'); const modalEditClassroom = document.getElementById('modal-edit-classroom'); const modalEditClassroomClose = document.getElementById('modal-edit-classroom-close'); const editClassroomForm = document.getElementById('edit-classroom-form'); let allEquipments = []; let editingClassroomData = null; initMultiSelect('equipment-select-box', 'equipment-dropdown-menu', 'equipment-select-text', 'equipment-checkboxes'); initMultiSelect('edit-equipment-select-box', 'edit-equipment-dropdown-menu', 'edit-equipment-select-text', 'edit-equipment-checkboxes'); async function loadInitialData() { try { allEquipments = await fetchEquipments(); renderEquipmentCheckboxes(allEquipments, 'equipment-checkboxes', 'equipment-select-text'); await loadClassrooms(); } catch (e) { classroomsTbody.innerHTML = 'Ошибка загрузки данных'; } } async function loadClassrooms() { try { const classrooms = await api.get('/api/classrooms?includeArchived=true'); renderClassrooms(classrooms); } catch (e) { classroomsTbody.innerHTML = 'Ошибка загрузки'; } } function renderClassrooms(classrooms) { if (!classrooms || !classrooms.length) { classroomsTbody.innerHTML = 'Нет аудиторий'; return; } classroomsTbody.innerHTML = classrooms.map(c => { const equipHtml = c.equipments && c.equipments.length ? c.equipments.map(eq => escapeHtml(eq.name)).join(', ') : '—'; return ` ${c.id} ${escapeHtml(c.name)} ${c.capacity} чел. ${equipHtml}
${c.status === 'ARCHIVED' ? 'Архив' : (c.isAvailable ? 'Доступна' : 'Не доступна')}
${c.status === 'ARCHIVED' ? `` : ``} `; }).join(''); } createClassroomForm.addEventListener('submit', async (e) => { e.preventDefault(); hideAlert('create-classroom-alert'); const name = document.getElementById('new-classroom-name').value.trim(); const capacity = parseInt(document.getElementById('new-classroom-capacity').value, 10); const checkedBoxes = Array.from(equipmentCheckboxes.querySelectorAll('input:checked')); const equipmentIds = checkedBoxes.map(chk => parseInt(chk.value, 10)); if (!name || isNaN(capacity)) { showAlert('create-classroom-alert', 'Заполните обязательные поля', 'error'); return; } try { const data = await api.post('/api/classrooms', { name, capacity, equipmentIds, isAvailable: true }); showAlert('create-classroom-alert', `Аудитория "${escapeHtml(data.name)}" добавлена`, 'success'); createClassroomForm.reset(); updateSelectText('equipment-checkboxes', 'equipment-select-text'); loadClassrooms(); } catch (e) { showAlert('create-classroom-alert', e.message || 'Ошибка создания', 'error'); } }); classroomsTbody.addEventListener('click', async (e) => { const btnDelete = e.target.closest('.btn-archive-classroom'); const btnToggleStatus = e.target.closest('.btn-icon-toggle'); const btnEdit = e.target.closest('.classroom-edit-action'); if (btnDelete) { if (!confirm('Вывести аудиторию из эксплуатации? Историческое расписание сохранится.')) return; try { await api.delete('/api/classrooms/' + btnDelete.dataset.id); loadClassrooms(); } catch (err) { alert('Ошибка архивирования'); } } const btnRestore = e.target.closest('.btn-restore-classroom'); if (btnRestore) { try { await api.post('/api/classrooms/' + btnRestore.dataset.id + '/restore', {}); loadClassrooms(); } catch (err) { alert('Ошибка восстановления аудитории'); } } if (btnToggleStatus) { const id = btnToggleStatus.dataset.id; const currentStatus = btnToggleStatus.dataset.currentStatus === 'true'; try { await api.put('/api/classrooms/' + id, { isAvailable: !currentStatus }); loadClassrooms(); } catch (err) { alert('Ошибка изменения статуса'); } } if (btnEdit) { openEditClassroomModal(btnEdit.dataset.id); } }); async function openEditClassroomModal(id) { try { // Can optimize by using already loaded classrooms, but fetch is safer to get fresh data const classrooms = await api.get('/api/classrooms?includeArchived=true'); editingClassroomData = classrooms.find(c => c.id == id); if (!editingClassroomData) return; document.getElementById('edit-classroom-id').value = editingClassroomData.id; document.getElementById('edit-classroom-name').value = editingClassroomData.name; document.getElementById('edit-classroom-capacity').value = editingClassroomData.capacity; const existingEquipIds = editingClassroomData.equipments.map(e => e.id); renderEquipmentCheckboxes(allEquipments, 'edit-equipment-checkboxes', 'edit-equipment-select-text', existingEquipIds); hideAlert('edit-classroom-alert'); modalEditClassroom.classList.add('open'); } catch (e) { alert('Ошибка загрузки данных аудитории'); } } modalEditClassroomClose.addEventListener('click', () => { modalEditClassroom.classList.remove('open'); }); modalEditClassroom.addEventListener('click', (e) => { if (e.target === modalEditClassroom) { modalEditClassroom.classList.remove('open'); } }); editClassroomForm.addEventListener('submit', async (e) => { e.preventDefault(); hideAlert('edit-classroom-alert'); const id = document.getElementById('edit-classroom-id').value; const name = document.getElementById('edit-classroom-name').value.trim(); const capacity = parseInt(document.getElementById('edit-classroom-capacity').value, 10); const checkedBoxes = Array.from(editEquipmentCheckboxes.querySelectorAll('input:checked')); const equipmentIds = checkedBoxes.map(chk => parseInt(chk.value, 10)); if (!name || isNaN(capacity)) { showAlert('edit-classroom-alert', 'Заполните обязательные поля', 'error'); return; } try { const data = await api.put('/api/classrooms/' + id, { name, capacity, equipmentIds, isAvailable: editingClassroomData.isAvailable }); modalEditClassroom.classList.remove('open'); // We show alert on the main create form area or we could use toast showAlert('create-classroom-alert', `Аудитория "${escapeHtml(data.name)}" обновлена`, 'success'); loadClassrooms(); } catch (e) { showAlert('edit-classroom-alert', e.message || 'Ошибка обновления', 'error'); } }); // Элементы модалки оборудования const btnManageEquipments = document.getElementById('btn-manage-equipments'); const modalManageEquipments = document.getElementById('modal-manage-equipments'); const modalManageEquipmentsClose = document.getElementById('modal-manage-equipments-close'); const manageEquipmentForm = document.getElementById('manage-equipment-form'); const manageEquipmentNameInput = document.getElementById('manage-equipment-name'); const manageEquipmentTbody = document.getElementById('manage-equipments-tbody'); btnManageEquipments.addEventListener('click', openManageEquipmentsModal); modalManageEquipmentsClose.addEventListener('click', () => modalManageEquipments.classList.remove('open')); modalManageEquipments.addEventListener('click', (e) => { if (e.target === modalManageEquipments) modalManageEquipments.classList.remove('open'); }); async function openManageEquipmentsModal() { hideAlert('manage-equipment-alert'); manageEquipmentForm.reset(); modalManageEquipments.classList.add('open'); await loadManageEquipments(); } async function loadManageEquipments() { manageEquipmentTbody.innerHTML = 'Загрузка...'; try { allEquipments = await fetchEquipments(); renderManageEquipmentsTable(); // Обновим чекбоксы на основной странице renderEquipmentCheckboxes(allEquipments, 'equipment-checkboxes', 'equipment-select-text'); } catch (e) { manageEquipmentTbody.innerHTML = 'Ошибка загрузки'; } } function renderManageEquipmentsTable() { if (!allEquipments || !allEquipments.length) { manageEquipmentTbody.innerHTML = 'Нет оборудования'; return; } manageEquipmentTbody.innerHTML = allEquipments.map(eq => ` ${eq.id} ${escapeHtml(eq.name)} `).join(''); } manageEquipmentForm.addEventListener('submit', async (e) => { e.preventDefault(); hideAlert('manage-equipment-alert'); const name = manageEquipmentNameInput.value.trim(); if (!name) { showAlert('manage-equipment-alert', 'Введите название', 'error'); return; } try { const data = await api.post('/api/equipments', { name }); showAlert('manage-equipment-alert', `Оборудование "${escapeHtml(data.name)}" добавлено`, 'success'); manageEquipmentForm.reset(); await loadManageEquipments(); } catch (err) { showAlert('manage-equipment-alert', err.message || 'Ошибка добавления', 'error'); } }); manageEquipmentTbody.addEventListener('click', async (e) => { const btnDelete = e.target.closest('.btn-delete-equipment'); if (!btnDelete) return; if (!confirm('Удалить оборудование из каталога?')) return; try { await api.delete('/api/equipments/' + btnDelete.dataset.id); await loadManageEquipments(); } catch (err) { alert(err.message || 'Ошибка удаления'); } }); loadInitialData(); }