async function pidCreateUsuario(payload) { return pidApiRequest("/usuarios/", { method: "POST", body: payload }); } async function pidUpdateUsuario(id, payload) { return pidApiRequest(`/usuarios/${id}/`, { method: "PATCH", body: payload }); } async function pidDeleteUsuario(id) { return pidApiRequest(`/usuarios/${id}/`, { method: "DELETE" }); } document.addEventListener("DOMContentLoaded", async () => { const listView = document.getElementById("ua-list-view"); const editView = document.getElementById("ua-edit-view"); if (!listView || !editView) return; const me = await pidGetMe(); if (!me) return; if (!me.gerencia_permissoes) { window.location.href = "portal.html"; return; } let users = await pidFetchUsuarios(); let editingId = null; const tableBody = document.getElementById("ua-table-body"); const footerCount = document.getElementById("ua-footer-count"); const searchInput = document.getElementById("ua-search-input"); const newBtn = document.getElementById("ua-new-btn"); const backBtn = document.getElementById("ua-back-btn"); const cancelBtn = document.getElementById("ua-cancel-btn"); const saveBtn = document.getElementById("ua-save-btn"); const loginInput = document.getElementById("ua-login"); const nomeInput = document.getElementById("ua-nome"); const senhaInput = document.getElementById("ua-senha"); const senhaToggleBtn = document.getElementById("ua-senha-toggle"); const profileChecklist = document.getElementById("ua-profile-checklist"); const formError = document.getElementById("ua-form-error"); const departamentoChecklist = document.getElementById("ua-departamento-checklist"); const departamentoNewInput = document.getElementById("ua-departamento-new"); const departamentoAddBtn = document.getElementById("ua-departamento-add-btn"); const departamentoError = document.getElementById("ua-departamento-error"); const emailInput = document.getElementById("ua-email"); const codigoFolhaInput = document.getElementById("ua-codigo-folha"); const codigoQuestorInput = document.getElementById("ua-codigo-questor"); const codigoTareffaInput = document.getElementById("ua-codigo-tareffa"); const codigoContabitInput = document.getElementById("ua-codigo-contabit"); const ramalInput = document.getElementById("ua-ramal"); const dataAniversarioInput = document.getElementById("ua-data-aniversario"); const ativoInput = document.getElementById("ua-ativo"); const liderancaInput = document.getElementById("ua-lideranca"); const lideradosField = document.getElementById("ua-liderados-field"); const lideradosSearchInput = document.getElementById("ua-liderados-search"); const lideradosSelectAllInput = document.getElementById("ua-liderados-select-all"); const lideradosChecklist = document.getElementById("ua-liderados-checklist"); liderancaInput.addEventListener("change", () => { lideradosField.hidden = !liderancaInput.checked; }); pidBindPasswordToggle(senhaToggleBtn, senhaInput); function profileNomes(perfis) { return perfis.length ? perfis.map((p) => p.nome).join(", ") : "Sem perfil vinculado"; } function renderList() { const term = searchInput.value.trim().toLowerCase(); const rows = users .filter((u) => !term || u.nome.toLowerCase().includes(term) || u.username.toLowerCase().includes(term)) .slice() .sort((a, b) => a.nome.localeCompare(b.nome)); tableBody.innerHTML = rows.length ? rows .map( (u) => ` ${u.username} ${u.nome} ${profileNomes(u.perfis)} ${u.is_active ? "Ativo" : "Inativo"}
` ) .join("") : `Nenhum usuário encontrado.`; footerCount.textContent = `${rows.length} ${rows.length === 1 ? "item" : "itens"}`; } async function fillProfileChecklist(selectedCodigos) { const perfis = (await pidFetchPerfis()).slice().sort((a, b) => a.nome.localeCompare(b.nome)); profileChecklist.innerHTML = perfis .map( (p) => ` ` ) .join(""); } let lideradosCandidatos = []; let lideradosSelecionados = new Set(); function departamentosTexto(usuario) { return (usuario.departamentos || []).map((d) => d.nome).join(", "); } function lideradosFiltrados() { const termo = lideradosSearchInput.value.trim().toLowerCase(); return lideradosCandidatos.filter( (u) => !termo || u.nome.toLowerCase().includes(termo) || departamentosTexto(u).toLowerCase().includes(termo) ); } function renderLideradosChecklist() { const filtrados = lideradosFiltrados(); lideradosChecklist.innerHTML = filtrados.length ? filtrados .map( (u) => ` ` ) .join("") : `

Nenhum usuário encontrado.

`; const todosMarcados = filtrados.length > 0 && filtrados.every((u) => lideradosSelecionados.has(u.id)); const algumMarcado = filtrados.some((u) => lideradosSelecionados.has(u.id)); lideradosSelectAllInput.disabled = filtrados.length === 0; lideradosSelectAllInput.checked = todosMarcados; lideradosSelectAllInput.indeterminate = !todosMarcados && algumMarcado; } function fillLideradosChecklist(selectedIds, excludeId) { lideradosCandidatos = users .filter((u) => u.id !== excludeId) .slice() .sort((a, b) => a.nome.localeCompare(b.nome)); lideradosSelecionados = new Set(selectedIds); lideradosSearchInput.value = ""; renderLideradosChecklist(); } function selectedLideradosIds() { return Array.from(lideradosSelecionados); } lideradosChecklist.addEventListener("change", (event) => { const checkbox = event.target.closest('input[type="checkbox"]'); if (!checkbox) return; const id = Number(checkbox.value); if (checkbox.checked) lideradosSelecionados.add(id); else lideradosSelecionados.delete(id); renderLideradosChecklist(); }); lideradosSearchInput.addEventListener("input", renderLideradosChecklist); lideradosSelectAllInput.addEventListener("change", () => { const filtrados = lideradosFiltrados(); if (lideradosSelectAllInput.checked) { filtrados.forEach((u) => lideradosSelecionados.add(u.id)); } else { filtrados.forEach((u) => lideradosSelecionados.delete(u.id)); } renderLideradosChecklist(); }); let departamentosCache = []; async function fillDepartamentoChecklist(selectedIds) { departamentosCache = (await pidFetchDepartamentos()).slice().sort((a, b) => a.nome.localeCompare(b.nome)); departamentoChecklist.innerHTML = departamentosCache .map( (d) => `
` ) .join(""); } function selectedDepartamentoIds() { return Array.from(departamentoChecklist.querySelectorAll('input[type="checkbox"]:checked')).map((cb) => Number(cb.value) ); } async function openEdit(id) { formError.textContent = ""; departamentoError.textContent = ""; departamentoNewInput.value = ""; senhaInput.value = ""; senhaInput.type = "password"; if (senhaToggleBtn) senhaToggleBtn.setAttribute("aria-label", "Mostrar senha"); if (id === null) { editingId = null; loginInput.value = ""; nomeInput.value = ""; senhaInput.placeholder = "Digite a senha"; emailInput.value = ""; codigoFolhaInput.value = ""; codigoQuestorInput.value = ""; codigoTareffaInput.value = ""; codigoContabitInput.value = ""; ramalInput.value = ""; dataAniversarioInput.value = ""; ativoInput.checked = true; ativoInput.disabled = false; liderancaInput.checked = false; lideradosField.hidden = true; await fillProfileChecklist([]); await fillDepartamentoChecklist([]); fillLideradosChecklist([], null); } else { const account = users.find((u) => u.id === id); if (!account) return; editingId = id; loginInput.value = account.username; nomeInput.value = account.nome; senhaInput.placeholder = "Deixe em branco para manter a senha atual"; emailInput.value = account.email || ""; codigoFolhaInput.value = account.codigo_folha || ""; codigoQuestorInput.value = account.codigo_questor || ""; codigoTareffaInput.value = account.codigo_tareffa || ""; codigoContabitInput.value = account.codigo_contabit || ""; ramalInput.value = account.ramal || ""; dataAniversarioInput.value = account.data_aniversario || ""; ativoInput.checked = account.is_active; ativoInput.disabled = account.id === me.id; liderancaInput.checked = account.lideranca; lideradosField.hidden = !account.lideranca; await fillProfileChecklist(account.perfis.map((p) => p.codigo)); await fillDepartamentoChecklist(account.departamentos.map((d) => d.id)); fillLideradosChecklist(account.liderados.map((u) => u.id), account.id); } listView.hidden = true; editView.hidden = false; } function closeEdit() { editView.hidden = true; listView.hidden = false; renderList(); } searchInput.addEventListener("input", renderList); newBtn.addEventListener("click", () => openEdit(null)); backBtn.addEventListener("click", closeEdit); cancelBtn.addEventListener("click", closeEdit); departamentoAddBtn.addEventListener("click", async () => { const nome = departamentoNewInput.value.trim(); if (!nome) { departamentoError.textContent = "Informe o nome do departamento."; return; } departamentoError.textContent = ""; try { const novo = await pidCreateDepartamento({ nome }); const selected = selectedDepartamentoIds(); selected.push(novo.id); await fillDepartamentoChecklist(selected); departamentoNewInput.value = ""; } catch (e) { departamentoError.textContent = e.message; } }); departamentoChecklist.addEventListener("click", async (event) => { const editBtn = event.target.closest("[data-dep-edit]"); if (editBtn) { const id = Number(editBtn.getAttribute("data-dep-edit")); const dep = departamentosCache.find((d) => d.id === id); if (!dep) return; const novoNome = window.prompt("Novo nome do departamento:", dep.nome); if (novoNome === null) return; const nome = novoNome.trim(); if (!nome) return; departamentoError.textContent = ""; try { await pidUpdateDepartamento(id, { nome }); await fillDepartamentoChecklist(selectedDepartamentoIds()); } catch (e) { departamentoError.textContent = e.message; } return; } const deleteBtn = event.target.closest("[data-dep-delete]"); if (deleteBtn) { const id = Number(deleteBtn.getAttribute("data-dep-delete")); const dep = departamentosCache.find((d) => d.id === id); if (!dep) return; if (!window.confirm(`Excluir o departamento "${dep.nome}"?`)) return; try { await pidDeleteDepartamento(id); const selected = selectedDepartamentoIds().filter((depId) => depId !== id); await fillDepartamentoChecklist(selected); } catch (e) { window.alert(e.message); } } }); tableBody.addEventListener("click", async (event) => { const editTarget = event.target.closest("[data-ua-edit]"); if (editTarget) { event.preventDefault(); await openEdit(Number(editTarget.getAttribute("data-ua-edit"))); return; } const deleteTarget = event.target.closest("[data-ua-delete]"); if (deleteTarget) { const id = Number(deleteTarget.getAttribute("data-ua-delete")); if (id === me.id) { window.alert("Você não pode excluir o usuário com o qual está logado."); return; } const account = users.find((u) => u.id === id); if (account && window.confirm(`Excluir o usuário "${account.nome}"?`)) { await pidDeleteUsuario(id); users = await pidFetchUsuarios(); renderList(); } return; } const toggleTarget = event.target.closest("[data-ua-toggle-active]"); if (toggleTarget) { const id = Number(toggleTarget.getAttribute("data-ua-toggle-active")); if (id === me.id) { window.alert("Você não pode desativar o usuário com o qual está logado."); return; } const account = users.find((u) => u.id === id); if (!account) return; const acao = account.is_active ? "Desativar" : "Ativar"; if (window.confirm(`${acao} o usuário "${account.nome}"?`)) { await pidUpdateUsuario(id, { is_active: !account.is_active }); users = await pidFetchUsuarios(); renderList(); } } }); saveBtn.addEventListener("click", async () => { const username = loginInput.value.trim(); const nome = nomeInput.value.trim(); const senha = senhaInput.value; const perfis = Array.from(profileChecklist.querySelectorAll('input[type="checkbox"]:checked')).map((cb) => Number(cb.value) ); const departamentos = selectedDepartamentoIds(); const email = emailInput.value.trim(); const codigo_folha = codigoFolhaInput.value.trim(); const codigo_questor = codigoQuestorInput.value.trim(); const codigo_tareffa = codigoTareffaInput.value.trim(); const codigo_contabit = codigoContabitInput.value.trim(); const ramal = ramalInput.value.trim(); const data_aniversario = dataAniversarioInput.value || null; const lideranca = liderancaInput.checked; const liderados = selectedLideradosIds(); if (!username || !nome) { formError.textContent = "Informe login e nome do usuário."; return; } if (editingId === null && !senha) { formError.textContent = "Informe uma senha para o novo usuário."; return; } formError.textContent = ""; const payload = { username, nome, senha, perfis, departamentos, email, codigo_folha, codigo_questor, codigo_tareffa, codigo_contabit, ramal, data_aniversario, lideranca, liderados, is_active: ativoInput.checked, }; try { if (editingId === null) { await pidCreateUsuario(payload); } else { await pidUpdateUsuario(editingId, payload); } users = await pidFetchUsuarios(); closeEdit(); } catch (e) { formError.textContent = e.message; } }); renderList(); });