202 lines
6.0 KiB
HTML
Executable File
202 lines
6.0 KiB
HTML
Executable File
<!DOCTYPE html>
|
|
<html lang="pt-BR">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
<title>Processador de Faturas</title>
|
|
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600&display=swap" rel="stylesheet"/>
|
|
<style>
|
|
* { box-sizing: border-box; margin: 0; padding: 0; font-family: 'Montserrat', sans-serif; }
|
|
body { background-color: #f7f9fc; padding: 2rem; color: #333; }
|
|
|
|
.nav { display: flex; justify-content: space-between; align-items: center; margin-bottom: 2rem; }
|
|
.nav h1 { font-size: 1.5rem; color: #4361ee; }
|
|
.nav ul { display: flex; list-style: none; gap: 1.5rem; }
|
|
.nav li a { text-decoration: none; color: #333; font-weight: 600; }
|
|
.nav li a:hover { color: #4361ee; }
|
|
|
|
.upload-box {
|
|
background: #fff;
|
|
border: 2px dashed #ccc;
|
|
padding: 2rem;
|
|
text-align: center;
|
|
border-radius: 10px;
|
|
margin-bottom: 2rem;
|
|
}
|
|
.upload-box.dragover {
|
|
background-color: #eef2ff;
|
|
border-color: #4361ee;
|
|
}
|
|
|
|
.buttons { display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap; margin-bottom: 2rem; }
|
|
|
|
.btn {
|
|
padding: 0.75rem 1.5rem;
|
|
border: none;
|
|
border-radius: 8px;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
transition: all 0.2s ease-in-out;
|
|
}
|
|
.btn:hover { opacity: 0.9; }
|
|
.btn-primary { background-color: #4361ee; color: white; }
|
|
.btn-success { background-color: #198754; color: white; }
|
|
.btn-danger { background-color: #dc3545; color: white; }
|
|
.btn-secondary { background-color: #6c757d; color: white; }
|
|
|
|
table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
background: #fff;
|
|
border-radius: 10px;
|
|
overflow: hidden;
|
|
box-shadow: 0 0 10px rgba(0,0,0,0.05);
|
|
}
|
|
th, td {
|
|
padding: 1rem;
|
|
text-align: left;
|
|
border-bottom: 1px solid #eee;
|
|
}
|
|
th {
|
|
background-color: #f2f2f2;
|
|
font-size: 0.85rem;
|
|
color: #555;
|
|
text-transform: uppercase;
|
|
letter-spacing: 1px;
|
|
}
|
|
|
|
#file-input { display: none; }
|
|
|
|
.status-ok { color: #198754; }
|
|
.status-error { color: #dc3545; }
|
|
.status-warn { color: #ffc107; }
|
|
|
|
footer {
|
|
text-align: center;
|
|
margin-top: 3rem;
|
|
font-size: 0.8rem;
|
|
color: #aaa;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<nav class="nav">
|
|
<h1>📄 Processador de Faturas</h1>
|
|
<ul>
|
|
<li><a href="/">Upload</a></li>
|
|
<li><a href="/dashboard">Dashboard</a></li>
|
|
<li><a href="/relatorios">Relatórios</a></li>
|
|
<li><a href="/parametros">Parâmetros</a></li>
|
|
</ul>
|
|
</nav>
|
|
|
|
<div class="upload-box" id="upload-box">
|
|
<h3>Arraste faturas em PDF aqui ou clique para selecionar</h3>
|
|
<p style="color: gray; font-size: 0.9rem;">Apenas PDFs textuais (não escaneados)</p>
|
|
<br />
|
|
<button class="btn btn-primary" onclick="document.getElementById('file-input').click()">Selecionar Arquivos</button>
|
|
<input type="file" id="file-input" accept=".pdf" multiple onchange="handleFiles(this.files)" />
|
|
</div>
|
|
|
|
<div class="buttons">
|
|
<button class="btn btn-primary" onclick="processar()">Processar Faturas</button>
|
|
<button class="btn btn-danger" onclick="limpar()">Limpar Tudo</button>
|
|
<button class="btn btn-success" onclick="baixarPlanilha()">📥 Abrir Planilha</button>
|
|
<button class="btn btn-success" onclick="gerarRelatorio()">📊 Gerar Relatório</button>
|
|
</div>
|
|
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Arquivo</th>
|
|
<th>Status</th>
|
|
<th>Mensagem</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="file-table">
|
|
<tr><td colspan="3" style="text-align: center; color: #aaa;">Nenhum arquivo selecionado.</td></tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<footer>
|
|
Sistema desenvolvido para análise tributária de faturas (PIS/COFINS/ICMS) com correção SELIC.
|
|
</footer>
|
|
|
|
<script>
|
|
let arquivos = [];
|
|
let statusInterval = null;
|
|
const fileTable = document.getElementById('file-table');
|
|
|
|
function handleFiles(files) {
|
|
arquivos = [...arquivos, ...files];
|
|
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>';
|
|
}
|
|
|
|
async function processar() {
|
|
if (arquivos.length === 0) return alert("Nenhum arquivo selecionado.");
|
|
const formData = new FormData();
|
|
arquivos.forEach(file => formData.append("files", file));
|
|
|
|
await fetch("/upload-files", { method: "POST", body: formData });
|
|
await fetch("/process-queue", { method: "POST" });
|
|
arquivos = [];
|
|
statusInterval = setInterval(updateStatus, 1000);
|
|
}
|
|
|
|
async function updateStatus() {
|
|
const res = await fetch("/get-status");
|
|
const data = await res.json();
|
|
renderTable(data.files);
|
|
|
|
if (!data.is_processing && statusInterval) {
|
|
clearInterval(statusInterval);
|
|
}
|
|
}
|
|
|
|
function limpar() {
|
|
fetch("/clear-all", { method: "POST" });
|
|
arquivos = [];
|
|
renderTable();
|
|
}
|
|
|
|
function baixarPlanilha() {
|
|
window.open('/download-spreadsheet', '_blank');
|
|
}
|
|
|
|
function gerarRelatorio() {
|
|
window.open('/generate-report', '_blank');
|
|
}
|
|
|
|
const dropZone = document.getElementById('upload-box');
|
|
dropZone.addEventListener('dragover', (e) => {
|
|
e.preventDefault();
|
|
dropZone.classList.add('dragover');
|
|
});
|
|
dropZone.addEventListener('dragleave', () => {
|
|
dropZone.classList.remove('dragover');
|
|
});
|
|
dropZone.addEventListener('drop', (e) => {
|
|
e.preventDefault();
|
|
dropZone.classList.remove('dragover');
|
|
handleFiles(e.dataTransfer.files);
|
|
});
|
|
|
|
window.addEventListener('DOMContentLoaded', updateStatus);
|
|
</script>
|
|
</body>
|
|
</html>
|