193 lines
8.7 KiB
JavaScript
193 lines
8.7 KiB
JavaScript
import { api } from '../api.js';
|
||
import { escapeHtml, showAlert, hideAlert } from '../utils.js';
|
||
|
||
export async function initProfiles() {
|
||
const createProfileForm = document.getElementById('create-profile-form');
|
||
const profileSpecialtySelect = document.getElementById('profile-specialty');
|
||
const profileNameInput = document.getElementById('profile-name');
|
||
const profileDescriptionInput = document.getElementById('profile-description');
|
||
const profilesTbody = document.getElementById('profiles-tbody');
|
||
const profilesContext = document.getElementById('profiles-context');
|
||
const refreshButton = document.getElementById('profiles-refresh');
|
||
const editProfileForm = document.getElementById('edit-profile-form');
|
||
const editProfileModal = document.getElementById('modal-edit-profile');
|
||
const editProfileClose = document.getElementById('modal-edit-profile-close');
|
||
|
||
let specialties = [];
|
||
let profiles = [];
|
||
|
||
await loadSpecialties();
|
||
|
||
profileSpecialtySelect.addEventListener('change', loadProfiles);
|
||
refreshButton.addEventListener('click', loadProfiles);
|
||
|
||
createProfileForm.addEventListener('submit', async (event) => {
|
||
event.preventDefault();
|
||
hideAlert('create-profile-alert');
|
||
|
||
const specialtyId = profileSpecialtySelect.value;
|
||
const name = profileNameInput.value.trim();
|
||
const description = profileDescriptionInput.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 (event) => {
|
||
const editButton = event.target.closest('.btn-edit-profile');
|
||
const deleteButton = event.target.closest('.btn-delete-profile');
|
||
|
||
if (editButton) {
|
||
const profile = profiles.find(item => String(item.id) === String(editButton.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 (deleteButton) {
|
||
if (!confirm('Удалить профиль обучения?')) return;
|
||
try {
|
||
await api.delete(`/api/specialties/${profileSpecialtySelect.value}/profiles/${deleteButton.dataset.id}`);
|
||
showAlert('create-profile-alert', 'Профиль удалён', 'success');
|
||
await loadProfiles();
|
||
} catch (error) {
|
||
showAlert('create-profile-alert', error.message || 'Ошибка удаления профиля', 'error');
|
||
}
|
||
}
|
||
});
|
||
|
||
editProfileForm.addEventListener('submit', async (event) => {
|
||
event.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');
|
||
}
|
||
});
|
||
|
||
editProfileClose.addEventListener('click', () => editProfileModal.classList.remove('open'));
|
||
editProfileModal.addEventListener('click', (event) => {
|
||
if (event.target === editProfileModal) {
|
||
editProfileModal.classList.remove('open');
|
||
}
|
||
});
|
||
|
||
async function loadSpecialties() {
|
||
profilesTbody.innerHTML = '<tr><td colspan="4" class="loading-row">Загрузка...</td></tr>';
|
||
try {
|
||
specialties = await api.get('/api/specialties');
|
||
renderSpecialtySelect();
|
||
await loadProfiles();
|
||
} catch (error) {
|
||
profileSpecialtySelect.innerHTML = '<option value="">Не удалось загрузить специальности</option>';
|
||
profilesTbody.innerHTML = `<tr><td colspan="4" class="loading-row">Ошибка загрузки: ${escapeHtml(error.message)}</td></tr>`;
|
||
syncSelect(profileSpecialtySelect);
|
||
}
|
||
}
|
||
|
||
function renderSpecialtySelect() {
|
||
if (!specialties.length) {
|
||
profileSpecialtySelect.innerHTML = '<option value="">Сначала создайте специальность</option>';
|
||
syncSelect(profileSpecialtySelect);
|
||
return;
|
||
}
|
||
|
||
const current = profileSpecialtySelect.value;
|
||
profileSpecialtySelect.innerHTML = '<option value="">Выберите специальность</option>' +
|
||
specialties.map(specialty => {
|
||
const code = specialty.specialityCode || specialty.specialtyCode || specialty.specialty_code || specialty.id;
|
||
const name = specialty.specialityName || specialty.name || 'Без названия';
|
||
return `<option value="${specialty.id}">${escapeHtml(code)} — ${escapeHtml(name)}</option>`;
|
||
}).join('');
|
||
|
||
if (current && specialties.some(specialty => String(specialty.id) === String(current))) {
|
||
profileSpecialtySelect.value = current;
|
||
} else {
|
||
profileSpecialtySelect.value = String(specialties[0].id);
|
||
}
|
||
syncSelect(profileSpecialtySelect);
|
||
}
|
||
|
||
async function loadProfiles() {
|
||
const specialtyId = profileSpecialtySelect.value;
|
||
const specialty = specialties.find(item => String(item.id) === String(specialtyId));
|
||
profilesContext.textContent = specialty ? specialtyLabel(specialty) : '';
|
||
|
||
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('');
|
||
}
|
||
|
||
function specialtyLabel(specialty) {
|
||
const code = specialty.specialityCode || specialty.specialtyCode || specialty.specialty_code || specialty.id;
|
||
const name = specialty.specialityName || specialty.name || 'Без названия';
|
||
return `${code} · ${name}`;
|
||
}
|
||
|
||
function syncSelect(select) {
|
||
select.dispatchEvent(new Event('change', { bubbles: true }));
|
||
}
|
||
}
|