import { api } from '../api.js';
import { escapeHtml, showAlert, hideAlert } from '../utils.js';
export async function initSubjects() {
const subjectsTbody = document.getElementById('subjects-tbody');
const createSubjectForm = document.getElementById('create-subject-form');
const newSubjectDeptSelect = document.getElementById('new-subject-department');
// Модалка управления преподавателями
const modalManageTeachers = document.getElementById('modal-manage-teachers');
const modalManageTeachersClose = document.getElementById('modal-manage-teachers-close');
const subjectTeachersContext = document.getElementById('subject-teachers-context');
const manageTeacherSubjectForm = document.getElementById('manage-teacher-subject-form');
const manageTsSubjectIdInput = document.getElementById('manage-ts-subject-id');
const manageTsTeacherSelect = document.getElementById('manage-ts-teacher-select');
const manageTsTbody = document.getElementById('manage-ts-tbody');
let allSubjects = [];
let allTeachers = [];
let allDepartments = [];
let teacherSubjects = [];
bindEvents();
await loadInitialData();
function bindEvents() {
createSubjectForm.addEventListener('submit', createSubject);
subjectsTbody.addEventListener('click', handleSubjectsTableClick);
manageTeacherSubjectForm.addEventListener('submit', saveTeacherAssignment);
manageTsTbody.addEventListener('click', handleTeacherAssignmentTableClick);
modalManageTeachersClose.addEventListener('click', () => modalManageTeachers.classList.remove('open'));
modalManageTeachers.addEventListener('click', (e) => {
if (e.target === modalManageTeachers) modalManageTeachers.classList.remove('open');
});
}
async function loadInitialData() {
try {
[allTeachers, allDepartments] = await Promise.all([
api.get('/api/users/teachers'),
api.get('/api/departments')
]);
populateDepartmentsSelect();
await loadSubjects();
} catch (e) {
subjectsTbody.innerHTML = `
| Ошибка загрузки справочников: ${escapeHtml(e.message)} |
`;
}
}
function populateDepartmentsSelect() {
newSubjectDeptSelect.innerHTML = '' +
allDepartments.map(d => {
const name = d.departmentName || d.name || 'Без названия';
const code = d.departmentCode || d.code || d.id;
return ``;
}).join('');
}
async function loadSubjects() {
subjectsTbody.innerHTML = '| Загрузка... |
';
try {
[allSubjects, teacherSubjects] = await Promise.all([
api.get('/api/subjects'),
api.get('/api/teacher-subjects')
]);
renderSubjects();
} catch (e) {
subjectsTbody.innerHTML = `| Ошибка загрузки: ${escapeHtml(e.message)} |
`;
}
}
function renderSubjects() {
if (!allSubjects || !allSubjects.length) {
subjectsTbody.innerHTML = '| Нет дисциплин |
';
return;
}
// Группируем преподавателей по дисциплинам
const teachersBySubject = new Map();
teacherSubjects.forEach(ts => {
if (!teachersBySubject.has(ts.subjectId)) {
teachersBySubject.set(ts.subjectId, []);
}
teachersBySubject.get(ts.subjectId).push(ts);
});
subjectsTbody.innerHTML = allSubjects.map(s => {
const teachers = teachersBySubject.get(s.id) || [];
const teachersHtml = teachers.length
? teachers.map(t => `${escapeHtml(t.fullName || t.username)}`).join('')
: 'Нет преподавателей';
return `
| ${s.id} |
${escapeHtml(s.name)} |
${escapeHtml(s.code || '-')} |
${escapeHtml(departmentLabel(s.departmentId))} |
${teachersHtml} |
|
`;
}).join('');
}
async function createSubject(e) {
e.preventDefault();
hideAlert('create-subject-alert');
const name = document.getElementById('new-subject-name').value.trim();
const code = document.getElementById('new-subject-code').value.trim();
const departmentId = newSubjectDeptSelect.value;
if (!name || !code || !departmentId) {
showAlert('create-subject-alert', 'Заполните все поля', 'error');
return;
}
try {
const data = await api.post('/api/subjects', {
name,
code,
departmentId: Number(departmentId)
});
showAlert('create-subject-alert', `Дисциплина "${escapeHtml(data.name || name)}" создана`, 'success');
createSubjectForm.reset();
await loadSubjects();
} catch (error) {
showAlert('create-subject-alert', error.message || 'Ошибка создания', 'error');
}
}
async function handleSubjectsTableClick(e) {
const btnDelete = e.target.closest('.btn-delete-subject');
const btnTeachers = e.target.closest('.btn-manage-teachers');
if (btnDelete) {
if (!confirm('Удалить дисциплину? Это удалит её привязки к преподавателям.')) return;
try {
await api.delete('/api/subjects/' + btnDelete.dataset.id);
await loadSubjects();
} catch (error) {
alert(error.message || 'Ошибка удаления');
}
}
if (btnTeachers) {
const subjectId = btnTeachers.dataset.id;
const subject = allSubjects.find(s => s.id == subjectId);
if (subject) openTeachersModal(subject);
}
}
// --- Управление привязками преподавателей к дисциплине ---
function openTeachersModal(subject) {
subjectTeachersContext.textContent = `${subject.code ? `${subject.code} · ` : ''}${subject.name}`;
manageTsSubjectIdInput.value = subject.id;
hideAlert('manage-ts-alert');
modalManageTeachers.classList.add('open');
renderSubjectTeachers(subject.id);
populateTeachersSelect(subject.id);
}
function renderSubjectTeachers(subjectId) {
const list = teacherSubjects.filter(ts => String(ts.subjectId) === String(subjectId));
if (!list.length) {
manageTsTbody.innerHTML = '| Преподаватели не привязаны |
';
return;
}
manageTsTbody.innerHTML = list.map(ts => `
| ${escapeHtml(ts.fullName || ts.username)} (${escapeHtml(ts.username)}) |
|
`).join('');
}
function populateTeachersSelect(subjectId) {
// Показываем только тех преподавателей, которые еще не привязаны к этой дисциплине
const assignedUserIds = new Set(
teacherSubjects
.filter(ts => String(ts.subjectId) === String(subjectId))
.map(ts => String(ts.userId))
);
const availableTeachers = allTeachers.filter(t => !assignedUserIds.has(String(t.id)));
if (!availableTeachers.length) {
manageTsTeacherSelect.innerHTML = '';
return;
}
manageTsTeacherSelect.innerHTML = '' +
availableTeachers.map(t => ``).join('');
}
async function saveTeacherAssignment(e) {
e.preventDefault();
hideAlert('manage-ts-alert');
const subjectId = manageTsSubjectIdInput.value;
const userId = manageTsTeacherSelect.value;
if (!userId) {
showAlert('manage-ts-alert', 'Выберите преподавателя', 'error');
return;
}
try {
await api.post('/api/teacher-subjects', {
userId: Number(userId),
subjectId: Number(subjectId)
});
showAlert('manage-ts-alert', 'Преподаватель успешно привязан', 'success');
// Перезагрузим привязки и обновим интерфейс
teacherSubjects = await api.get('/api/teacher-subjects');
renderSubjectTeachers(subjectId);
populateTeachersSelect(subjectId);
// Также обновим главную таблицу
renderSubjects();
} catch (error) {
showAlert('manage-ts-alert', error.message || 'Ошибка привязки', 'error');
}
}
async function handleTeacherAssignmentTableClick(e) {
const btnDelete = e.target.closest('.btn-delete-ts');
if (!btnDelete) return;
if (!confirm('Удалить привязку преподавателя?')) return;
const subjectId = manageTsSubjectIdInput.value;
try {
await api.delete('/api/teacher-subjects', {
userId: Number(btnDelete.dataset.userId),
subjectId: Number(btnDelete.dataset.subjectId)
});
// Перезагрузим привязки
teacherSubjects = await api.get('/api/teacher-subjects');
renderSubjectTeachers(subjectId);
populateTeachersSelect(subjectId);
// Обновим главную таблицу
renderSubjects();
} catch (error) {
alert(error.message || 'Ошибка удаления привязки');
}
}
// --- Вспомогательные функции ---
function departmentLabel(departmentId) {
const department = allDepartments.find(item => item.id == departmentId);
if (!department) return departmentId || '-';
return department.departmentName || department.name || departmentId;
}
}