154 lines
6.5 KiB
JavaScript
154 lines
6.5 KiB
JavaScript
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 assignTeacherForm = document.getElementById('assign-teacher-form');
|
|
const assignTeacherSelect = document.getElementById('assign-teacher-select');
|
|
const assignSubjectSelect = document.getElementById('assign-subject-select');
|
|
const teacherSubjectsTbody = document.getElementById('teacher-subjects-tbody');
|
|
|
|
let allSubjects = [];
|
|
let allTeachers = [];
|
|
|
|
async function loadInitialData() {
|
|
await Promise.all([loadSubjects(), loadTeachers()]);
|
|
await loadTeacherSubjects();
|
|
}
|
|
|
|
async function loadSubjects() {
|
|
try {
|
|
allSubjects = await api.get('/api/subjects');
|
|
renderSubjects(allSubjects);
|
|
populateSubjectSelect(allSubjects);
|
|
} catch (e) {
|
|
if (subjectsTbody) subjectsTbody.innerHTML = '<tr><td colspan="3" class="loading-row">Ошибка загрузки</td></tr>';
|
|
}
|
|
}
|
|
|
|
function renderSubjects(subjects) {
|
|
if (!subjects || !subjects.length) {
|
|
subjectsTbody.innerHTML = '<tr><td colspan="3" class="loading-row">Нет дисциплин</td></tr>';
|
|
return;
|
|
}
|
|
subjectsTbody.innerHTML = subjects.map(s => `
|
|
<tr>
|
|
<td>${s.id}</td>
|
|
<td>${escapeHtml(s.name)}</td>
|
|
<td><button class="btn-delete" data-id="${s.id}">Удалить</button></td>
|
|
</tr>`).join('');
|
|
}
|
|
|
|
function populateSubjectSelect(subjects) {
|
|
if (!assignSubjectSelect) return;
|
|
const currentVal = assignSubjectSelect.value;
|
|
assignSubjectSelect.innerHTML = '<option value="">Выберите дисциплину</option>' +
|
|
subjects.map(s => `<option value="${s.id}">${escapeHtml(s.name)}</option>`).join('');
|
|
if (currentVal && subjects.find(s => s.id == currentVal)) {
|
|
assignSubjectSelect.value = currentVal;
|
|
}
|
|
}
|
|
|
|
async function loadTeachers() {
|
|
try {
|
|
allTeachers = await api.get('/api/users/teachers');
|
|
populateTeacherSelect(allTeachers);
|
|
} catch (e) {
|
|
if (assignTeacherSelect) assignTeacherSelect.innerHTML = '<option value="">Ошибка загрузки</option>';
|
|
}
|
|
}
|
|
|
|
function populateTeacherSelect(teachers) {
|
|
if (!assignTeacherSelect) return;
|
|
const currentVal = assignTeacherSelect.value;
|
|
if (!teachers || !teachers.length) {
|
|
assignTeacherSelect.innerHTML = '<option value="">Нет преподавателей</option>';
|
|
return;
|
|
}
|
|
assignTeacherSelect.innerHTML = '<option value="">Выберите преподавателя</option>' +
|
|
teachers.map(t => `<option value="${t.id}">${escapeHtml(t.username)}</option>`).join('');
|
|
if (currentVal && teachers.find(t => t.id == currentVal)) {
|
|
assignTeacherSelect.value = currentVal;
|
|
}
|
|
}
|
|
|
|
async function loadTeacherSubjects() {
|
|
try {
|
|
const tsData = await api.get('/api/teacher-subjects');
|
|
renderTeacherSubjects(tsData);
|
|
} catch (e) {
|
|
if (teacherSubjectsTbody) teacherSubjectsTbody.innerHTML = '<tr><td colspan="3" class="loading-row">Ошибка загрузки</td></tr>';
|
|
}
|
|
}
|
|
|
|
function renderTeacherSubjects(tsArray) {
|
|
if (!tsArray || !tsArray.length) {
|
|
teacherSubjectsTbody.innerHTML = '<tr><td colspan="3" class="loading-row">Нет привязок</td></tr>';
|
|
return;
|
|
}
|
|
teacherSubjectsTbody.innerHTML = tsArray.map(ts => `
|
|
<tr>
|
|
<td>${escapeHtml(ts.username)}</td>
|
|
<td>${escapeHtml(ts.subjectName)}</td>
|
|
<td><button class="btn-delete" data-user-id="${ts.userId}" data-subject-id="${ts.subjectId}">Удалить</button></td>
|
|
</tr>`).join('');
|
|
}
|
|
|
|
createSubjectForm.addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
hideAlert('create-subject-alert');
|
|
const name = document.getElementById('new-subject-name').value.trim();
|
|
if (!name) { showAlert('create-subject-alert', 'Введите название', 'error'); return; }
|
|
|
|
try {
|
|
const data = await api.post('/api/subjects', { name });
|
|
showAlert('create-subject-alert', `Дисциплина "${escapeHtml(data.name)}" добавлена`, 'success');
|
|
createSubjectForm.reset();
|
|
loadSubjects();
|
|
} catch (e) { showAlert('create-subject-alert', e.message || 'Ошибка создания', 'error'); }
|
|
});
|
|
|
|
subjectsTbody.addEventListener('click', async (e) => {
|
|
const btn = e.target.closest('.btn-delete');
|
|
if (!btn) return;
|
|
if (!confirm('Удалить дисциплину?')) return;
|
|
try {
|
|
await api.delete('/api/subjects/' + btn.dataset.id);
|
|
loadSubjects();
|
|
loadTeacherSubjects(); // May have deleted a subject that was assigned
|
|
} catch (e) { alert(e.message || 'Ошибка удаления'); }
|
|
});
|
|
|
|
assignTeacherForm.addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
hideAlert('assign-teacher-alert');
|
|
const userId = assignTeacherSelect.value;
|
|
const subjectId = assignSubjectSelect.value;
|
|
if (!userId) { showAlert('assign-teacher-alert', 'Выберите преподавателя', 'error'); return; }
|
|
if (!subjectId) { showAlert('assign-teacher-alert', 'Выберите дисциплину', 'error'); return; }
|
|
|
|
try {
|
|
await api.post('/api/teacher-subjects', { userId: Number(userId), subjectId: Number(subjectId) });
|
|
showAlert('assign-teacher-alert', 'Привязка создана', 'success');
|
|
loadTeacherSubjects();
|
|
} catch (e) { showAlert('assign-teacher-alert', e.message || 'Ошибка привязки', 'error'); }
|
|
});
|
|
|
|
teacherSubjectsTbody.addEventListener('click', async (e) => {
|
|
const btn = e.target.closest('.btn-delete');
|
|
if (!btn) return;
|
|
if (!confirm('Удалить привязку?')) return;
|
|
try {
|
|
await api.delete('/api/teacher-subjects', {
|
|
userId: Number(btn.dataset.userId),
|
|
subjectId: Number(btn.dataset.subjectId)
|
|
});
|
|
loadTeacherSubjects();
|
|
} catch (e) { alert(e.message || 'Ошибка удаления'); }
|
|
});
|
|
|
|
loadInitialData();
|
|
}
|