passport-static / static /index.html
Hztech's picture
done
cd964f2 verified
Raw History Blame Contribute Delete
8.33 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Passport OCR Extractor</title>
<style>
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: #f4f7f6; color: #333; margin: 0; padding: 20px; }
.container { max-width: 1000px; margin: auto; background: white; padding: 30px; border-radius: 12px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); }
h1 { text-align: center; color: #2c3e50; margin-bottom: 30px; }
.controls { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 30px; }
.control-group { display: flex; flex-direction: column; }
label { font-weight: bold; margin-bottom: 8px; color: #555; }
select, input[type="file"] { padding: 10px; border: 1px solid #ddd; border-radius: 6px; }
button { background-color: #3498db; color: white; border: none; padding: 12px 25px; font-size: 16px; border-radius: 6px; cursor: pointer; transition: background 0.3s; margin-top: 20px; width: 100%; }
button:hover { background-color: #2980b9; }
button:disabled { background-color: #bdc3c7; cursor: not-allowed; }
#results { margin-top: 40px; }
.summary { display: flex; justify-content: space-around; margin-bottom: 20px; padding: 15px; background: #e8f4fd; border-radius: 8px; }
.summary-item { text-align: center; }
.summary-val { font-size: 24px; font-weight: bold; color: #2980b9; }
.summary-label { font-size: 12px; color: #7f8c8d; text-transform: uppercase; }
.table-container { overflow-x: auto; margin-top: 20px; border: 1px solid #eee; border-radius: 8px; }
table { width: 100%; border-collapse: collapse; font-size: 14px; }
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #eee; }
th { background-color: #f8f9fa; color: #2c3e50; }
.downloads { display: flex; gap: 15px; margin-top: 20px; justify-content: center; }
.download-btn { background-color: #27ae60; color: white; text-decoration: none; padding: 10px 20px; border-radius: 6px; font-weight: bold; }
.download-btn:hover { background-color: #219150; }
.loader { border: 4px solid #f3f3f3; border-top: 4px solid #3498db; border-radius: 50%; width: 30px; height: 30px; animation: spin 2s linear infinite; margin: 20px auto; display: none; }
@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
.checkbox-group { flex-direction: row; align-items: center; gap: 10px; cursor: pointer; }
.checkbox-group input { width: auto; }
</style>
</head>
<body>
<div class="container">
<h1>🛂 Passport OCR Extractor</h1>
<div class="controls">
<div class="control-group">
<label for="files">Upload Passport Files (Images or PDFs)</label>
<input type="file" id="files" multiple accept=".png,.jpg,.jpeg,.pdf,.webp">
</div>
<div class="control-group">
<label for="airline">Choose Airline Format</label>
<select id="airline">
<option value="Default">Default</option>
<option value="Fly Dubai">Fly Dubai</option>
<option value="Iraqi">Iraqi</option>
<option value="Fly Baghdad">Fly Baghdad</option>
</select>
<label class="checkbox-group" style="margin-top: 15px;">
<input type="checkbox" id="include_all"> Include all files in export
</label>
</div>
</div>
<button id="processBtn">Extract Data</button>
<div id="loader" class="loader"></div>
<div id="results" style="display: none;">
<div class="summary">
<div class="summary-item">
<div id="summaryTotal" class="summary-val">0</div>
<div class="summary-label">Total Files</div>
</div>
<div class="summary-item">
<div id="summarySuccess" class="summary-val">0</div>
<div class="summary-label">Success</div>
</div>
<div class="summary-item">
<div id="summaryFailed" class="summary-val">0</div>
<div class="summary-label">Failed</div>
</div>
</div>
<div class="downloads">
<a id="downloadCsv" href="#" class="download-btn">Download CSV</a>
<a id="downloadXlsx" href="#" class="download-btn">Download Excel</a>
</div>
<div class="table-container">
<table id="resultsTable">
<thead><tr id="tableHeader"></tr></thead>
<tbody id="tableBody"></tbody>
</table>
</div>
</div>
</div>
<script>
const processBtn = document.getElementById('processBtn');
const loader = document.getElementById('loader');
const results = document.getElementById('results');
const filesInput = document.getElementById('files');
const airlineSelect = document.getElementById('airline');
const includeAllCheckbox = document.getElementById('include_all');
processBtn.addEventListener('click', async () => {
const files = filesInput.files;
if (files.length === 0) {
alert('Please upload at least one file.');
return;
}
processBtn.disabled = true;
loader.style.display = 'block';
results.style.display = 'none';
const formData = new FormData();
for (let i = 0; i < files.length; i++) {
formData.append('files', files[i]);
}
formData.append('airline', airlineSelect.value);
formData.append('include_all', includeAllCheckbox.checked);
try {
const response = await fetch('/api/process', {
method: 'POST',
body: formData
});
if (!response.ok) throw new Error('Processing failed');
const result = await response.json();
displayResults(result);
} catch (error) {
alert('Error: ' + error.message);
} finally {
processBtn.disabled = false;
loader.style.display = 'none';
}
});
function displayResults(res) {
results.style.display = 'block';
document.getElementById('summaryTotal').innerText = res.summary.total;
document.getElementById('summarySuccess').innerText = res.summary.success;
document.getElementById('summaryFailed').innerText = res.summary.failed;
document.getElementById('downloadCsv').href = '/api/download/' + res.csv_id;
document.getElementById('downloadXlsx').href = '/api/download/' + res.xlsx_id;
const tableHeader = document.getElementById('tableHeader');
const tableBody = document.getElementById('tableBody');
tableHeader.innerHTML = '';
tableBody.innerHTML = '';
if (res.data.length > 0) {
const keys = Object.keys(res.data[0]);
keys.forEach(key => {
const th = document.createElement('th');
th.innerText = key;
tableHeader.appendChild(th);
});
res.data.forEach(row => {
const tr = document.createElement('tr');
keys.forEach(key => {
const td = document.createElement('td');
td.innerText = row[key] || '';
tr.appendChild(td);
});
tableBody.appendChild(tr);
});
}
}
</script>
</body>
</html>