portal_publico/static/js/confirm-modal.js

92 lines
3.7 KiB
JavaScript

// Modais de confirmação/aviso genéricos, no padrão visual do Portal —
// substituem window.confirm()/window.alert() nativos do navegador (pedido
// explícito do usuário: nenhum popup deve usar o diálogo nativo do browser,
// sempre um modal dentro do próprio Portal).
//
// `pidConfirm(mensagem, opcoes)` devolve uma Promise<boolean> (true se
// confirmado, false se cancelado ou fechado clicando fora) — chame com
// `await` no lugar de `window.confirm(...)`.
//
// `pidAlert(mensagem, opcoes)` devolve uma Promise<void>, resolvida quando o
// usuário fecha o aviso (um único botão, sem "Cancelar") — chame com
// `await` no lugar de `window.alert(...)`.
//
// `opcoes` (todas opcionais): { titulo, textoConfirmar, textoCancelar,
// perigoso } — `perigoso: true` troca o botão de ação pra
// `.btn-danger-outline` (mesmo estilo já usado em ações destrutivas como
// "Excluir selecionadas"), em vez do `.btn-solid` padrão. Em `pidAlert`,
// `textoConfirmar` é o texto do único botão (default "OK").
//
// Único modal, compartilhado pelos dois, criado sob demanda e empilhado por
// cima de qualquer modal já aberto (`.modal-overlay--top`, z-index maior) —
// não fecha o modal por trás, só pergunta/avisa e devolve a resposta.
function pidConfirmModal() {
let modal = document.getElementById("pid-confirm-modal");
if (modal) return modal;
modal = document.createElement("div");
modal.className = "modal-overlay modal-overlay--top";
modal.id = "pid-confirm-modal";
modal.hidden = true;
modal.innerHTML = `
<div class="modal-card">
<h2 class="modal-card__title confirm-modal__titulo"></h2>
<p class="modal-card__subtitle confirm-modal__mensagem"></p>
<div class="modal-actions">
<button type="button" class="btn-outline confirm-modal__cancelar-btn"></button>
<button type="button" class="confirm-modal__confirmar-btn"></button>
</div>
</div>
`;
document.body.appendChild(modal);
return modal;
}
function pidConfirmOuAlerta(mensagem, opcoes, modoAlerta) {
const modal = pidConfirmModal();
const titulo = modal.querySelector(".confirm-modal__titulo");
const mensagemEl = modal.querySelector(".confirm-modal__mensagem");
const cancelarBtn = modal.querySelector(".confirm-modal__cancelar-btn");
const confirmarBtn = modal.querySelector(".confirm-modal__confirmar-btn");
titulo.textContent = opcoes.titulo || (modoAlerta ? "Aviso" : "Confirmar ação");
mensagemEl.textContent = mensagem;
cancelarBtn.hidden = modoAlerta;
cancelarBtn.textContent = opcoes.textoCancelar || "Cancelar";
confirmarBtn.textContent = opcoes.textoConfirmar || (modoAlerta ? "OK" : "Confirmar");
confirmarBtn.className = `confirm-modal__confirmar-btn ${opcoes.perigoso ? "btn-danger-outline" : "btn-solid"}`;
modal.hidden = false;
return new Promise((resolve) => {
function finalizar(resultado) {
modal.hidden = true;
cancelarBtn.removeEventListener("click", onCancelar);
confirmarBtn.removeEventListener("click", onConfirmar);
modal.removeEventListener("click", onOverlayClick);
resolve(resultado);
}
function onCancelar() {
finalizar(false);
}
function onConfirmar() {
finalizar(true);
}
function onOverlayClick(event) {
if (event.target === modal) finalizar(false);
}
cancelarBtn.addEventListener("click", onCancelar);
confirmarBtn.addEventListener("click", onConfirmar);
modal.addEventListener("click", onOverlayClick);
});
}
function pidConfirm(mensagem, opcoes = {}) {
return pidConfirmOuAlerta(mensagem, opcoes, false);
}
function pidAlert(mensagem, opcoes = {}) {
return pidConfirmOuAlerta(mensagem, opcoes, true).then(() => undefined);
}