import { api } from '../api.js'; import { escapeHtml, showAlert, hideAlert } from '../utils.js'; const ROLE_DEPARTMENT = 'DEPARTMENT'; export async function initDepartmentWorkspace() { const role = localStorage.getItem('role'); const userDepartmentId = localStorage.getItem('departmentId'); const departmentField = document.getElementById('department-workspace-department-field'); const departmentSelect = document.getElementById('department-workspace-department'); const startInput = document.getElementById('department-workspace-start'); const endInput = document.getElementById('department-workspace-end'); const refreshButton = document.getElementById('department-workspace-refresh'); const importForm = document.getElementById('department-subject-import-form'); const subjectsTbody = document.getElementById('department-subjects-tbody'); const subjectCount = document.getElementById('department-subject-count'); const commentsCard = document.getElementById('department-comments-card'); const commentsTitle = document.getElementById('department-comments-title'); const commentsList = document.getElementById('department-comment-list'); const commentsForm = document.getElementById('department-comment-form'); const commentsSubjectInput = document.getElementById('department-comment-subject-id'); const commentsTextInput = document.getElementById('department-comment-text'); const commentsCloseButton = document.getElementById('department-comments-close'); setDefaultDates(startInput, endInput); refreshButton?.addEventListener('click', loadWorkspace); departmentSelect?.addEventListener('change', loadWorkspace); startInput?.addEventListener('change', loadWorkload); endInput?.addEventListener('change', loadWorkload); importForm?.addEventListener('submit', importSubjects); commentsForm?.addEventListener('submit', saveComment); commentsCloseButton?.addEventListener('click', () => { commentsCard.hidden = true; commentsSubjectInput.value = ''; }); subjectsTbody?.addEventListener('click', event => { const button = event.target.closest('.department-comments-open'); if (button) { openComments(button.dataset.subjectId, button.dataset.subjectName); } }); try { await loadDepartments(role, userDepartmentId); if (role === ROLE_DEPARTMENT) { departmentField.hidden = true; departmentSelect.value = userDepartmentId || ''; } await loadWorkspace(); } catch (error) { showAlert('department-workspace-alert', error.message || 'Ошибка загрузки кабинета кафедры', 'error'); } async function loadWorkspace() { hideAlert('department-workspace-alert'); await Promise.all([loadSubjects(), loadTeachers(), loadWorkload()]); } async function loadSubjects() { const departmentId = selectedDepartmentId(); subjectsTbody.innerHTML = 'Загрузка...'; subjectCount.textContent = 'Загрузка...'; try { const subjects = await api.get(`/api/department/subjects?departmentId=${encodeURIComponent(departmentId || '')}`); subjectCount.textContent = subjectCountLabel(subjects.length); if (!subjects.length) { subjectsTbody.innerHTML = 'Дисциплины не найдены'; return; } subjectsTbody.innerHTML = subjects.map(subject => ` ${escapeHtml(subject.code || '-')} ${escapeHtml(subject.name || '-')} ${escapeHtml(subject.description || '-')} `).join(''); } catch (error) { subjectsTbody.innerHTML = `${escapeHtml(error.message || 'Ошибка загрузки дисциплин')}`; subjectCount.textContent = '0 дисциплин'; } } async function importSubjects(event) { event.preventDefault(); const alertId = 'department-subject-import-alert'; hideAlert(alertId); const departmentId = selectedDepartmentId(); const rows = document.getElementById('department-subject-import-text').value .split('\n') .map(row => row.trim()) .filter(Boolean) .map(row => { const [code, ...nameParts] = row.split(';'); return { code: (code || '').trim(), name: nameParts.join(';').trim(), departmentId: Number(departmentId) }; }) .filter(item => item.name); if (!departmentId) { showAlert(alertId, 'Выберите кафедру', 'error'); return; } if (!rows.length) { showAlert(alertId, 'Добавьте хотя бы одну строку в формате «код; название»', 'error'); return; } try { const result = await api.post('/api/department/subjects/import', rows); showAlert(alertId, result.message || 'Дисциплины загружены', 'success'); document.getElementById('department-subject-import-text').value = ''; await loadSubjects(); } catch (error) { showAlert(alertId, error.message || 'Ошибка загрузки дисциплин', 'error'); } } async function openComments(subjectId, subjectName) { commentsCard.hidden = false; commentsTitle.textContent = `Комментарии: ${subjectName || 'дисциплина'}`; commentsSubjectInput.value = subjectId; commentsTextInput.value = ''; hideAlert('department-comment-alert'); commentsList.textContent = 'Загрузка...'; try { const comments = await api.get(`/api/department/subjects/${subjectId}/comments`); commentsList.innerHTML = comments.length ? comments.map(comment => `
${escapeHtml(comment.authorName || 'Автор не указан')} ${escapeHtml(formatDateTime(comment.createdAt))}

${escapeHtml(comment.comment)}

`).join('') : '
Комментариев пока нет
'; } catch (error) { commentsList.innerHTML = `
${escapeHtml(error.message || 'Ошибка загрузки комментариев')}
`; } } async function saveComment(event) { event.preventDefault(); const subjectId = commentsSubjectInput.value; const comment = commentsTextInput.value.trim(); if (!subjectId) { showAlert('department-comment-alert', 'Выберите дисциплину', 'error'); return; } if (!comment) { showAlert('department-comment-alert', 'Комментарий не должен быть пустым', 'error'); return; } try { await api.post(`/api/department/subjects/${subjectId}/comments`, { comment }); showAlert('department-comment-alert', 'Комментарий сохранён', 'success'); await openComments(subjectId, commentsTitle.textContent.replace('Комментарии: ', '')); } catch (error) { showAlert('department-comment-alert', error.message || 'Ошибка сохранения комментария', 'error'); } } async function loadTeachers() { const container = document.getElementById('department-teachers-list'); container.textContent = 'Загрузка...'; try { const teachers = await api.get(`/api/department/teachers?departmentId=${encodeURIComponent(selectedDepartmentId() || '')}`); container.innerHTML = teachers.length ? teachers.map(teacher => `
${escapeHtml(teacher.fullName || teacher.username || '-')} ${escapeHtml(teacher.jobTitle || 'Должность не указана')}
`).join('') : '
Преподаватели не найдены
'; } catch (error) { container.innerHTML = `
${escapeHtml(error.message || 'Ошибка загрузки преподавателей')}
`; } } async function loadWorkload() { const container = document.getElementById('department-workload-list'); const params = new URLSearchParams({ startDate: startInput.value, endDate: endInput.value }); if (selectedDepartmentId()) { params.set('departmentId', selectedDepartmentId()); } container.textContent = 'Загрузка...'; try { const workload = await api.get(`/api/workload/teachers?${params}`); container.innerHTML = workload.length ? workload.map(item => `
${escapeHtml(item.name || '-')} ${escapeHtml(String(item.academicHours ?? 0))} ак. ч. ${escapeHtml(String(item.lessonCount ?? 0))} занятий
`).join('') : '
Нагрузка не найдена
'; } catch (error) { container.innerHTML = `
${escapeHtml(error.message || 'Ошибка расчёта нагрузки')}
`; } } function selectedDepartmentId() { return role === ROLE_DEPARTMENT ? userDepartmentId : departmentSelect.value; } } async function loadDepartments(role, userDepartmentId) { const departments = await api.get('/api/departments'); fillSelect('department-workspace-department', departments, item => item.id, item => item.departmentName, 'Выберите кафедру'); if (role === ROLE_DEPARTMENT && userDepartmentId) { document.getElementById('department-workspace-department').value = userDepartmentId; } else if (!document.getElementById('department-workspace-department').value && departments.length) { document.getElementById('department-workspace-department').value = departments[0].id; } } function fillSelect(id, items, valueFn, labelFn, emptyLabel) { const select = document.getElementById(id); if (!select) return; select.innerHTML = `` + (items || []).map(item => ``).join(''); } function setDefaultDates(startInput, endInput) { const today = new Date(); const nextWeek = new Date(); nextWeek.setDate(today.getDate() + 7); startInput.value = toIsoDate(today); endInput.value = toIsoDate(nextWeek); } function toIsoDate(date) { return date.toISOString().slice(0, 10); } function formatDateTime(value) { if (!value) return '-'; return String(value).replace('T', ' ').slice(0, 16); } function subjectCountLabel(count) { const tail = count % 100; if (tail >= 11 && tail <= 14) return `${count} дисциплин`; if (count % 10 === 1) return `${count} дисциплина`; if ([2, 3, 4].includes(count % 10)) return `${count} дисциплины`; return `${count} дисциплин`; }