Fix user edit modal: pass full user object instead of just ID
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
async function init() {
|
||||
if (!(await checkAuth())) return;
|
||||
if (!isAdmin()) { location.href = 'journal.html'; return; }
|
||||
buildSidebar('users');
|
||||
document.getElementById('addUserBtn').addEventListener('click', () => openModal(null));
|
||||
document.getElementById('uCancel').addEventListener('click', closeModal);
|
||||
document.getElementById('uSave').addEventListener('click', saveUser);
|
||||
document.getElementById('uRole').addEventListener('change', () => {
|
||||
document.getElementById('uBranchesField').style.display = document.getElementById('uRole').value === 'admin' ? 'none' : '';
|
||||
});
|
||||
await loadUsers();
|
||||
}
|
||||
|
||||
let branches = [];
|
||||
let editingId = null;
|
||||
|
||||
async function loadUsers() {
|
||||
const [uRes, bRes] = await Promise.all([
|
||||
fetch(`${API}/api/users`, { headers: hdr() }),
|
||||
fetch(`${API}/api/branches`, { headers: hdr() }),
|
||||
]);
|
||||
if (!uRes.ok) { showToast('Ошибка загрузки пользователей'); return; }
|
||||
branches = await bRes.json();
|
||||
renderUsers(await uRes.json());
|
||||
}
|
||||
|
||||
function renderUsers(users) {
|
||||
const tbody = document.querySelector('#usersTable tbody');
|
||||
const empty = document.getElementById('usersEmpty');
|
||||
tbody.innerHTML = '';
|
||||
empty.style.display = users.length ? 'none' : 'block';
|
||||
const branchById = {};
|
||||
branches.forEach(b => { branchById[b.id] = b.name; });
|
||||
users.forEach(u => {
|
||||
const tr = document.createElement('tr');
|
||||
const branchNames = (u.branch_ids || []).map(id => branchById[id] || `#${id}`).join(', ') || '—';
|
||||
const roleCls = u.role === 'admin' ? 'badge-admin' : 'badge-tutor';
|
||||
const roleTxt = u.role === 'admin' ? 'Администратор' : 'Тутор';
|
||||
const status = u.is_active ? '<span class="status-ok">Активен</span>' : '<span class="status-off">Заблокирован</span>';
|
||||
const delBtn = u.id === currentUser.id
|
||||
? ''
|
||||
: `<button class="row-btn del" data-del="${u.id}" title="Удалить">×</button>`;
|
||||
tr.innerHTML = `
|
||||
<td>${u.id}</td>
|
||||
<td>${esc(u.username)}</td>
|
||||
<td>${esc(u.name || '')}</td>
|
||||
<td><span class="${roleCls}">${roleTxt}</span></td>
|
||||
<td class="user-branches">${esc(branchNames)}</td>
|
||||
<td>${status}</td>
|
||||
<td>
|
||||
<button class="row-btn" data-edit="${u.id}" title="Редактировать">✎</button>
|
||||
${delBtn}
|
||||
</td>`;
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
tbody.querySelectorAll('[data-edit]').forEach(b => {
|
||||
const userId = Number(b.dataset.edit);
|
||||
const user = users.find(u => u.id === userId);
|
||||
b.addEventListener('click', () => openModal(user));
|
||||
});
|
||||
tbody.querySelectorAll('[data-del]').forEach(b => b.addEventListener('click', () => delUser(Number(b.dataset.del))));
|
||||
}
|
||||
|
||||
function openModal(user) {
|
||||
editingId = user ? user.id : null;
|
||||
document.getElementById('userModalTitle').textContent = user ? `Пользователь: ${user.username}` : 'Новый пользователь';
|
||||
document.getElementById('uUsername').value = user ? user.username : '';
|
||||
document.getElementById('uName').value = user ? (user.name || '') : '';
|
||||
document.getElementById('uRole').value = user ? user.role : 'tutor';
|
||||
document.getElementById('uPassword').value = '';
|
||||
document.getElementById('uActive').checked = user ? user.is_active : true;
|
||||
document.getElementById('pwdHint').textContent = user ? '(оставьте пустым, чтобы не менять)' : '(мин. 6 символов)';
|
||||
document.getElementById('uRole').disabled = !!user && user.id === currentUser.id;
|
||||
const sel = document.getElementById('uBranches');
|
||||
sel.innerHTML = '';
|
||||
branches.forEach(b => {
|
||||
const o = document.createElement('option');
|
||||
o.value = b.id;
|
||||
o.textContent = b.name;
|
||||
if (user && (user.branch_ids || []).includes(b.id)) o.selected = true;
|
||||
sel.appendChild(o);
|
||||
});
|
||||
document.getElementById('uBranchesField').style.display = document.getElementById('uRole').value === 'admin' ? 'none' : '';
|
||||
document.getElementById('userModal').classList.add('open');
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
document.getElementById('userModal').classList.remove('open');
|
||||
}
|
||||
|
||||
async function saveUser() {
|
||||
const username = document.getElementById('uUsername').value.trim();
|
||||
const name = document.getElementById('uName').value.trim() || null;
|
||||
const role = document.getElementById('uRole').value;
|
||||
const password = document.getElementById('uPassword').value;
|
||||
const is_active = document.getElementById('uActive').checked;
|
||||
const branchSel = document.getElementById('uBranches');
|
||||
const branch_ids = role === 'admin' ? [] : [...branchSel.selectedOptions].map(o => Number(o.value));
|
||||
if (!username) { showToast('Укажите логин'); return; }
|
||||
if (!editingId && password.length < 6) { showToast('Пароль должен быть не короче 6 символов'); return; }
|
||||
const payload = { username, name, role, is_active, branch_ids };
|
||||
if (password) payload.password = password;
|
||||
const res = await fetch(editingId ? `${API}/api/users/${editingId}` : `${API}/api/users`, {
|
||||
method: editingId ? 'PUT' : 'POST',
|
||||
headers: hdrJson(),
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
const data = await res.json().catch(() => ({}));
|
||||
if (!res.ok) { showToast(data.error || 'Ошибка сохранения'); return; }
|
||||
showToast('Сохранено');
|
||||
closeModal();
|
||||
loadUsers();
|
||||
}
|
||||
|
||||
async function delUser(id) {
|
||||
if (!confirm('Удалить пользователя?')) return;
|
||||
const res = await fetch(`${API}/api/users/${id}`, { method: 'DELETE', headers: hdr() });
|
||||
if (!res.ok) {
|
||||
const data = await res.json().catch(() => ({}));
|
||||
showToast(data.error || 'Ошибка удаления');
|
||||
return;
|
||||
}
|
||||
showToast('Пользователь удалён');
|
||||
loadUsers();
|
||||
}
|
||||
|
||||
init();
|
||||
Reference in New Issue
Block a user