доработал отображение учебного графика
This commit is contained in:
192
frontend/admin/js/views/profiles.js
Normal file
192
frontend/admin/js/views/profiles.js
Normal file
@@ -0,0 +1,192 @@
|
||||
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 }));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user