Fix silent failure when loading pending campaign replies

carregarReplies() swallowed any fetch error, leaving whatever was already
in #pending-replies — on first load, the static "Nenhuma resposta
pendente." placeholder. A failed load was visually indistinguishable from
a genuine empty state, so a customer reply could go unnoticed with no
error surfaced (every other action in this file already toasts on
failure). Now shows an explicit error state and toasts, and the fetch
mock harness in campaign-ui.test.mjs gained toast-call tracking to prove it.

Found via a full-project audit.
This commit is contained in:
Gustavo
2026-07-31 22:06:30 -03:00
parent 0c36f27cb3
commit 2b83995446
2 changed files with 36 additions and 4 deletions
+8 -2
View File
@@ -219,11 +219,11 @@ window.campanhasInit = window.campanhasInit || (() => {
}
async function carregarReplies() {
const container = el('pending-replies');
try {
const campaigns = await API.get('/api/campaigns').then((r) => r.campaigns).catch(() => []);
const campaignNames = new Map(campaigns.map((c) => [c.id, c.name]));
const { pending } = await API.get('/api/campaigns/replies/pending');
const container = el('pending-replies');
if (!pending || !pending.length) {
container.replaceChildren(h('p', { class: 'muted' }, 'Nenhuma resposta pendente.'));
return;
@@ -240,7 +240,13 @@ window.campanhasInit = window.campanhasInit || (() => {
}, 'Classificar')
)
));
} catch { /* silêncio */ }
} catch (error) {
// Nunca deixar o placeholder de "nenhuma pendente" no lugar de um erro
// real de carregamento — os dois ficariam visualmente indistinguiveis e
// uma resposta de cliente poderia passar despercebida.
container.replaceChildren(h('p', { class: 'muted' }, 'Erro ao carregar respostas pendentes.'));
toast(`Erro ao carregar respostas pendentes: ${error.message}`);
}
}
function abrirStageDialog(leadId) {