Docfile commited on
Commit
7d77f9b
·
verified ·
1 Parent(s): ebac722

Delete templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +0 -659
templates/index.html DELETED
@@ -1,659 +0,0 @@
1
-
2
- <!DOCTYPE html>
3
- <html lang="fr">
4
- <head>
5
- <meta charset="UTF-8">
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>FaceAI Pro - Démonstration de Reconnaissance Faciale</title>
8
- <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet">
9
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css">
10
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css">
11
- <style>
12
- :root {
13
- --primary-color: #2563eb; /* Bleu plus formel */
14
- --secondary-color: #1d4ed8; /* Bleu secondaire */
15
- --gray-dark: #1f2937;
16
- --gray-light: #f3f4f6;
17
- --font-sans: 'Inter', sans-serif; /* Police plus professionnelle */
18
- }
19
-
20
- body {
21
- font-family: var(--font-sans);
22
- background-color: var(--gray-light);
23
- color: var(--gray-dark);
24
- line-height: 1.6;
25
- }
26
-
27
- /* Animations */
28
- @keyframes pulse-border {
29
- 0% { box-shadow: 0 0 0 0 rgba(var(--primary-color), 0.7); }
30
- 70% { box-shadow: 0 0 0 10px rgba(var(--primary-color), 0); }
31
- 100% { box-shadow: 0 0 0 0 rgba(var(--primary-color), 0); }
32
- }
33
-
34
- @keyframes spin {
35
- 100% { transform: rotate(360deg); }
36
- }
37
-
38
- /* Composants */
39
- .container {
40
- max-width: 1200px;
41
- }
42
-
43
- .preview-container {
44
- position: relative;
45
- aspect-ratio: 1;
46
- background: white;
47
- border-radius: 0.5rem;
48
- overflow: hidden;
49
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
50
- }
51
-
52
- .preview-image {
53
- position: absolute;
54
- top: 0;
55
- left: 0;
56
- width: 100%;
57
- height: 100%;
58
- background-size: cover;
59
- background-position: center;
60
- transition: transform 0.2s ease;
61
- }
62
-
63
- .preview-container:hover .preview-image {
64
- transform: scale(1.03);
65
- }
66
-
67
- .delete-btn {
68
- position: absolute;
69
- bottom: 0.5rem;
70
- right: 0.5rem;
71
- background-color: rgba(220, 53, 69, 0.9); /* Red-500 with opacity */
72
- color: white;
73
- padding: 0.4rem 0.5rem;
74
- border-radius: 50%;
75
- opacity: 0;
76
- transition: opacity 0.2s ease;
77
- cursor: pointer;
78
- z-index: 10;
79
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
80
- }
81
-
82
- .preview-container:hover .delete-btn {
83
- opacity: 0.9;
84
- }
85
-
86
- .preview-container:hover .delete-btn:hover {
87
- background-color: rgba(220, 53, 69, 1);
88
- opacity: 1;
89
- }
90
-
91
- .loading-overlay {
92
- position: fixed;
93
- top: 0;
94
- left: 0;
95
- width: 100%;
96
- height: 100%;
97
- background: rgba(0, 0, 0, 0.8);
98
- display: none;
99
- justify-content: center;
100
- align-items: center;
101
- z-index: 1000;
102
- }
103
-
104
- .progress-ring {
105
- animation: spin 1.5s linear infinite;
106
- width: 60px;
107
- height: 60px;
108
- }
109
-
110
- .btn-primary {
111
- background-color: var(--primary-color);
112
- color: white;
113
- transition: all 0.2s ease;
114
- font-weight: 600;
115
- padding: 0.75rem 1.5rem;
116
- border-radius: 0.375rem;
117
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
118
- }
119
-
120
- .btn-primary:hover {
121
- background-color: var(--secondary-color);
122
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
123
- }
124
-
125
- .btn-primary:active {
126
- transform: translateY(1px);
127
- }
128
-
129
- .btn-secondary {
130
- background-color: #4b5563;
131
- color: white;
132
- transition: all 0.2s ease;
133
- font-weight: 600;
134
- padding: 0.75rem 1.5rem;
135
- border-radius: 0.375rem;
136
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
137
- }
138
-
139
- .btn-secondary:hover {
140
- background-color: #374151;
141
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
142
- }
143
-
144
- .result-card {
145
- border: 1px solid #e5e7eb;
146
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
147
- padding: 1.5rem;
148
- border-radius: 0.5rem;
149
- background-color: white;
150
- }
151
-
152
- .result-card.show {
153
- animation: fadeInUp 0.4s; /* Animation plus subtile */
154
- }
155
-
156
- @keyframes fadeInUp {
157
- from {
158
- opacity: 0;
159
- transform: translate3d(0, 20px, 0);
160
- }
161
- to {
162
- opacity: 1;
163
- transform: none;
164
- }
165
- }
166
-
167
- .camera-feed {
168
- border-radius: 0.5rem;
169
- transform: scaleX(-1);
170
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
171
- }
172
-
173
- .github-corner {
174
- position: fixed;
175
- top: 0;
176
- right: 0;
177
- width: 70px;
178
- height: 70px;
179
- z-index: 1001;
180
- }
181
-
182
- .github-corner:hover {
183
- transform: scale(1.05);
184
- transition: transform 0.2s ease;
185
- }
186
-
187
- .section-title {
188
- font-size: 1.75rem;
189
- font-weight: 700;
190
- color: var(--gray-dark);
191
- margin-bottom: 1.5rem;
192
- display: flex;
193
- align-items: center;
194
- border-bottom: 2px solid var(--primary-color);
195
- padding-bottom: 0.75rem;
196
- }
197
-
198
- .section-title i {
199
- color: var(--primary-color);
200
- margin-right: 1rem;
201
- font-size: 1.5rem;
202
- }
203
-
204
- .input-hidden {
205
- display: none;
206
- }
207
-
208
- .comparison-result {
209
- font-size: 1.2rem;
210
- margin-bottom: 0.75rem;
211
- }
212
-
213
- .comparison-result.positive {
214
- color: #22c55e; /* Vert plus formel */
215
- font-weight: 600;
216
- }
217
-
218
- .comparison-result.negative {
219
- color: #ef4444; /* Rouge plus formel */
220
- font-weight: 600;
221
- }
222
-
223
- .progress-bar {
224
- height: 1rem;
225
- background-color: #e5e7eb;
226
- border-radius: 0.5rem;
227
- margin-bottom: 1rem;
228
- overflow: hidden;
229
- }
230
-
231
- .progress-bar-fill {
232
- height: 100%;
233
- background-color: var(--primary-color);
234
- width: 0%;
235
- transition: width 0.5s ease;
236
- }
237
-
238
- .project-description {
239
- background-color: white;
240
- padding: 2.5rem;
241
- border-radius: 0.5rem;
242
- margin-bottom: 2.5rem;
243
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
244
- }
245
-
246
- .project-description h2 {
247
- font-size: 2.25rem;
248
- font-weight: 800;
249
- color: var(--gray-dark);
250
- margin-bottom: 1.5rem;
251
- line-height: 1.2;
252
- }
253
-
254
- .project-description p {
255
- font-size: 1.1rem;
256
- color: #4b5563;
257
- line-height: 1.7;
258
- }
259
-
260
- .project-description ul {
261
- list-style-type: disc;
262
- margin-left: 1.5rem;
263
- color: #4b5563;
264
- margin-top: 1rem;
265
- }
266
-
267
- .project-description ul li {
268
- margin-bottom: 0.75rem;
269
- font-size: 1.1rem;
270
- line-height: 1.7;
271
- }
272
- .project-description ul li ul{
273
- list-style-type: circle;
274
- }
275
-
276
- .tech-used {
277
- margin-top: 0.5rem;
278
- }
279
-
280
- /* Navigation */
281
- .navbar {
282
- background-color: white;
283
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
284
- padding: 1rem 1.5rem;
285
- }
286
-
287
- .navbar .container {
288
- display: flex;
289
- align-items: center;
290
- justify-content: space-between;
291
- }
292
-
293
- .navbar-brand {
294
- display: flex;
295
- align-items: center;
296
- font-weight: 800;
297
- font-size: 1.75rem;
298
- color: var(--gray-dark);
299
- }
300
-
301
- .navbar-brand i {
302
- color: var(--primary-color);
303
- margin-right: 1rem;
304
- font-size: 2rem;
305
- }
306
- .navbar-brand:hover{
307
- color: var(--secondary-color);
308
- transition: all 0.2s ease;
309
- }
310
-
311
- .navbar-links {
312
- display: flex;
313
- align-items: center;
314
- }
315
-
316
- .navbar-links a {
317
- color: #4b5563;
318
- font-weight: 500;
319
- margin-left: 2rem;
320
- transition: color 0.2s ease;
321
- }
322
-
323
- .navbar-links a:hover {
324
- color: var(--primary-color);
325
- }
326
- .font-bold{
327
- font-weight: 700;
328
- }
329
-
330
- /* Responsiveness */
331
- @media (max-width: 768px) {
332
- .preview-container {
333
- margin-bottom: 1rem;
334
- }
335
-
336
- .project-description {
337
- margin-bottom: 1.5rem;
338
- padding: 1.5rem;
339
- }
340
-
341
- .project-description h2 {
342
- font-size: 2rem;
343
- }
344
-
345
- .section-title {
346
- font-size: 1.5rem;
347
- }
348
-
349
- .section-title i {
350
- font-size: 1.25rem;
351
- }
352
-
353
- .navbar-brand {
354
- font-size: 1.5rem;
355
- }
356
-
357
- .navbar-brand i {
358
- font-size: 1.75rem;
359
- }
360
-
361
- .navbar-links a {
362
- margin-left: 1.5rem;
363
- }
364
- }
365
- </style>
366
- </head>
367
- <body class="bg-gray-100">
368
- <div class="loading-overlay">
369
- <svg class="progress-ring text-blue-500" viewBox="0 0 50 50">
370
- <circle cx="25" cy="25" r="20" fill="none" stroke="currentColor" stroke-width="5" stroke-dasharray="80, 200"/>
371
- </svg>
372
- </div>
373
-
374
- <!-- Navigation -->
375
- <nav class="navbar">
376
- <div class="container mx-auto">
377
- <a href="/" class="navbar-brand">
378
- <i class="fas fa-brain text-blue-600"></i>
379
- FaceAI Pro
380
- </a>
381
- <div class="navbar-links">
382
- <a href="#" class="hover:text-blue-600">
383
- <i class="fas fa-question-circle text-lg"></i>
384
- <span class="hidden md:inline-block ml-1">Aide</span>
385
- </a>
386
- <a href="#" class="hover:text-blue-600">
387
- <i class="fas fa-cog text-lg"></i>
388
- <span class="hidden md:inline-block ml-1">Paramètres</span>
389
- </a>
390
- </div>
391
- </div>
392
- </nav>
393
-
394
- <!-- Contenu principal -->
395
- <main class="container mx-auto p-6">
396
- <!-- Description du projet -->
397
- <div class="project-description">
398
- <h2 class="text-3xl font-extrabold text-gray-900 mb-4 tracking-tight">FaceAI Pro : Démonstration de Reconnaissance Faciale en Temps Réel</h2>
399
- <p class="text-gray-700">
400
- <strong class="font-bold">FaceAI Pro</strong> est une application web pour démontrer la reconnaissance faciale. Comparez deux visages et évaluez leur similarité en temps réel.
401
- </p>
402
- <p class="mt-4 text-gray-700">
403
- Explorez cette technologie et ses applications dans la sécurité et l'authentification.
404
- </p>
405
- <h3 class="text-xl font-bold text-gray-800 mt-8 mb-3">Fonctionnalités Clés :</h3>
406
- <ul class="text-gray-700">
407
- <li>Comparaison en temps réel de deux images de visages.</li>
408
- <li>Détection automatique des visages.</li>
409
- <li>Évaluation quantitative de la similarité (en pourcentage).</li>
410
- <li>Capture d'image via la caméra.</li>
411
- <li>Interface utilisateur simple et intuitive.</li>
412
- </ul>
413
- <h3 class="text-xl font-bold text-gray-800 mt-8 mb-3">Technologies Employées :</h3>
414
- <ul class="text-gray-700">
415
- <li><strong class="font-bold">Backend :</strong> <a href="https://flask.palletsprojects.com/" target="_blank" class="text-blue-600 hover:underline">Flask</a> (Python).</li>
416
- <li><strong class="font-bold">Reconnaissance Faciale :</strong> Algorithme de deep learning.</li>
417
- <li><strong class="font-bold">Frontend :</strong> HTML5, CSS3 (<a href="https://tailwindcss.com/" target="_blank" class="text-blue-600 hover:underline">Tailwind CSS</a>), JavaScript.</li>
418
- <li><strong class="font-bold">Icônes :</strong> <a href="https://fontawesome.com/" target="_blank" class="text-blue-600 hover:underline">Font Awesome</a>.</li>
419
- <li><strong class="font-bold">Animations :</strong> <a href="https://animate.style/" target="_blank" class="text-blue-600 hover:underline">Animate.css</a>.</li>
420
- </ul>
421
- <p class="mt-4 text-gray-700">
422
- Le code source est disponible sur GitHub : <a href="https://github.com/Yusufibin" target="_blank" class="text-blue-600 hover:underline">https://github.com/Yusufibin</a>.
423
- </p>
424
- </div>
425
- <div class="grid md:grid-cols-2 gap-8">
426
- <!-- Section de capture -->
427
- <div class="bg-white rounded-lg shadow-md p-6">
428
- <h2 class="section-title">
429
- <i class="fas fa-camera"></i>
430
- Capture d'Images
431
- </h2>
432
-
433
- <div class="space-y-4">
434
- <div class="flex space-x-4">
435
- <label for="fileInput" class="btn-primary text-white px-6 py-3 rounded-lg flex items-center cursor-pointer">
436
- <i class="fas fa-upload mr-2"></i>
437
- Importer des Images
438
- </label>
439
- <button id="cameraBtn" class="btn-secondary text-white px-6 py-3 rounded-lg flex items-center transition-all">
440
- <i class="fas fa-video mr-2"></i>
441
- Utiliser la Caméra
442
- </button>
443
- </div>
444
-
445
- <input type="file" id="fileInput" class="input-hidden" accept="image/*" multiple>
446
- <video id="video" class="camera-feed w-full hidden" autoplay muted playsinline></video>
447
-
448
- <div class="grid grid-cols-2 gap-4">
449
- <div class="preview-container">
450
- <div id="preview1" class="preview-image"></div>
451
- <button class="delete-btn" data-target="preview1" title="Supprimer">
452
- <i class="fas fa-times"></i>
453
- </button>
454
- </div>
455
- <div class="preview-container">
456
- <div id="preview2" class="preview-image"></div>
457
- <button class="delete-btn" data-target="preview2" title="Supprimer">
458
- <i class="fas fa-times"></i>
459
- </button>
460
- </div>
461
- </div>
462
- </div>
463
- </div>
464
-
465
- <!-- Section des résultats -->
466
- <div class="bg-white rounded-lg shadow-md p-6">
467
- <h2 class="section-title">
468
- <i class="fas fa-chart-bar"></i>
469
- Résultats de l'Analyse
470
- </h2>
471
-
472
- <div id="results" class="result-card">
473
- <div class="text-center text-gray-500">
474
- <i class="fas fa-upload text-4xl mb-3"></i>
475
- <p class="text-gray-600">Importez ou capturez deux images pour démarrer l'analyse.</p>
476
- </div>
477
- </div>
478
-
479
- <button id="compareBtn" class="btn-primary w-full mt-6 py-3 rounded-lg text-white font-semibold hidden">
480
- <i class="fas fa-sync-alt mr-2"></i>
481
- Lancer la Comparaison
482
- </button>
483
- </div>
484
- </div>
485
- </main>
486
-
487
- <!-- GitHub Corner -->
488
- <a href="https://github.com/Yusufibin" class="github-corner" target="_blank" aria-label="Voir le code source sur GitHub">
489
- <svg width="80" height="80" viewBox="0 0 250 250" style="fill:var(--gray-dark); color:#fff;">
490
- <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
491
- <path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>
492
- <path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path>
493
- </svg>
494
- </a>
495
-
496
- <!-- Script JavaScript -->
497
- <script>
498
- let uploadedImages = [];
499
-
500
- const fileInput = document.getElementById('fileInput');
501
- fileInput.addEventListener('change', handleImageUpload);
502
-
503
- function handleImageUpload(event) {
504
- const files = event.target.files;
505
- for (let i = 0; i < files.length; i++) {
506
- const file = files[i];
507
- if (uploadedImages.length < 2 && file.type.startsWith('image/')) {
508
- const reader = new FileReader();
509
- reader.onload = (e) => {
510
- const previewId = uploadedImages.length === 0 ? 'preview1' : 'preview2';
511
- const previewImg = document.getElementById(previewId);
512
- previewImg.style.backgroundImage = `url(${e.target.result})`;
513
- uploadedImages.push({ file: file, preview: previewId });
514
- updateCompareButtonState();
515
- };
516
- reader.readAsDataURL(file);
517
- }
518
- }
519
- }
520
-
521
- document.querySelectorAll('.delete-btn').forEach(button => {
522
- button.addEventListener('click', function() {
523
- const targetPreviewId = this.dataset.target;
524
- const targetPreview = document.getElementById(targetPreviewId);
525
- targetPreview.style.backgroundImage = '';
526
-
527
- uploadedImages = uploadedImages.filter(image => image.preview !== targetPreviewId);
528
-
529
- updateCompareButtonState();
530
- });
531
- });
532
-
533
- const cameraBtn = document.getElementById('cameraBtn');
534
- const video = document.getElementById('video');
535
- let stream = null;
536
-
537
- cameraBtn.addEventListener('click', async () => {
538
- if (stream) {
539
- // Arrêter la caméra
540
- stream.getTracks().forEach(track => track.stop());
541
- video.classList.add('hidden');
542
- cameraBtn.innerHTML = '<i class="fas fa-video mr-2"></i>Utiliser la Caméra';
543
- stream = null;
544
- } else {
545
- // Démarrer la caméra
546
- try {
547
- stream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: 'user' } });
548
- video.srcObject = stream;
549
- video.classList.remove('hidden');
550
- cameraBtn.innerHTML = '<i class="fas fa-times mr-2"></i>Arrêter la caméra';
551
- } catch (err) {
552
- console.error('Erreur lors de l\'accès à la caméra:', err);
553
- }
554
- }
555
- });
556
-
557
- video.addEventListener('click', () => {
558
- if (stream && uploadedImages.length < 2) {
559
- const canvas = document.createElement('canvas');
560
- canvas.width = video.videoWidth;
561
- canvas.height = video.videoHeight;
562
- const ctx = canvas.getContext('2d');
563
- ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
564
- canvas.toBlob(blob => {
565
- const file = new File([blob], `capture-${Date.now()}.jpg`, { type: 'image/jpeg' });
566
- const previewId = uploadedImages.length === 0 ? 'preview1' : 'preview2';
567
- const previewImg = document.getElementById(previewId);
568
- previewImg.style.backgroundImage = `url(${URL.createObjectURL(file)})`;
569
- uploadedImages.push({ file: file, preview: previewId });
570
- updateCompareButtonState();
571
- }, 'image/jpeg');
572
- }
573
- });
574
-
575
- const compareBtn = document.getElementById('compareBtn');
576
- compareBtn.addEventListener('click', () => {
577
- if (uploadedImages.length === 2) {
578
- showLoading();
579
- const formData = new FormData();
580
- formData.append('file1', uploadedImages[0].file);
581
- formData.append('file2', uploadedImages[1].file);
582
-
583
- fetch('/compare', {
584
- method: 'POST',
585
- body: formData
586
- })
587
- .then(response => response.json())
588
- .then(data => {
589
- showResults(data);
590
- })
591
- .catch(error => {
592
- console.error('Erreur lors de la comparaison:', error);
593
- showError(error);
594
- })
595
- .finally(() => {
596
- hideLoading();
597
- });
598
- }
599
- });
600
-
601
- function updateCompareButtonState() {
602
- compareBtn.classList.toggle('hidden', uploadedImages.length < 2);
603
- }
604
-
605
- function showResults(data) {
606
- const resultsDiv = document.getElementById('results');
607
- resultsDiv.classList.remove('show');
608
-
609
- setTimeout(() => {
610
- resultsDiv.innerHTML = `
611
- <div class="text-center">
612
- <div class="text-4xl mb-4 ${data.verified ? 'text-green-500' : 'text-red-500'}">
613
- <i class="fas ${data.verified ? 'fa-check-circle' : 'fa-times-circle'}"></i>
614
- </div>
615
- <h3 class="text-xl font-bold mb-2">
616
- ${data.verified ? 'Visages identiques' : 'Visages différents'}
617
- </h3>
618
- <div class="space-y-2">
619
- <p class="comparison-result ${data.verified ? 'positive' : 'negative'}">
620
- Similarité: <span class="font-semibold">${data.similarity}%</span>
621
- </p>
622
- <div class="progress-bar">
623
- <div class="progress-bar-fill" style="width: ${data.similarity}%; --progress-value: ${data.similarity};" data-progress="${data.similarity}"></div>
624
- </div>
625
- </div>
626
- </div>
627
- `;
628
- resultsDiv.classList.add('show');
629
- setTimeout(() => {
630
- const progressBarFill = resultsDiv.querySelector('.progress-bar-fill');
631
- progressBarFill.style.width = `${data.similarity}%`;
632
- }, 50);
633
- }, 300);
634
- }
635
-
636
- function showError(error) {
637
- const resultsDiv = document.getElementById('results');
638
- resultsDiv.classList.remove('show');
639
- setTimeout(() => {
640
- resultsDiv.innerHTML = `
641
- <div class="text-center text-red-500">
642
- <i class="fas fa-exclamation-triangle text-4xl mb-3"></i>
643
- <p>Erreur : ${error.message || 'Une erreur est survenue.'}</p>
644
- </div>
645
- `;
646
- resultsDiv.classList.add('show');
647
- }, 300);
648
- }
649
-
650
- function showLoading() {
651
- document.querySelector('.loading-overlay').style.display = 'flex';
652
- }
653
-
654
- function hideLoading() {
655
- document.querySelector('.loading-overlay').style.display = 'none';
656
- }
657
- </script>
658
- </body>
659
- </html>