278 lines
11 KiB
JavaScript
278 lines
11 KiB
JavaScript
document.addEventListener("DOMContentLoaded", async () => {
|
|
const chipBtn = document.getElementById("persona-chip");
|
|
const dropdown = document.getElementById("account-dropdown");
|
|
if (!chipBtn || !dropdown) return;
|
|
|
|
const me = await pidGetMe();
|
|
if (!me) return;
|
|
|
|
const chipLabel = document.getElementById("persona-chip-label");
|
|
const nameEl = document.getElementById("account-name");
|
|
const profileEl = document.getElementById("account-profile");
|
|
const manageLink = document.getElementById("account-manage-link");
|
|
const manageAccountBtn = document.getElementById("account-manage-account-btn");
|
|
|
|
const profiles = me.perfis || [];
|
|
|
|
if (chipLabel) chipLabel.textContent = me.nome;
|
|
if (nameEl) nameEl.textContent = me.nome;
|
|
if (profileEl) {
|
|
profileEl.textContent = profiles.length ? profiles.map((p) => p.nome).join(", ") : "Sem perfil vinculado";
|
|
}
|
|
if (manageLink) manageLink.hidden = !me.gerencia_permissoes;
|
|
|
|
const themeSwatchesEl = document.getElementById("theme-swatches");
|
|
if (themeSwatchesEl) {
|
|
const renderSwatches = () => {
|
|
const active = pidGetColorTheme();
|
|
themeSwatchesEl.innerHTML = PID_COLOR_THEMES.map(
|
|
(t) => `
|
|
<button type="button" class="theme-swatch ${t.key === active ? "is-active" : ""}" data-theme-choice="${t.key}" style="background:${t.swatch}" aria-label="Tema ${t.label}" title="${t.label}">
|
|
${
|
|
t.key === active
|
|
? '<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><path d="M20 6L9 17l-5-5" stroke-linecap="round" stroke-linejoin="round"/></svg>'
|
|
: ""
|
|
}
|
|
</button>`
|
|
).join("");
|
|
};
|
|
|
|
renderSwatches();
|
|
|
|
themeSwatchesEl.addEventListener("click", (event) => {
|
|
const btn = event.target.closest("[data-theme-choice]");
|
|
if (!btn) return;
|
|
pidSetColorTheme(btn.getAttribute("data-theme-choice"));
|
|
renderSwatches();
|
|
});
|
|
}
|
|
|
|
/* Toggle "Temas sazonais" — liga/desliga temas sazonais (Halloween etc.),
|
|
ver seasonal-theme.js. Recarrega a página ao alternar: o tema sazonal já
|
|
foi aplicado (ou não) via troca de innerHTML/markup no carregamento
|
|
desta mesma página, então não dá pra simplesmente desfazer isso in-place
|
|
— o reload garante que tudo (ícone, teias, favicon) reflita a nova
|
|
preferência de forma correta e imediata (importante sobretudo pra quem
|
|
desligou por aracnofobia — a aranha precisa sumir na hora, não só na
|
|
próxima navegação). */
|
|
const seasonalToggleBtn = document.getElementById("seasonal-theme-toggle");
|
|
const seasonalToggleLabel = document.getElementById("seasonal-theme-toggle-label");
|
|
if (seasonalToggleBtn && seasonalToggleLabel && typeof pidSeasonalThemesOptedOut === "function") {
|
|
const syncSeasonalToggle = () => {
|
|
const optedOut = pidSeasonalThemesOptedOut();
|
|
seasonalToggleBtn.setAttribute("aria-pressed", String(!optedOut));
|
|
seasonalToggleLabel.textContent = optedOut ? "Inativo" : "Ativo";
|
|
};
|
|
|
|
syncSeasonalToggle();
|
|
|
|
seasonalToggleBtn.addEventListener("click", () => {
|
|
const optedOut = pidSeasonalThemesOptedOut();
|
|
pidSetSeasonalThemesOptedOut(!optedOut);
|
|
window.location.reload();
|
|
});
|
|
}
|
|
|
|
chipBtn.addEventListener("click", (event) => {
|
|
event.stopPropagation();
|
|
dropdown.hidden = !dropdown.hidden;
|
|
});
|
|
|
|
document.addEventListener("click", (event) => {
|
|
if (!dropdown.hidden && !dropdown.contains(event.target) && event.target !== chipBtn) {
|
|
dropdown.hidden = true;
|
|
}
|
|
});
|
|
|
|
const manageAccountModal = document.getElementById("manage-account-modal");
|
|
const manageAccountModalCard = document.getElementById("manage-account-modal-card");
|
|
const manageAccountChangePasswordBtn = document.getElementById("manage-account-change-password-btn");
|
|
const manageAccountCloseBtn = document.getElementById("manage-account-close-btn");
|
|
const manageAccountLideradosField = document.getElementById("manage-account-liderados-field");
|
|
const manageAccountLideradosError = document.getElementById("manage-account-liderados-error");
|
|
const manageAccountSaveBtn = document.getElementById("manage-account-save-btn");
|
|
|
|
// Redefinida abaixo quando o modal Gerenciar Usuário existe na página.
|
|
let lideradosAlterados = () => false;
|
|
|
|
if (manageAccountBtn && manageAccountModal) {
|
|
function departamentosTexto(usuario) {
|
|
return (usuario.departamentos || []).map((d) => d.nome).join(", ");
|
|
}
|
|
|
|
const seletorLiderados = pidCriarSeletorDuplo({
|
|
available: {
|
|
selectAll: document.getElementById("manage-account-liderados-available-select-all"),
|
|
sortHeader: document.getElementById("manage-account-liderados-available-sort-nome"),
|
|
searchPrincipal: document.getElementById("manage-account-liderados-available-search-nome"),
|
|
searchSecundaria: document.getElementById("manage-account-liderados-available-search-departamento"),
|
|
body: document.getElementById("manage-account-liderados-available-body"),
|
|
footer: document.getElementById("manage-account-liderados-available-footer"),
|
|
acaoBtn: document.getElementById("manage-account-liderados-available-link-btn"),
|
|
},
|
|
linked: {
|
|
selectAll: document.getElementById("manage-account-liderados-linked-select-all"),
|
|
sortHeader: document.getElementById("manage-account-liderados-linked-sort-nome"),
|
|
searchPrincipal: document.getElementById("manage-account-liderados-linked-search-nome"),
|
|
searchSecundaria: document.getElementById("manage-account-liderados-linked-search-departamento"),
|
|
body: document.getElementById("manage-account-liderados-linked-body"),
|
|
footer: document.getElementById("manage-account-liderados-linked-footer"),
|
|
acaoBtn: document.getElementById("manage-account-liderados-linked-unlink-btn"),
|
|
},
|
|
secundariaValor: departamentosTexto,
|
|
});
|
|
|
|
// Só há o que perder se o seletor de liderados foi carregado e a lista
|
|
// vinculada difere da que veio do servidor (me.liderados).
|
|
let lideradosCarregados = false;
|
|
|
|
function idsOrdenados(ids) {
|
|
return ids.map(Number).sort((a, b) => a - b).join(",");
|
|
}
|
|
|
|
lideradosAlterados = () => {
|
|
if (!lideradosCarregados) return false;
|
|
return idsOrdenados(seletorLiderados.getVinculadosIds()) !== idsOrdenados((me.liderados || []).map((u) => u.id));
|
|
};
|
|
|
|
manageAccountBtn.addEventListener("click", async () => {
|
|
dropdown.hidden = true;
|
|
manageAccountLideradosError.textContent = "";
|
|
lideradosCarregados = false;
|
|
if (me.lideranca) {
|
|
let usuarios;
|
|
try {
|
|
usuarios = (await pidApiRequest("/usuarios-resumo/")) || [];
|
|
} catch (e) {
|
|
await pidAlert(e.message, { titulo: "Não foi possível abrir Gerenciar Usuário" });
|
|
return;
|
|
}
|
|
manageAccountLideradosField.hidden = false;
|
|
manageAccountSaveBtn.hidden = false;
|
|
manageAccountModalCard.classList.add("modal-card--wide");
|
|
const candidatos = usuarios
|
|
.filter((u) => u.id !== me.id)
|
|
.slice()
|
|
.sort((a, b) => a.nome.localeCompare(b.nome));
|
|
seletorLiderados.setDados(candidatos, (me.liderados || []).map((u) => u.id));
|
|
lideradosCarregados = true;
|
|
} else {
|
|
manageAccountLideradosField.hidden = true;
|
|
manageAccountSaveBtn.hidden = true;
|
|
manageAccountModalCard.classList.remove("modal-card--wide");
|
|
}
|
|
manageAccountModal.hidden = false;
|
|
});
|
|
|
|
manageAccountCloseBtn.addEventListener("click", async () => {
|
|
if (lideradosAlterados()) {
|
|
const sair = await pidConfirm("Sair sem salvar as alterações?", {
|
|
titulo: "Sair sem salvar",
|
|
textoConfirmar: "Sair sem salvar",
|
|
perigoso: true,
|
|
});
|
|
if (!sair) return;
|
|
}
|
|
manageAccountModal.hidden = true;
|
|
});
|
|
|
|
manageAccountSaveBtn.addEventListener("click", async () => {
|
|
const liderados = seletorLiderados.getVinculadosIds();
|
|
const textoOriginal = manageAccountSaveBtn.textContent;
|
|
manageAccountSaveBtn.disabled = true;
|
|
manageAccountSaveBtn.textContent = "Salvando…";
|
|
manageAccountLideradosError.textContent = "";
|
|
try {
|
|
const atualizados = await pidApiRequest("/me/liderados/", { method: "PATCH", body: { liderados } });
|
|
me.liderados = atualizados;
|
|
manageAccountModal.hidden = true;
|
|
} catch (e) {
|
|
manageAccountLideradosError.textContent = e.message;
|
|
} finally {
|
|
manageAccountSaveBtn.disabled = false;
|
|
manageAccountSaveBtn.textContent = textoOriginal;
|
|
}
|
|
});
|
|
}
|
|
|
|
const passwordModal = document.getElementById("password-modal");
|
|
if (!passwordModal || !manageAccountChangePasswordBtn) return;
|
|
|
|
const currentInput = document.getElementById("pwd-current");
|
|
const newInput = document.getElementById("pwd-new");
|
|
const confirmInput = document.getElementById("pwd-confirm");
|
|
const pwdError = document.getElementById("pwd-error");
|
|
const pwdSaveBtn = document.getElementById("pwd-save-btn");
|
|
const pwdCancelBtn = document.getElementById("pwd-cancel-btn");
|
|
|
|
pidBindPasswordToggle(document.getElementById("pwd-current-toggle"), currentInput);
|
|
pidBindPasswordToggle(document.getElementById("pwd-new-toggle"), newInput);
|
|
pidBindPasswordToggle(document.getElementById("pwd-confirm-toggle"), confirmInput);
|
|
|
|
function closePasswordModal() {
|
|
passwordModal.hidden = true;
|
|
}
|
|
|
|
// Campo oculto de usuário (só existe em portal.html): dá ao gerenciador de
|
|
// senhas do navegador a qual conta a senha nova pertence.
|
|
const pwdUsernameInput = document.getElementById("pwd-username");
|
|
if (pwdUsernameInput) pwdUsernameInput.value = me.username || "";
|
|
|
|
manageAccountChangePasswordBtn.addEventListener("click", async () => {
|
|
// "Alterar senha" também fecha Gerenciar Usuário: mesmo aviso do Fechar.
|
|
if (lideradosAlterados()) {
|
|
const sair = await pidConfirm("Sair sem salvar as alterações?", {
|
|
titulo: "Sair sem salvar",
|
|
textoConfirmar: "Sair sem salvar",
|
|
perigoso: true,
|
|
});
|
|
if (!sair) return;
|
|
}
|
|
manageAccountModal.hidden = true;
|
|
currentInput.value = "";
|
|
newInput.value = "";
|
|
confirmInput.value = "";
|
|
currentInput.type = "password";
|
|
newInput.type = "password";
|
|
confirmInput.type = "password";
|
|
pwdError.textContent = "";
|
|
passwordModal.hidden = false;
|
|
currentInput.focus();
|
|
});
|
|
|
|
pwdCancelBtn.addEventListener("click", closePasswordModal);
|
|
|
|
pwdSaveBtn.addEventListener("click", async () => {
|
|
const current = currentInput.value;
|
|
const next = newInput.value;
|
|
const confirmValue = confirmInput.value;
|
|
|
|
if (!next) {
|
|
pwdError.textContent = "Informe a nova senha.";
|
|
return;
|
|
}
|
|
if (next !== confirmValue) {
|
|
pwdError.textContent = "A confirmação não corresponde à nova senha.";
|
|
return;
|
|
}
|
|
|
|
const textoOriginal = pwdSaveBtn.textContent;
|
|
pwdSaveBtn.disabled = true;
|
|
pwdSaveBtn.textContent = "Salvando…";
|
|
pwdError.textContent = "";
|
|
try {
|
|
await pidApiRequest("/me/senha/", {
|
|
method: "POST",
|
|
body: { senha_atual: current, nova_senha: next },
|
|
});
|
|
closePasswordModal();
|
|
await pidAlert("Senha alterada.", { titulo: "Senha alterada" });
|
|
} catch (e) {
|
|
pwdError.textContent = e.message;
|
|
} finally {
|
|
pwdSaveBtn.disabled = false;
|
|
pwdSaveBtn.textContent = textoOriginal;
|
|
}
|
|
});
|
|
});
|