AadharAPI / index.html
Binayak Panigrahi
Add application file
8976c96
Raw
History Blame Contribute Delete
16.1 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Aadhaar Card OCR API - Test Dashboard</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
header {
background: white;
border-radius: 10px;
padding: 30px;
margin-bottom: 30px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}
h1 {
color: #333;
margin-bottom: 10px;
}
.subtitle {
color: #666;
font-size: 14px;
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
margin-bottom: 30px;
}
.card {
background: white;
border-radius: 10px;
padding: 25px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}
.card h2 {
color: #667eea;
margin-bottom: 20px;
font-size: 18px;
border-bottom: 2px solid #667eea;
padding-bottom: 10px;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
color: #333;
font-weight: 500;
font-size: 14px;
}
input[type="file"] {
display: block;
width: 100%;
padding: 10px;
border: 2px dashed #667eea;
border-radius: 5px;
cursor: pointer;
font-size: 14px;
color: #666;
}
input[type="file"]:hover {
border-color: #764ba2;
background-color: #f8f9ff;
}
button {
width: 100%;
padding: 12px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 5px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
}
button:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
}
button:active {
transform: translateY(0);
}
button:disabled {
background: #ccc;
cursor: not-allowed;
transform: none;
}
.loading {
display: none;
text-align: center;
color: #667eea;
font-size: 14px;
margin-top: 10px;
}
.loading.active {
display: block;
}
.spinner {
display: inline-block;
width: 20px;
height: 20px;
border: 3px solid #f3f3f3;
border-top: 3px solid #667eea;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-right: 8px;
vertical-align: middle;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.results {
background: white;
border-radius: 10px;
padding: 25px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}
.result-item {
margin-bottom: 20px;
padding: 15px;
background: #f8f9ff;
border-left: 4px solid #667eea;
border-radius: 5px;
}
.result-item.error {
border-left-color: #e74c3c;
background: #ffe6e6;
}
.result-item.success {
border-left-color: #27ae60;
background: #e6ffe6;
}
.result-item h3 {
color: #333;
font-size: 16px;
margin-bottom: 10px;
}
.result-field {
display: grid;
grid-template-columns: 120px 1fr;
gap: 10px;
margin-bottom: 8px;
font-size: 14px;
}
.result-label {
font-weight: 600;
color: #667eea;
}
.result-value {
color: #333;
word-break: break-all;
}
.error-message {
color: #e74c3c;
font-size: 14px;
margin-top: 10px;
}
.health-status {
display: inline-block;
padding: 5px 15px;
background: #27ae60;
color: white;
border-radius: 20px;
font-size: 12px;
font-weight: 600;
}
.health-status.error {
background: #e74c3c;
}
.hidden {
display: none;
}
@media (max-width: 768px) {
.grid {
grid-template-columns: 1fr;
}
.result-field {
grid-template-columns: 1fr;
}
header {
padding: 20px;
}
.card {
padding: 20px;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>🎨 Aadhaar Card OCR API</h1>
<p class="subtitle">Test Dashboard - Extract Aadhaar data from images and PDFs</p>
<div style="margin-top: 15px;">
Health: <span class="health-status" id="healthStatus">Checking...</span>
</div>
</header>
<div class="grid">
<!-- Image Upload - Front -->
<div class="card">
<h2>πŸ“Έ Extract Front (Image or PDF)</h2>
<form id="frontImageForm">
<div class="form-group">
<label for="frontImageFile">Upload Front Side Image or PDF</label>
<input type="file" id="frontImageFile" accept="image/*,.pdf" required>
</div>
<button type="submit">Extract Front Data</button>
<div class="loading" id="frontImageLoading">
<span class="spinner"></span> Processing...
</div>
</form>
</div>
<!-- Image Upload - Back -->
<div class="card">
<h2>πŸ“Έ Extract Back (Image or PDF)</h2>
<form id="backImageForm">
<div class="form-group">
<label for="backImageFile">Upload Back Side Image or PDF</label>
<input type="file" id="backImageFile" accept="image/*,.pdf" required>
</div>
<button type="submit">Extract Back Data</button>
<div class="loading" id="backImageLoading">
<span class="spinner"></span> Processing...
</div>
</form>
</div>
<!-- PDF Upload -->
<div class="card">
<h2>πŸ“„ Extract from PDF (Front & Back)</h2>
<form id="pdfForm">
<div class="form-group">
<label for="pdfFile">Upload PDF with Aadhaar Cards (Front & Back)</label>
<input type="file" id="pdfFile" accept=".pdf" required>
</div>
<button type="submit">Extract from PDF</button>
<div class="loading" id="pdfLoading">
<span class="spinner"></span> Processing...
</div>
</form>
</div>
</div>
<!-- Results Section -->
<div class="results hidden" id="resultsSection">
<h2 style="margin-bottom: 20px; color: #333;">πŸ“Š Results</h2>
<div id="resultsContainer"></div>
</div>
</div>
<script>
const API_BASE = window.location.origin;
// Check health on load
window.addEventListener('load', checkHealth);
async function checkHealth() {
try {
const response = await fetch(`${API_BASE}/health`);
const data = await response.json();
const status = document.getElementById('healthStatus');
status.textContent = `βœ“ ${data.status}`;
status.classList.remove('error');
} catch (error) {
const status = document.getElementById('healthStatus');
status.textContent = 'βœ— Offline';
status.classList.add('error');
}
}
// Front Image Form
document.getElementById('frontImageForm').addEventListener('submit', async (e) => {
e.preventDefault();
await handleUpload('frontImage', '/extract-front', 'Front Image');
});
// Back Image Form
document.getElementById('backImageForm').addEventListener('submit', async (e) => {
e.preventDefault();
await handleUpload('backImage', '/extract-back', 'Back Image');
});
// PDF Form
document.getElementById('pdfForm').addEventListener('submit', async (e) => {
e.preventDefault();
await handleUpload('pdf', '/extract-pdf', 'PDF');
});
async function handleUpload(formId, endpoint, label) {
const fileInput = document.getElementById(`${formId}File`);
const loading = document.getElementById(`${formId}Loading`);
const file = fileInput.files[0];
if (!file) {
alert('Please select a file');
return;
}
const formData = new FormData();
formData.append('file', file);
loading.classList.add('active');
try {
const response = await fetch(`${API_BASE}${endpoint}`, {
method: 'POST',
body: formData
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.detail || 'Request failed');
}
displayResults(data, label, response.ok);
fileInput.value = '';
} catch (error) {
displayResults({ error: error.message }, label, false);
} finally {
loading.classList.remove('active');
}
}
function displayResults(data, label, success) {
const resultsSection = document.getElementById('resultsSection');
const resultsContainer = document.getElementById('resultsContainer');
resultsSection.classList.remove('hidden');
let html = '';
if (Array.isArray(data)) {
data.forEach((item, index) => {
html += formatResultItem(item, `${label} - Item ${index + 1}`);
});
} else if (data.error) {
html = `<div class="result-item error">
<h3>${label}</h3>
<div class="error-message">❌ ${data.error}</div>
</div>`;
} else {
html = formatResultItem(data, label);
}
resultsContainer.insertAdjacentHTML('afterbegin', html);
}
function formatResultItem(item, label) {
const isError = item.error;
const itemClass = isError ? 'error' : 'success';
const icon = isError ? '❌' : 'βœ…';
let html = `<div class="result-item ${itemClass}">
<h3>${icon} ${label}</h3>`;
if (isError) {
html += `<div class="error-message">${item.error}</div>`;
if (item.page) {
html += `<div class="result-field">
<span class="result-label">Page:</span>
<span class="result-value">${item.page}</span>
</div>`;
}
} else {
// Display page number
if (item.page) {
html += `<div class="result-field">
<span class="result-label">Page:</span>
<span class="result-value">${item.page}</span>
</div>`;
}
// Display front data if available
if (item.front_data) {
html += `<div style="margin-top: 12px; padding-top: 12px; border-top: 1px solid #ddd;">
<div style="font-weight: 600; color: #667eea; margin-bottom: 8px;">πŸ“‹ Front Side Data</div>`;
Object.entries(item.front_data).forEach(([key, value]) => {
if (value) {
const displayKey = key.replace(/_/g, ' ').charAt(0).toUpperCase() +
key.replace(/_/g, ' ').slice(1);
html += `<div class="result-field">
<span class="result-label">${displayKey}:</span>
<span class="result-value">${value}</span>
</div>`;
}
});
html += `</div>`;
}
if (item.front_error) {
html += `<div style="margin-top: 8px; color: #e74c3c; font-size: 13px;">⚠ Front extraction: ${item.front_error}</div>`;
}
// Display back data if available
if (item.back_data) {
html += `<div style="margin-top: 12px; padding-top: 12px; border-top: 1px solid #ddd;">
<div style="font-weight: 600; color: #667eea; margin-bottom: 8px;">πŸ—Ί Back Side Data</div>`;
Object.entries(item.back_data).forEach(([key, value]) => {
if (value) {
const displayKey = key.replace(/_/g, ' ').charAt(0).toUpperCase() +
key.replace(/_/g, ' ').slice(1);
html += `<div class="result-field">
<span class="result-label">${displayKey}:</span>
<span class="result-value">${value}</span>
</div>`;
}
});
html += `</div>`;
}
if (item.back_error) {
html += `<div style="margin-top: 8px; color: #e74c3c; font-size: 13px;">⚠ Back extraction: ${item.back_error}</div>`;
}
// Display other fields dynamically (non-front, non-back data)
Object.entries(item).forEach(([key, value]) => {
if (key !== 'error' && key !== 'page' && key !== 'front_data' && key !== 'back_data' &&
key !== 'front_error' && key !== 'back_error' && value) {
const displayKey = key.replace(/_/g, ' ').charAt(0).toUpperCase() +
key.replace(/_/g, ' ').slice(1);
html += `<div class="result-field">
<span class="result-label">${displayKey}:</span>
<span class="result-value">${value}</span>
</div>`;
}
});
}
html += '</div>';
return html;
}
</script>
</body>
</html>