367 lines
16 KiB
JavaScript
367 lines
16 KiB
JavaScript
import { api } from '../api.js';
|
|
import { escapeHtml, showAlert, hideAlert } from '../utils.js';
|
|
|
|
export async function initDepartmentsData() {
|
|
const deptTbody = document.getElementById('departments-tbody');
|
|
const specTbody = document.getElementById('specialties-tbody');
|
|
|
|
const createDeptForm = document.getElementById('create-department-form');
|
|
const createSpecForm = document.getElementById('create-specialty-form');
|
|
const createProfileForm = document.getElementById('create-profile-form');
|
|
const profileSpecialtySelect = document.getElementById('profile-specialty');
|
|
const profilesTbody = document.getElementById('profiles-tbody');
|
|
const editDeptForm = document.getElementById('edit-department-form');
|
|
const editSpecForm = document.getElementById('edit-specialty-form');
|
|
const editProfileForm = document.getElementById('edit-profile-form');
|
|
const editDeptModal = document.getElementById('modal-edit-department');
|
|
const editSpecModal = document.getElementById('modal-edit-specialty');
|
|
const editProfileModal = document.getElementById('modal-edit-profile');
|
|
const editDeptClose = document.getElementById('modal-edit-department-close');
|
|
const editSpecClose = document.getElementById('modal-edit-specialty-close');
|
|
const editProfileClose = document.getElementById('modal-edit-profile-close');
|
|
|
|
let departments = [];
|
|
let specialties = [];
|
|
let profiles = [];
|
|
|
|
async function loadData() {
|
|
// Load Departments
|
|
try {
|
|
departments = await api.get('/api/departments');
|
|
renderDepartments();
|
|
} catch (e) {
|
|
deptTbody.innerHTML = '<tr><td colspan="4" class="loading-row">-</td></tr>';
|
|
}
|
|
|
|
// Load Specialties
|
|
try {
|
|
specialties = await api.get('/api/specialties');
|
|
renderSpecialties();
|
|
renderProfileSpecialtySelect();
|
|
await loadProfiles();
|
|
} catch (e) {
|
|
specTbody.innerHTML = '<tr><td colspan="4" class="loading-row">-</td></tr>';
|
|
profilesTbody.innerHTML = '<tr><td colspan="4" class="loading-row">-</td></tr>';
|
|
}
|
|
}
|
|
|
|
function renderDepartments() {
|
|
if (!departments || !departments.length) {
|
|
deptTbody.innerHTML = '<tr><td colspan="4" class="loading-row">-</td></tr>';
|
|
return;
|
|
}
|
|
deptTbody.innerHTML = departments.map(d => `
|
|
<tr>
|
|
<td>${d.id}</td>
|
|
<td>${escapeHtml(d.departmentName || d.name)}</td>
|
|
<td>${escapeHtml(String(d.departmentCode || d.code))}</td>
|
|
<td>
|
|
<button class="btn-edit-classroom btn-edit-department" data-id="${d.id}">Изменить</button>
|
|
<button class="btn-delete btn-delete-department" data-id="${d.id}">Удалить</button>
|
|
</td>
|
|
</tr>
|
|
`).join('');
|
|
}
|
|
|
|
function renderSpecialties() {
|
|
if (!specialties || !specialties.length) {
|
|
specTbody.innerHTML = '<tr><td colspan="4" class="loading-row">-</td></tr>';
|
|
return;
|
|
}
|
|
specTbody.innerHTML = specialties.map(s => `
|
|
<tr>
|
|
<td>${s.id}</td>
|
|
<td>${escapeHtml(s.specialityName || s.name)}</td>
|
|
<td>${escapeHtml(s.specialityCode || s.specialtyCode || s.specialty_code)}</td>
|
|
<td>
|
|
<button class="btn-edit-classroom btn-edit-specialty" data-id="${s.id}">Изменить</button>
|
|
<button class="btn-delete btn-delete-specialty" data-id="${s.id}">Удалить</button>
|
|
</td>
|
|
</tr>
|
|
`).join('');
|
|
}
|
|
|
|
function renderProfileSpecialtySelect() {
|
|
const current = profileSpecialtySelect.value;
|
|
profileSpecialtySelect.innerHTML = '<option value="">Выберите специальность</option>' +
|
|
specialties.map(s => `<option value="${s.id}">${escapeHtml(s.specialityCode || s.specialtyCode || s.specialty_code)} — ${escapeHtml(s.specialityName || s.name)}</option>`).join('');
|
|
if (current && specialties.some(s => String(s.id) === String(current))) {
|
|
profileSpecialtySelect.value = current;
|
|
} else if (specialties.length) {
|
|
profileSpecialtySelect.value = String(specialties[0].id);
|
|
}
|
|
syncSelect(profileSpecialtySelect);
|
|
}
|
|
|
|
async function loadProfiles() {
|
|
const specialtyId = profileSpecialtySelect.value;
|
|
if (!specialtyId) {
|
|
profiles = [];
|
|
profilesTbody.innerHTML = '<tr><td colspan="4" class="loading-row">Выберите специальность</td></tr>';
|
|
return;
|
|
}
|
|
profilesTbody.innerHTML = '<tr><td colspan="4" class="loading-row">Загрузка...</td></tr>';
|
|
try {
|
|
profiles = await api.get(`/api/specialties/${specialtyId}/profiles`);
|
|
renderProfiles();
|
|
} catch (error) {
|
|
profilesTbody.innerHTML = `<tr><td colspan="4" class="loading-row">Ошибка загрузки: ${escapeHtml(error.message)}</td></tr>`;
|
|
}
|
|
}
|
|
|
|
function renderProfiles() {
|
|
if (!profiles.length) {
|
|
profilesTbody.innerHTML = '<tr><td colspan="4" class="loading-row">Профили не созданы</td></tr>';
|
|
return;
|
|
}
|
|
profilesTbody.innerHTML = profiles.map(profile => `
|
|
<tr>
|
|
<td>${profile.id}</td>
|
|
<td>${escapeHtml(profile.name)}</td>
|
|
<td>${escapeHtml(profile.description || '-')}</td>
|
|
<td>
|
|
<button class="btn-edit-classroom btn-edit-profile" data-id="${profile.id}">Изменить</button>
|
|
<button class="btn-delete btn-delete-profile" data-id="${profile.id}">Удалить</button>
|
|
</td>
|
|
</tr>
|
|
`).join('');
|
|
}
|
|
|
|
createDeptForm.addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
hideAlert('create-dept-alert');
|
|
const name = document.getElementById('dept-name').value.trim();
|
|
const code = document.getElementById('dept-code').value.trim();
|
|
|
|
if (!name || !code) {
|
|
showAlert('create-dept-alert', 'Заполните все поля', 'error');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await api.post('/api/departments', { departmentName: name, departmentCode: Number(code) });
|
|
showAlert('create-dept-alert', `Кафедра "${name}" создана`, 'success');
|
|
createDeptForm.reset();
|
|
loadData();
|
|
} catch (error) {
|
|
showAlert('create-dept-alert', error.message || 'Ошибка создания кафедры', 'error');
|
|
}
|
|
});
|
|
|
|
deptTbody.addEventListener('click', async (e) => {
|
|
const editBtn = e.target.closest('.btn-edit-department');
|
|
const deleteBtn = e.target.closest('.btn-delete-department');
|
|
|
|
if (editBtn) {
|
|
const department = departments.find(item => item.id == editBtn.dataset.id);
|
|
if (!department) return;
|
|
|
|
document.getElementById('edit-dept-id').value = department.id;
|
|
document.getElementById('edit-dept-name').value = department.departmentName || department.name || '';
|
|
document.getElementById('edit-dept-code').value = department.departmentCode || department.code || '';
|
|
hideAlert('edit-dept-alert');
|
|
editDeptModal.classList.add('open');
|
|
return;
|
|
}
|
|
|
|
if (deleteBtn) {
|
|
if (!confirm('Удалить кафедру?')) return;
|
|
try {
|
|
await api.delete('/api/departments/' + deleteBtn.dataset.id);
|
|
showAlert('create-dept-alert', 'Кафедра удалена', 'success');
|
|
await loadData();
|
|
} catch (error) {
|
|
showAlert('create-dept-alert', error.message || 'Ошибка удаления кафедры', 'error');
|
|
}
|
|
}
|
|
});
|
|
|
|
createSpecForm.addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
hideAlert('create-spec-alert');
|
|
const name = document.getElementById('spec-name').value.trim();
|
|
const code = document.getElementById('spec-code').value.trim();
|
|
|
|
if (!name || !code) {
|
|
showAlert('create-spec-alert', 'Заполните все поля', 'error');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await api.post('/api/specialties', { specialityName: name, specialityCode: code });
|
|
showAlert('create-spec-alert', `Специальность "${name}" создана`, 'success');
|
|
createSpecForm.reset();
|
|
loadData();
|
|
} catch (error) {
|
|
showAlert('create-spec-alert', error.message || 'Ошибка создания специальности', 'error');
|
|
}
|
|
});
|
|
|
|
profileSpecialtySelect.addEventListener('change', loadProfiles);
|
|
|
|
createProfileForm.addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
hideAlert('create-profile-alert');
|
|
const specialtyId = profileSpecialtySelect.value;
|
|
const name = document.getElementById('profile-name').value.trim();
|
|
const description = document.getElementById('profile-description').value.trim();
|
|
|
|
if (!specialtyId || !name) {
|
|
showAlert('create-profile-alert', 'Выберите специальность и заполните название профиля', 'error');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await api.post(`/api/specialties/${specialtyId}/profiles`, { name, description });
|
|
showAlert('create-profile-alert', `Профиль "${name}" создан`, 'success');
|
|
createProfileForm.reset();
|
|
profileSpecialtySelect.value = specialtyId;
|
|
syncSelect(profileSpecialtySelect);
|
|
await loadProfiles();
|
|
} catch (error) {
|
|
showAlert('create-profile-alert', error.message || 'Ошибка создания профиля', 'error');
|
|
}
|
|
});
|
|
|
|
profilesTbody.addEventListener('click', async (e) => {
|
|
const editBtn = e.target.closest('.btn-edit-profile');
|
|
const deleteBtn = e.target.closest('.btn-delete-profile');
|
|
|
|
if (editBtn) {
|
|
const profile = profiles.find(item => item.id == editBtn.dataset.id);
|
|
if (!profile) return;
|
|
document.getElementById('edit-profile-id').value = profile.id;
|
|
document.getElementById('edit-profile-name').value = profile.name || '';
|
|
document.getElementById('edit-profile-description').value = profile.description || '';
|
|
hideAlert('edit-profile-alert');
|
|
editProfileModal.classList.add('open');
|
|
return;
|
|
}
|
|
|
|
if (deleteBtn) {
|
|
if (!confirm('Удалить профиль обучения?')) return;
|
|
try {
|
|
await api.delete(`/api/specialties/${profileSpecialtySelect.value}/profiles/${deleteBtn.dataset.id}`);
|
|
showAlert('create-profile-alert', 'Профиль удалён', 'success');
|
|
await loadProfiles();
|
|
} catch (error) {
|
|
showAlert('create-profile-alert', error.message || 'Ошибка удаления профиля', 'error');
|
|
}
|
|
}
|
|
});
|
|
|
|
specTbody.addEventListener('click', async (e) => {
|
|
const editBtn = e.target.closest('.btn-edit-specialty');
|
|
const deleteBtn = e.target.closest('.btn-delete-specialty');
|
|
|
|
if (editBtn) {
|
|
const speciality = specialties.find(item => item.id == editBtn.dataset.id);
|
|
if (!speciality) return;
|
|
|
|
document.getElementById('edit-spec-id').value = speciality.id;
|
|
document.getElementById('edit-spec-name').value = speciality.specialityName || speciality.name || '';
|
|
document.getElementById('edit-spec-code').value = speciality.specialityCode || speciality.specialtyCode || speciality.specialty_code || '';
|
|
hideAlert('edit-spec-alert');
|
|
editSpecModal.classList.add('open');
|
|
return;
|
|
}
|
|
|
|
if (deleteBtn) {
|
|
if (!confirm('Удалить специальность?')) return;
|
|
try {
|
|
await api.delete('/api/specialties/' + deleteBtn.dataset.id);
|
|
showAlert('create-spec-alert', 'Специальность удалена', 'success');
|
|
await loadData();
|
|
} catch (error) {
|
|
showAlert('create-spec-alert', error.message || 'Ошибка удаления специальности', 'error');
|
|
}
|
|
}
|
|
});
|
|
|
|
editDeptForm.addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
hideAlert('edit-dept-alert');
|
|
const id = document.getElementById('edit-dept-id').value;
|
|
const name = document.getElementById('edit-dept-name').value.trim();
|
|
const code = document.getElementById('edit-dept-code').value.trim();
|
|
|
|
if (!name || !code) {
|
|
showAlert('edit-dept-alert', 'Заполните все поля', 'error');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await api.put('/api/departments/' + id, { departmentName: name, departmentCode: Number(code) });
|
|
editDeptModal.classList.remove('open');
|
|
showAlert('create-dept-alert', `Кафедра "${name}" обновлена`, 'success');
|
|
await loadData();
|
|
} catch (error) {
|
|
showAlert('edit-dept-alert', error.message || 'Ошибка обновления кафедры', 'error');
|
|
}
|
|
});
|
|
|
|
editSpecForm.addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
hideAlert('edit-spec-alert');
|
|
const id = document.getElementById('edit-spec-id').value;
|
|
const name = document.getElementById('edit-spec-name').value.trim();
|
|
const code = document.getElementById('edit-spec-code').value.trim();
|
|
|
|
if (!name || !code) {
|
|
showAlert('edit-spec-alert', 'Заполните все поля', 'error');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await api.put('/api/specialties/' + id, { specialityName: name, specialityCode: code });
|
|
editSpecModal.classList.remove('open');
|
|
showAlert('create-spec-alert', `Специальность "${name}" обновлена`, 'success');
|
|
await loadData();
|
|
} catch (error) {
|
|
showAlert('edit-spec-alert', error.message || 'Ошибка обновления специальности', 'error');
|
|
}
|
|
});
|
|
|
|
editProfileForm.addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
hideAlert('edit-profile-alert');
|
|
const specialtyId = profileSpecialtySelect.value;
|
|
const id = document.getElementById('edit-profile-id').value;
|
|
const name = document.getElementById('edit-profile-name').value.trim();
|
|
const description = document.getElementById('edit-profile-description').value.trim();
|
|
|
|
if (!specialtyId || !id || !name) {
|
|
showAlert('edit-profile-alert', 'Заполните название профиля', 'error');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await api.put(`/api/specialties/${specialtyId}/profiles/${id}`, { id: Number(id), name, description });
|
|
editProfileModal.classList.remove('open');
|
|
showAlert('create-profile-alert', `Профиль "${name}" обновлён`, 'success');
|
|
await loadProfiles();
|
|
} catch (error) {
|
|
showAlert('edit-profile-alert', error.message || 'Ошибка обновления профиля', 'error');
|
|
}
|
|
});
|
|
|
|
editDeptClose.addEventListener('click', () => editDeptModal.classList.remove('open'));
|
|
editSpecClose.addEventListener('click', () => editSpecModal.classList.remove('open'));
|
|
editProfileClose.addEventListener('click', () => editProfileModal.classList.remove('open'));
|
|
editDeptModal.addEventListener('click', (e) => {
|
|
if (e.target === editDeptModal) editDeptModal.classList.remove('open');
|
|
});
|
|
editSpecModal.addEventListener('click', (e) => {
|
|
if (e.target === editSpecModal) editSpecModal.classList.remove('open');
|
|
});
|
|
editProfileModal.addEventListener('click', (e) => {
|
|
if (e.target === editProfileModal) editProfileModal.classList.remove('open');
|
|
});
|
|
|
|
await loadData();
|
|
|
|
function syncSelect(select) {
|
|
select.dispatchEvent(new Event('change', { bubbles: true }));
|
|
}
|
|
}
|