Path: C:\
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Transvoyant | Processador de CSV</title>
<link rel="stylesheet" href="style.css">
<!-- Ionicons for beautiful icons -->
<script type="module" src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.esm.js"></script>
<script nomodule src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.js"></script>
</head>
<body>
<div class="bg-shapes">
<div class="shape shape-1"></div>
<div class="shape shape-2"></div>
</div>
<main>
<div class="card">
<div class="header">
<h1 class="title">Transvoyant</h1>
<p class="subtitle">Faça o upload do relatório bruto CSV</p>
</div>
<form id="uploadForm" enctype="multipart/form-data">
<div class="upload-area" id="dropArea">
<ion-icon name="cloud-upload-outline" class="upload-icon"></ion-icon>
<div class="upload-text">Arraste e solte seu CSV aqui</div>
<div class="upload-subtext">ou clique para selecionar do computador</div>
<input type="file" name="csv_file" id="fileInput" accept=".csv" required>
</div>
<div class="file-info" id="fileInfo">
<div style="display: flex; align-items: center; gap: 0.5rem;">
<ion-icon name="document-text-outline" style="font-size: 1.5rem; color: #60a5fa;"></ion-icon>
<span class="file-name" id="fileName">arquivo.csv</span>
</div>
</div>
<button type="submit" class="btn" id="submitBtn" disabled>
<span>Processar e Enviar</span>
<div class="loader" id="btnLoader"></div>
</button>
</form>
<div class="alert" id="alertBox"></div>
</div>
</main>
<script>
const form = document.getElementById('uploadForm');
const fileInput = document.getElementById('fileInput');
const dropArea = document.getElementById('dropArea');
const fileInfo = document.getElementById('fileInfo');
const fileName = document.getElementById('fileName');
const submitBtn = document.getElementById('submitBtn');
const btnLoader = document.getElementById('btnLoader');
const alertBox = document.getElementById('alertBox');
// Drag and Drop Logic
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
dropArea.addEventListener(eventName, preventDefaults, false);
});
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
['dragenter', 'dragover'].forEach(eventName => {
dropArea.addEventListener(eventName, () => dropArea.classList.add('dragover'), false);
});
['dragleave', 'drop'].forEach(eventName => {
dropArea.addEventListener(eventName, () => dropArea.classList.remove('dragover'), false);
});
dropArea.addEventListener('drop', (e) => {
const dt = e.dataTransfer;
const files = dt.files;
if (files.length) {
fileInput.files = files;
handleFiles();
}
});
fileInput.addEventListener('change', handleFiles);
function handleFiles() {
if (fileInput.files.length > 0) {
const file = fileInput.files[0];
if (!file.name.endsWith('.csv')) {
showAlert('Por favor, selecione um arquivo formato CSV.', 'error');
submitBtn.disabled = true;
fileInfo.classList.remove('active');
return;
}
fileName.textContent = file.name;
fileInfo.classList.add('active');
submitBtn.disabled = false;
alertBox.classList.remove('active');
} else {
fileInfo.classList.remove('active');
submitBtn.disabled = true;
}
}
form.addEventListener('submit', async (e) => {
e.preventDefault();
if (!fileInput.files.length) return;
// UI Loading update
submitBtn.disabled = true;
submitBtn.querySelector('span').textContent = 'Processando...';
btnLoader.style.display = 'block';
alertBox.classList.remove('active');
alertBox.className = 'alert';
const formData = new FormData(form);
try {
const response = await fetch('processar.php', {
method: 'POST',
body: formData
});
const result = await response.json();
if (result.status === 'success') {
showAlert(result.message, 'success');
} else if (result.status === 'warning') {
showAlert(result.message, 'warning'); // custom warning logic inside success box or error
alertBox.classList.add('alert-error'); // fallback
} else {
showAlert(result.message, 'error');
}
} catch (error) {
showAlert('Erro crítico ao contatar o servidor.\n' + error.message, 'error');
} finally {
// UI Reset
submitBtn.disabled = false;
submitBtn.querySelector('span').textContent = 'Processar e Enviar';
btnLoader.style.display = 'none';
}
});
function showAlert(msg, type) {
alertBox.innerHTML = `<pre>${msg}</pre>`;
alertBox.className = `alert alert-${type} active`;
}
</script>
</body>
</html>