115 lines
4.3 KiB
JavaScript
115 lines
4.3 KiB
JavaScript
// public/k.js – управление привязкой учителей к корпусам
|
||
|
||
let currentUser = null;
|
||
let teachersList = []; // [{ id, name, subject, campus }]
|
||
|
||
document.addEventListener('DOMContentLoaded', async () => {
|
||
await checkAuth();
|
||
await loadTeachers();
|
||
setupEventListeners();
|
||
});
|
||
|
||
async function checkAuth() {
|
||
try {
|
||
const res = await fetch('/api/me');
|
||
const data = await res.json();
|
||
if (!data.authenticated || data.user.role !== 'admin') {
|
||
window.location.href = '/login.html';
|
||
return;
|
||
}
|
||
currentUser = data.user;
|
||
document.getElementById('userInfo').innerHTML = `👋 ${currentUser.full_name} (${currentUser.role})`;
|
||
} catch (err) {
|
||
window.location.href = '/login.html';
|
||
}
|
||
}
|
||
|
||
async function loadTeachers() {
|
||
try {
|
||
const res = await fetch('/api/teachers');
|
||
teachersList = await res.json();
|
||
renderTable();
|
||
} catch (err) {
|
||
console.error(err);
|
||
document.getElementById('tableBody').innerHTML = '<tr><td colspan="3">Ошибка загрузки</td></tr>';
|
||
}
|
||
}
|
||
|
||
function renderTable() {
|
||
const tbody = document.getElementById('tableBody');
|
||
if (!teachersList.length) {
|
||
tbody.innerHTML = '<tr><td colspan="3">Нет учителей</td></tr>';
|
||
return;
|
||
}
|
||
tbody.innerHTML = teachersList.map(teacher => `
|
||
<tr data-id="${teacher.id}">
|
||
<td>${escapeHtml(teacher.name)}</td>
|
||
<td>${escapeHtml(teacher.subject || '—')}</td>
|
||
<td>
|
||
<select class="campus-select" data-id="${teacher.id}">
|
||
<option value="" ${teacher.campus === '' ? 'selected' : ''}>Оба корпуса</option>
|
||
<option value="Феофанова 10" ${teacher.campus === 'Феофанова 10' ? 'selected' : ''}>Феофанова 10</option>
|
||
<option value="Цветоносная 2" ${teacher.campus === 'Цветоносная 2' ? 'selected' : ''}>Цветоносная 2</option>
|
||
</select>
|
||
</td>
|
||
</tr>
|
||
`).join('');
|
||
}
|
||
|
||
async function saveAllChanges() {
|
||
const updates = [];
|
||
document.querySelectorAll('.campus-select').forEach(select => {
|
||
const teacherId = parseInt(select.dataset.id);
|
||
const newCampus = select.value;
|
||
updates.push({ id: teacherId, campus: newCampus });
|
||
});
|
||
|
||
const messageDiv = document.getElementById('message');
|
||
messageDiv.style.display = 'block';
|
||
messageDiv.className = 'message';
|
||
messageDiv.innerHTML = 'Сохранение...';
|
||
|
||
try {
|
||
const res = await fetch('/api/teachers/campus/batch', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ updates })
|
||
});
|
||
const data = await res.json();
|
||
if (res.ok) {
|
||
messageDiv.className = 'message success';
|
||
messageDiv.innerHTML = '✅ Изменения сохранены';
|
||
setTimeout(() => messageDiv.style.display = 'none', 3000);
|
||
// обновляем локальные данные
|
||
teachersList = teachersList.map(t => {
|
||
const update = updates.find(u => u.id === t.id);
|
||
if (update) t.campus = update.campus;
|
||
return t;
|
||
});
|
||
} else {
|
||
throw new Error(data.error || 'Ошибка сохранения');
|
||
}
|
||
} catch (err) {
|
||
messageDiv.className = 'message error';
|
||
messageDiv.innerHTML = `❌ Ошибка: ${err.message}`;
|
||
setTimeout(() => messageDiv.style.display = 'none', 3000);
|
||
}
|
||
}
|
||
|
||
function setupEventListeners() {
|
||
document.getElementById('saveAllBtn')?.addEventListener('click', saveAllChanges);
|
||
document.getElementById('logoutBtn')?.addEventListener('click', async () => {
|
||
await fetch('/api/logout', { method: 'POST' });
|
||
window.location.href = '/';
|
||
});
|
||
}
|
||
|
||
function escapeHtml(str) {
|
||
if (!str) return '';
|
||
return str.replace(/[&<>]/g, function(m) {
|
||
if (m === '&') return '&';
|
||
if (m === '<') return '<';
|
||
if (m === '>') return '>';
|
||
return m;
|
||
});
|
||
} |