Atualiza exibição do tempo por processo e garante consistência da estrutura em app/
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-07-28 22:31:31 -03:00
parent d863d7f9e2
commit f3c2b08a69
82 changed files with 183 additions and 7786 deletions

View File

@@ -25,6 +25,7 @@
<th>Arquivo</th>
<th>Status</th>
<th>Mensagem</th>
<th>Tempo</th>
</tr>
</thead>
<tbody id="file-table">
@@ -42,18 +43,31 @@
renderTable();
}
function renderTable(statusList = []) {
const rows = statusList.length ? statusList : arquivos.map(file => ({ nome: file.name, status: 'Aguardando', mensagem: '' }));
fileTable.innerHTML = rows.length
? rows.map(file => `
<tr>
<td>${file.nome}</td>
<td class="${file.status === 'Concluido' ? 'status-ok' : file.status === 'Erro' ? 'status-error' : 'status-warn'}">${file.status}</td>
<td>${file.mensagem || '---'}</td>
</tr>
`).join('')
: '<tr><td colspan="3" style="text-align:center; color: #aaa;">Nenhum arquivo selecionado.</td></tr>';
}
function renderTable(statusList = []) {
const rows = statusList.length ? statusList : arquivos.map(file => ({
nome: file.name,
status: 'Aguardando',
mensagem: ''
}));
fileTable.innerHTML = rows.length
? rows.map(file => {
const status = file.status || 'Aguardando';
const statusClass = status === 'Concluído' ? 'status-ok'
: status === 'Erro' ? 'status-error'
: status === 'Aguardando' ? 'status-warn'
: 'status-processing';
return `
<tr>
<td>${file.nome}</td>
<td class="${statusClass}">${status}</td>
<td>${file.mensagem || '---'}</td>
<td>${file.tempo || '---'}</td>
</tr>
`;
}).join('')
: '<tr><td colspan="3" style="text-align:center; color: #aaa;">Nenhum arquivo selecionado.</td></tr>';
}
async function processar(btn) {
if (arquivos.length === 0) return alert("Nenhum arquivo selecionado.");
@@ -65,11 +79,17 @@
try {
await fetch("/upload-files", { method: "POST", body: formData });
await fetch("/process-queue", { method: "POST" });
arquivos = [];
const response = await fetch("/process-queue", { method: "POST" });
if (!response.ok) {
const msg = await response.text();
throw new Error(`Erro no processamento: ${msg}`);
}
arquivos = []; // <- só limpa se o processamento for bem-sucedido
statusInterval = setInterval(updateStatus, 1000);
} catch (err) {
alert("Erro ao processar faturas.");
alert("Erro ao processar faturas:\n" + err.message);
} finally {
setTimeout(() => {
btn.innerText = "Processar Faturas";
@@ -78,6 +98,7 @@
}
}
async function updateStatus() {
const res = await fetch("/get-status");
const data = await res.json();
@@ -91,6 +112,7 @@
function limpar() {
fetch("/clear-all", { method: "POST" });
arquivos = [];
document.getElementById("file-input").value = null;
renderTable();
}
@@ -102,7 +124,7 @@
window.open('/generate-report', '_blank');
}
const dropZone = document.getElementById('upload-box');
const dropZone = document.body;
dropZone.addEventListener('dragover', (e) => {
e.preventDefault();
dropZone.classList.add('dragover');
@@ -117,6 +139,23 @@
});
window.addEventListener('DOMContentLoaded', updateStatus);
// Adiciona destaque visual à caixa ao arrastar arquivos na tela toda
window.addEventListener('dragover', (e) => {
e.preventDefault();
document.getElementById('upload-box').classList.add('dragover');
});
window.addEventListener('dragleave', () => {
document.getElementById('upload-box').classList.remove('dragover');
});
window.addEventListener('drop', (e) => {
e.preventDefault();
document.getElementById('upload-box').classList.remove('dragover');
handleFiles(e.dataTransfer.files);
});
</script>
<style>
@@ -179,6 +218,12 @@
.status-ok { color: #198754; }
.status-error { color: #dc3545; }
.status-warn { color: #ffc107; }
.status-processing {
color: #0d6efd; /* azul */
font-weight: bold;
}
</style>
{% endblock %}