Binayak Panigrahi commited on
Commit
1bb8e63
Β·
1 Parent(s): 01aa482

Add application file

Browse files
Files changed (1) hide show
  1. index.html +461 -0
index.html ADDED
@@ -0,0 +1,461 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Aadhaar Card OCR API - Test Dashboard</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body {
15
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
16
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
17
+ min-height: 100vh;
18
+ padding: 20px;
19
+ }
20
+
21
+ .container {
22
+ max-width: 1200px;
23
+ margin: 0 auto;
24
+ }
25
+
26
+ header {
27
+ background: white;
28
+ border-radius: 10px;
29
+ padding: 30px;
30
+ margin-bottom: 30px;
31
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
32
+ }
33
+
34
+ h1 {
35
+ color: #333;
36
+ margin-bottom: 10px;
37
+ }
38
+
39
+ .subtitle {
40
+ color: #666;
41
+ font-size: 14px;
42
+ }
43
+
44
+ .grid {
45
+ display: grid;
46
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
47
+ gap: 20px;
48
+ margin-bottom: 30px;
49
+ }
50
+
51
+ .card {
52
+ background: white;
53
+ border-radius: 10px;
54
+ padding: 25px;
55
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
56
+ }
57
+
58
+ .card h2 {
59
+ color: #667eea;
60
+ margin-bottom: 20px;
61
+ font-size: 18px;
62
+ border-bottom: 2px solid #667eea;
63
+ padding-bottom: 10px;
64
+ }
65
+
66
+ .form-group {
67
+ margin-bottom: 20px;
68
+ }
69
+
70
+ label {
71
+ display: block;
72
+ margin-bottom: 8px;
73
+ color: #333;
74
+ font-weight: 500;
75
+ font-size: 14px;
76
+ }
77
+
78
+ input[type="file"] {
79
+ display: block;
80
+ width: 100%;
81
+ padding: 10px;
82
+ border: 2px dashed #667eea;
83
+ border-radius: 5px;
84
+ cursor: pointer;
85
+ font-size: 14px;
86
+ color: #666;
87
+ }
88
+
89
+ input[type="file"]:hover {
90
+ border-color: #764ba2;
91
+ background-color: #f8f9ff;
92
+ }
93
+
94
+ button {
95
+ width: 100%;
96
+ padding: 12px;
97
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
98
+ color: white;
99
+ border: none;
100
+ border-radius: 5px;
101
+ font-size: 16px;
102
+ font-weight: 600;
103
+ cursor: pointer;
104
+ transition: transform 0.2s, box-shadow 0.2s;
105
+ }
106
+
107
+ button:hover {
108
+ transform: translateY(-2px);
109
+ box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
110
+ }
111
+
112
+ button:active {
113
+ transform: translateY(0);
114
+ }
115
+
116
+ button:disabled {
117
+ background: #ccc;
118
+ cursor: not-allowed;
119
+ transform: none;
120
+ }
121
+
122
+ .loading {
123
+ display: none;
124
+ text-align: center;
125
+ color: #667eea;
126
+ font-size: 14px;
127
+ margin-top: 10px;
128
+ }
129
+
130
+ .loading.active {
131
+ display: block;
132
+ }
133
+
134
+ .spinner {
135
+ display: inline-block;
136
+ width: 20px;
137
+ height: 20px;
138
+ border: 3px solid #f3f3f3;
139
+ border-top: 3px solid #667eea;
140
+ border-radius: 50%;
141
+ animation: spin 1s linear infinite;
142
+ margin-right: 8px;
143
+ vertical-align: middle;
144
+ }
145
+
146
+ @keyframes spin {
147
+ 0% { transform: rotate(0deg); }
148
+ 100% { transform: rotate(360deg); }
149
+ }
150
+
151
+ .results {
152
+ background: white;
153
+ border-radius: 10px;
154
+ padding: 25px;
155
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
156
+ }
157
+
158
+ .result-item {
159
+ margin-bottom: 20px;
160
+ padding: 15px;
161
+ background: #f8f9ff;
162
+ border-left: 4px solid #667eea;
163
+ border-radius: 5px;
164
+ }
165
+
166
+ .result-item.error {
167
+ border-left-color: #e74c3c;
168
+ background: #ffe6e6;
169
+ }
170
+
171
+ .result-item.success {
172
+ border-left-color: #27ae60;
173
+ background: #e6ffe6;
174
+ }
175
+
176
+ .result-item h3 {
177
+ color: #333;
178
+ font-size: 16px;
179
+ margin-bottom: 10px;
180
+ }
181
+
182
+ .result-field {
183
+ display: grid;
184
+ grid-template-columns: 120px 1fr;
185
+ gap: 10px;
186
+ margin-bottom: 8px;
187
+ font-size: 14px;
188
+ }
189
+
190
+ .result-label {
191
+ font-weight: 600;
192
+ color: #667eea;
193
+ }
194
+
195
+ .result-value {
196
+ color: #333;
197
+ word-break: break-all;
198
+ }
199
+
200
+ .error-message {
201
+ color: #e74c3c;
202
+ font-size: 14px;
203
+ margin-top: 10px;
204
+ }
205
+
206
+ .health-status {
207
+ display: inline-block;
208
+ padding: 5px 15px;
209
+ background: #27ae60;
210
+ color: white;
211
+ border-radius: 20px;
212
+ font-size: 12px;
213
+ font-weight: 600;
214
+ }
215
+
216
+ .health-status.error {
217
+ background: #e74c3c;
218
+ }
219
+
220
+ .hidden {
221
+ display: none;
222
+ }
223
+
224
+ @media (max-width: 768px) {
225
+ .grid {
226
+ grid-template-columns: 1fr;
227
+ }
228
+
229
+ .result-field {
230
+ grid-template-columns: 1fr;
231
+ }
232
+
233
+ header {
234
+ padding: 20px;
235
+ }
236
+
237
+ .card {
238
+ padding: 20px;
239
+ }
240
+ }
241
+ </style>
242
+ </head>
243
+ <body>
244
+ <div class="container">
245
+ <header>
246
+ <h1>🎨 Aadhaar Card OCR API</h1>
247
+ <p class="subtitle">Test Dashboard - Extract Aadhaar data from images and PDFs</p>
248
+ <div style="margin-top: 15px;">
249
+ Health: <span class="health-status" id="healthStatus">Checking...</span>
250
+ </div>
251
+ </header>
252
+
253
+ <div class="grid">
254
+ <!-- Image Upload - Front -->
255
+ <div class="card">
256
+ <h2>πŸ“Έ Extract Front (Image)</h2>
257
+ <form id="frontImageForm">
258
+ <div class="form-group">
259
+ <label for="frontImageFile">Upload Front Side Image</label>
260
+ <input type="file" id="frontImageFile" accept="image/*" required>
261
+ </div>
262
+ <button type="submit">Extract Front Data</button>
263
+ <div class="loading" id="frontImageLoading">
264
+ <span class="spinner"></span> Processing...
265
+ </div>
266
+ </form>
267
+ </div>
268
+
269
+ <!-- Image Upload - Back -->
270
+ <div class="card">
271
+ <h2>πŸ“Έ Extract Back (Image)</h2>
272
+ <form id="backImageForm">
273
+ <div class="form-group">
274
+ <label for="backImageFile">Upload Back Side Image</label>
275
+ <input type="file" id="backImageFile" accept="image/*" required>
276
+ </div>
277
+ <button type="submit">Extract Back Data</button>
278
+ <div class="loading" id="backImageLoading">
279
+ <span class="spinner"></span> Processing...
280
+ </div>
281
+ </form>
282
+ </div>
283
+
284
+ <!-- PDF Upload - Front -->
285
+ <div class="card">
286
+ <h2>πŸ“„ Extract Front (PDF)</h2>
287
+ <form id="frontPdfForm">
288
+ <div class="form-group">
289
+ <label for="frontPdfFile">Upload PDF with Front Side(s)</label>
290
+ <input type="file" id="frontPdfFile" accept=".pdf" required>
291
+ </div>
292
+ <button type="submit">Extract from PDF</button>
293
+ <div class="loading" id="frontPdfLoading">
294
+ <span class="spinner"></span> Processing...
295
+ </div>
296
+ </form>
297
+ </div>
298
+
299
+ <!-- PDF Upload - Back -->
300
+ <div class="card">
301
+ <h2>πŸ“„ Extract Back (PDF)</h2>
302
+ <form id="backPdfForm">
303
+ <div class="form-group">
304
+ <label for="backPdfFile">Upload PDF with Back Side(s)</label>
305
+ <input type="file" id="backPdfFile" accept=".pdf" required>
306
+ </div>
307
+ <button type="submit">Extract from PDF</button>
308
+ <div class="loading" id="backPdfLoading">
309
+ <span class="spinner"></span> Processing...
310
+ </div>
311
+ </form>
312
+ </div>
313
+ </div>
314
+
315
+ <!-- Results Section -->
316
+ <div class="results hidden" id="resultsSection">
317
+ <h2 style="margin-bottom: 20px; color: #333;">πŸ“Š Results</h2>
318
+ <div id="resultsContainer"></div>
319
+ </div>
320
+ </div>
321
+
322
+ <script>
323
+ const API_BASE = window.location.origin;
324
+
325
+ // Check health on load
326
+ window.addEventListener('load', checkHealth);
327
+
328
+ async function checkHealth() {
329
+ try {
330
+ const response = await fetch(`${API_BASE}/health`);
331
+ const data = await response.json();
332
+ const status = document.getElementById('healthStatus');
333
+ status.textContent = `βœ“ ${data.status}`;
334
+ status.classList.remove('error');
335
+ } catch (error) {
336
+ const status = document.getElementById('healthStatus');
337
+ status.textContent = 'βœ— Offline';
338
+ status.classList.add('error');
339
+ }
340
+ }
341
+
342
+ // Front Image Form
343
+ document.getElementById('frontImageForm').addEventListener('submit', async (e) => {
344
+ e.preventDefault();
345
+ await handleUpload('frontImage', '/extract-front', 'Front Image');
346
+ });
347
+
348
+ // Back Image Form
349
+ document.getElementById('backImageForm').addEventListener('submit', async (e) => {
350
+ e.preventDefault();
351
+ await handleUpload('backImage', '/extract-back', 'Back Image');
352
+ });
353
+
354
+ // Front PDF Form
355
+ document.getElementById('frontPdfForm').addEventListener('submit', async (e) => {
356
+ e.preventDefault();
357
+ await handleUpload('frontPdf', '/extract-pdf-front', 'Front PDF');
358
+ });
359
+
360
+ // Back PDF Form
361
+ document.getElementById('backPdfForm').addEventListener('submit', async (e) => {
362
+ e.preventDefault();
363
+ await handleUpload('backPdf', '/extract-pdf-back', 'Back PDF');
364
+ });
365
+
366
+ async function handleUpload(formId, endpoint, label) {
367
+ const fileInput = document.getElementById(`${formId}File`);
368
+ const loading = document.getElementById(`${formId}Loading`);
369
+ const file = fileInput.files[0];
370
+
371
+ if (!file) {
372
+ alert('Please select a file');
373
+ return;
374
+ }
375
+
376
+ const formData = new FormData();
377
+ formData.append('file', file);
378
+
379
+ loading.classList.add('active');
380
+
381
+ try {
382
+ const response = await fetch(`${API_BASE}${endpoint}`, {
383
+ method: 'POST',
384
+ body: formData
385
+ });
386
+
387
+ const data = await response.json();
388
+
389
+ if (!response.ok) {
390
+ throw new Error(data.detail || 'Request failed');
391
+ }
392
+
393
+ displayResults(data, label, response.ok);
394
+ fileInput.value = '';
395
+ } catch (error) {
396
+ displayResults({ error: error.message }, label, false);
397
+ } finally {
398
+ loading.classList.remove('active');
399
+ }
400
+ }
401
+
402
+ function displayResults(data, label, success) {
403
+ const resultsSection = document.getElementById('resultsSection');
404
+ const resultsContainer = document.getElementById('resultsContainer');
405
+
406
+ resultsSection.classList.remove('hidden');
407
+
408
+ let html = '';
409
+
410
+ if (Array.isArray(data)) {
411
+ data.forEach((item, index) => {
412
+ html += formatResultItem(item, `${label} - Item ${index + 1}`);
413
+ });
414
+ } else if (data.error) {
415
+ html = `<div class="result-item error">
416
+ <h3>${label}</h3>
417
+ <div class="error-message">❌ ${data.error}</div>
418
+ </div>`;
419
+ } else {
420
+ html = formatResultItem(data, label);
421
+ }
422
+
423
+ resultsContainer.insertAdjacentHTML('afterbegin', html);
424
+ }
425
+
426
+ function formatResultItem(item, label) {
427
+ const isError = item.error;
428
+ const itemClass = isError ? 'error' : 'success';
429
+ const icon = isError ? '❌' : 'βœ…';
430
+
431
+ let html = `<div class="result-item ${itemClass}">
432
+ <h3>${icon} ${label}</h3>`;
433
+
434
+ if (isError) {
435
+ html += `<div class="error-message">${item.error}</div>`;
436
+ if (item.page) {
437
+ html += `<div class="result-field">
438
+ <span class="result-label">Page:</span>
439
+ <span class="result-value">${item.page}</span>
440
+ </div>`;
441
+ }
442
+ } else {
443
+ // Display all fields dynamically
444
+ Object.entries(item).forEach(([key, value]) => {
445
+ if (key !== 'error' && value) {
446
+ const displayKey = key.replace(/_/g, ' ').charAt(0).toUpperCase() +
447
+ key.replace(/_/g, ' ').slice(1);
448
+ html += `<div class="result-field">
449
+ <span class="result-label">${displayKey}:</span>
450
+ <span class="result-value">${value}</span>
451
+ </div>`;
452
+ }
453
+ });
454
+ }
455
+
456
+ html += '</div>';
457
+ return html;
458
+ }
459
+ </script>
460
+ </body>
461
+ </html>