Docfile commited on
Commit
637ab00
·
verified ·
1 Parent(s): 58ef26b

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +160 -171
templates/index.html CHANGED
@@ -1,93 +1,34 @@
1
  <!DOCTYPE html>
2
  <html lang="fr">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Mariam Espagnol - Analyse de Documents</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
8
- <script src="https://unpkg.com/[email protected]/marked.min.js"></script>
9
- <script src="https://cdnjs.cloudflare.com/ajax/libs/prismjs/1.24.1/prism.min.js"></script>
10
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prismjs/1.24.1/themes/prism.min.css">
11
- <style>
12
- @import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700&family=Poppins:wght@300;400;500;600&display=swap');
 
 
 
13
 
14
- .fade-in {
15
- animation: fadeIn 0.5s ease-in;
16
- }
17
-
18
- .slide-up {
19
- animation: slideUp 0.5s ease-out;
20
- }
21
-
22
- @keyframes fadeIn {
23
- from { opacity: 0; }
24
- to { opacity: 1; }
25
- }
26
-
27
- @keyframes slideUp {
28
- from { transform: translateY(20px); opacity: 0; }
29
- to { transform: translateY(0); opacity: 1; }
30
- }
31
-
32
- .gradient-text {
33
- background: linear-gradient(45deg, #FF6B6B, #4ECDC4);
34
- -webkit-background-clip: text;
35
- background-clip: text;
36
- color: transparent;
37
- }
38
 
39
- .upload-zone {
40
- background: linear-gradient(145deg, #ffffff, #f3f4f6);
41
- box-shadow: 20px 20px 60px #d1d1d1,
42
- -20px -20px 60px #ffffff;
43
- }
44
 
45
- .upload-zone:hover {
46
- transform: scale(1.01);
47
- transition: all 0.3s ease;
48
- }
49
 
50
- .waves {
51
- position: absolute;
52
- bottom: 0;
53
- left: 0;
54
- width: 100%;
55
- overflow: hidden;
56
- line-height: 0;
57
- transform: rotate(180deg);
58
- }
59
-
60
- .waves svg {
61
- position: relative;
62
- display: block;
63
- width: calc(100% + 1.3px);
64
- height: 150px;
65
- }
66
-
67
- .prose {
68
- max-width: none;
69
- color: #374151;
70
- }
71
-
72
- .prose h1, .prose h2, .prose h3 {
73
- color: #1F2937;
74
- font-family: 'Playfair Display', serif;
75
- margin-top: 2em;
76
- margin-bottom: 1em;
77
- }
78
-
79
- .prose p {
80
- margin-bottom: 1.5em;
81
- line-height: 1.8;
82
- }
83
- </style>
84
- </head>
85
  <body class="bg-gradient-to-br from-gray-50 to-gray-100 min-h-screen relative">
86
- <div class="waves">
87
- <svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 120" preserveAspectRatio="none">
88
- <path d="M321.39,56.44c58-10.79,114.16-30.13,172-41.86,82.39-16.72,168.19-17.73,250.45-.39C823.78,31,906.67,72,985.66,92.83c70.05,18.48,146.53,26.09,214.34,3V0H0V27.35A600.21,600.21,0,0,0,321.39,56.44Z" class="fill-indigo-50"></path>
89
- </svg>
90
- </div>
91
 
92
  <div class="max-w-6xl mx-auto px-4 py-12 relative z-10">
93
  <!-- Header -->
@@ -102,23 +43,44 @@
102
 
103
  <!-- Main Content -->
104
  <div class="bg-white rounded-2xl shadow-xl p-6 md:p-8 mb-8 slide-up">
105
- <!-- File Type Selection -->
106
- <div class="mb-8">
107
- <label class="block text-lg font-medium text-gray-700 mb-4">Type de document</label>
108
- <div class="flex gap-6">
109
- <label class="relative flex items-center group cursor-pointer">
110
- <input type="radio" name="fileType" value="image" checked
111
- class="peer sr-only">
112
- <div class="w-6 h-6 border-2 border-gray-300 rounded-full peer-checked:border-indigo-500 peer-checked:bg-indigo-500 transition-all"></div>
113
- <span class="ml-3 text-gray-700 group-hover:text-indigo-500 transition-colors">Image</span>
114
- </label>
115
- <label class="relative flex items-center group cursor-pointer">
116
- <input type="radio" name="fileType" value="text"
117
- class="peer sr-only">
118
- <div class="w-6 h-6 border-2 border-gray-300 rounded-full peer-checked:border-indigo-500 peer-checked:bg-indigo-500 transition-all"></div>
119
- <span class="ml-3 text-gray-700 group-hover:text-indigo-500 transition-colors">Texte</span>
120
- </label>
121
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  </div>
123
 
124
  <!-- Upload Zone -->
@@ -130,13 +92,10 @@
130
  </svg>
131
  </div>
132
  <div class="text-sm text-gray-600">
133
- <label class="relative cursor-pointer rounded-md font-medium text-indigo-600 hover:text-indigo-500 focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-indigo-500">
134
- <span>Déposez votre fichier ici</span>
135
- <input id="file-upload" name="file" type="file" class="sr-only">
136
- </label>
137
- <p class="pl-1">ou cliquez pour sélectionner</p>
138
  </div>
139
- <p class="text-xs text-gray-500">PNG, JPG, GIF, PDF, TXT jusqu'à 10MB</p>
140
  </div>
141
  </div>
142
 
@@ -149,6 +108,15 @@
149
  </div>
150
  </div>
151
 
 
 
 
 
 
 
 
 
 
152
  <!-- Analysis Results -->
153
  <div id="results" class="mt-12 hidden slide-up">
154
  <h3 class="text-xl font-medium text-gray-900 mb-6">Analyse détaillée</h3>
@@ -168,23 +136,99 @@
168
  </div>
169
 
170
  <script>
171
- document.addEventListener('DOMContentLoaded', function() {
172
- const uploadZone = document.querySelector('.upload-zone');
173
- const fileInput = document.getElementById('file-upload');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
  const preview = document.getElementById('preview');
175
  const imagePreview = document.getElementById('image-preview');
176
  const textPreview = document.getElementById('text-preview');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  const results = document.getElementById('results');
178
  const analysisContent = document.getElementById('analysis-content');
179
- const loading = document.getElementById('loading');
180
 
181
- // Configuration de marked pour le rendu Markdown
182
- marked.setOptions({
183
- breaks: true,
184
- gfm: true,
185
- headerIds: true,
186
- sanitize: false
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  });
 
 
 
 
 
 
188
 
189
  uploadZone.addEventListener('click', () => fileInput.click());
190
 
@@ -207,62 +251,7 @@
207
  fileInput.addEventListener('change', (e) => {
208
  if (e.target.files.length) handleFile(e.target.files[0]);
209
  });
210
-
211
- function handleFile(file) {
212
- const fileType = document.querySelector('input[name="fileType"]:checked').value;
213
-
214
- // Animation de l'aperçu
215
- preview.classList.remove('hidden');
216
- preview.classList.add('fade-in');
217
-
218
- if (fileType === 'image') {
219
- imagePreview.classList.remove('hidden');
220
- textPreview.classList.add('hidden');
221
- const reader = new FileReader();
222
- reader.onload = (e) => {
223
- imagePreview.src = e.target.result;
224
- imagePreview.classList.add('fade-in');
225
- };
226
- reader.readAsDataURL(file);
227
- } else {
228
- imagePreview.classList.add('hidden');
229
- textPreview.classList.remove('hidden');
230
- const reader = new FileReader();
231
- reader.onload = (e) => {
232
- textPreview.textContent = e.target.result;
233
- textPreview.classList.add('fade-in');
234
- };
235
- reader.readAsText(file);
236
- }
237
-
238
- const formData = new FormData();
239
- formData.append('file', file);
240
- formData.append('fileType', fileType);
241
-
242
- loading.classList.remove('hidden');
243
- loading.classList.add('fade-in');
244
-
245
- fetch('/upload', {
246
- method: 'POST',
247
- body: formData
248
- })
249
- .then(response => response.json())
250
- .then(data => {
251
- loading.classList.add('hidden');
252
- results.classList.remove('hidden');
253
- results.classList.add('slide-up');
254
- // Convertir le Markdown en HTML
255
- analysisContent.innerHTML = marked.parse(data.analysis);
256
- // Activer la coloration syntaxique
257
- Prism.highlightAll();
258
- })
259
- .catch(error => {
260
- loading.classList.add('hidden');
261
- alert('Une erreur est survenue lors de l\'analyse. Veuillez réessayer.');
262
- console.error('Error:', error);
263
- });
264
- }
265
  });
266
  </script>
267
  </body>
268
- </html>
 
1
  <!DOCTYPE html>
2
  <html lang="fr">
3
+ <!-- [Head section reste identique jusqu'aux styles] -->
4
+ <style>
5
+ /* [Styles précédents restent identiques] */
6
+
7
+ .button-submit {
8
+ background: linear-gradient(45deg, #4F46E5, #818CF8);
9
+ transition: all 0.3s ease;
10
+ }
11
+
12
+ .button-submit:hover {
13
+ transform: translateY(-2px);
14
+ box-shadow: 0 10px 20px rgba(79, 70, 229, 0.2);
15
+ }
16
 
17
+ .option-card {
18
+ transition: all 0.3s ease;
19
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
+ .option-card:hover {
22
+ transform: translateY(-5px);
23
+ }
 
 
24
 
25
+ .file-input {
26
+ display: none;
27
+ }
28
+ </style>
29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  <body class="bg-gradient-to-br from-gray-50 to-gray-100 min-h-screen relative">
31
+ <!-- [Waves section reste identique] -->
 
 
 
 
32
 
33
  <div class="max-w-6xl mx-auto px-4 py-12 relative z-10">
34
  <!-- Header -->
 
43
 
44
  <!-- Main Content -->
45
  <div class="bg-white rounded-2xl shadow-xl p-6 md:p-8 mb-8 slide-up">
46
+ <!-- Document Type Selection -->
47
+ <div class="mb-8 grid md:grid-cols-2 gap-6">
48
+ <div class="option-card p-6 rounded-xl border-2 border-gray-200 hover:border-indigo-500 cursor-pointer transition-all"
49
+ onclick="selectDocType('iconographic')">
50
+ <input type="radio" name="docType" value="iconographic" class="sr-only" checked>
51
+ <div class="flex items-center mb-4">
52
+ <svg class="w-8 h-8 text-indigo-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
53
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/>
54
+ </svg>
55
+ <h3 class="ml-3 text-lg font-semibold">Document Iconographique</h3>
56
+ </div>
57
+ <p class="text-gray-600 text-sm">Images, photos, illustrations, publicités, etc.</p>
 
 
 
 
58
  </div>
59
+
60
+ <div class="option-card p-6 rounded-xl border-2 border-gray-200 hover:border-indigo-500 cursor-pointer transition-all"
61
+ onclick="selectDocType('textual')">
62
+ <input type="radio" name="docType" value="textual" class="sr-only">
63
+ <div class="flex items-center mb-4">
64
+ <svg class="w-8 h-8 text-indigo-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
65
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
66
+ </svg>
67
+ <h3 class="ml-3 text-lg font-semibold">Document Textuel</h3>
68
+ </div>
69
+ <p class="text-gray-600 text-sm">Textes, articles, documents écrits, etc.</p>
70
+ </div>
71
+ </div>
72
+
73
+ <!-- File Selection -->
74
+ <div class="mb-8">
75
+ <button onclick="openFileSelection()" class="w-full py-4 px-6 rounded-xl bg-indigo-50 hover:bg-indigo-100 transition-colors flex items-center justify-center gap-3">
76
+ <svg class="w-6 h-6 text-indigo-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
77
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12"/>
78
+ </svg>
79
+ <span class="text-indigo-700 font-medium">Sélectionner depuis la galerie</span>
80
+ </button>
81
+
82
+ <input type="file" id="file-upload" class="file-input" accept="image/*,text/*"
83
+ capture="environment" multiple>
84
  </div>
85
 
86
  <!-- Upload Zone -->
 
92
  </svg>
93
  </div>
94
  <div class="text-sm text-gray-600">
95
+ <p>Déposez votre fichier ici</p>
96
+ <p class="text-xs text-gray-500 mt-2">ou</p>
97
+ <p class="text-indigo-600 font-medium mt-2">Cliquez pour sélectionner</p>
 
 
98
  </div>
 
99
  </div>
100
  </div>
101
 
 
108
  </div>
109
  </div>
110
 
111
+ <!-- Submit Button -->
112
+ <div class="mt-8">
113
+ <button id="submit-button"
114
+ class="button-submit w-full py-4 px-8 rounded-xl text-white font-medium text-lg disabled:opacity-50 disabled:cursor-not-allowed hidden"
115
+ onclick="submitAnalysis()">
116
+ Analyser le document
117
+ </button>
118
+ </div>
119
+
120
  <!-- Analysis Results -->
121
  <div id="results" class="mt-12 hidden slide-up">
122
  <h3 class="text-xl font-medium text-gray-900 mb-6">Analyse détaillée</h3>
 
136
  </div>
137
 
138
  <script>
139
+ let selectedFile = null;
140
+
141
+ function selectDocType(type) {
142
+ document.querySelectorAll('.option-card').forEach(card => {
143
+ card.classList.remove('border-indigo-500');
144
+ card.classList.add('border-gray-200');
145
+ });
146
+
147
+ const selectedCard = document.querySelector(`[onclick="selectDocType('${type}')"]`);
148
+ selectedCard.classList.remove('border-gray-200');
149
+ selectedCard.classList.add('border-indigo-500');
150
+
151
+ const radio = selectedCard.querySelector('input[type="radio"]');
152
+ radio.checked = true;
153
+ }
154
+
155
+ function openFileSelection() {
156
+ document.getElementById('file-upload').click();
157
+ }
158
+
159
+ function handleFile(file) {
160
+ selectedFile = file;
161
+ const submitButton = document.getElementById('submit-button');
162
+ submitButton.classList.remove('hidden');
163
+
164
+ // Preview logic
165
  const preview = document.getElementById('preview');
166
  const imagePreview = document.getElementById('image-preview');
167
  const textPreview = document.getElementById('text-preview');
168
+
169
+ preview.classList.remove('hidden');
170
+ preview.classList.add('fade-in');
171
+
172
+ const docType = document.querySelector('input[name="docType"]:checked').value;
173
+
174
+ if (docType === 'iconographic' && file.type.startsWith('image/')) {
175
+ imagePreview.classList.remove('hidden');
176
+ textPreview.classList.add('hidden');
177
+ const reader = new FileReader();
178
+ reader.onload = (e) => {
179
+ imagePreview.src = e.target.result;
180
+ imagePreview.classList.add('fade-in');
181
+ };
182
+ reader.readAsDataURL(file);
183
+ } else {
184
+ imagePreview.classList.add('hidden');
185
+ textPreview.classList.remove('hidden');
186
+ const reader = new FileReader();
187
+ reader.onload = (e) => {
188
+ textPreview.textContent = e.target.result;
189
+ textPreview.classList.add('fade-in');
190
+ };
191
+ reader.readAsText(file);
192
+ }
193
+ }
194
+
195
+ function submitAnalysis() {
196
+ if (!selectedFile) return;
197
+
198
+ const formData = new FormData();
199
+ formData.append('file', selectedFile);
200
+ formData.append('docType', document.querySelector('input[name="docType"]:checked').value);
201
+
202
+ const loading = document.getElementById('loading');
203
  const results = document.getElementById('results');
204
  const analysisContent = document.getElementById('analysis-content');
 
205
 
206
+ loading.classList.remove('hidden');
207
+ loading.classList.add('fade-in');
208
+
209
+ fetch('/upload', {
210
+ method: 'POST',
211
+ body: formData
212
+ })
213
+ .then(response => response.json())
214
+ .then(data => {
215
+ loading.classList.add('hidden');
216
+ results.classList.remove('hidden');
217
+ results.classList.add('slide-up');
218
+ analysisContent.innerHTML = marked.parse(data.analysis);
219
+ Prism.highlightAll();
220
+ })
221
+ .catch(error => {
222
+ loading.classList.add('hidden');
223
+ alert('Une erreur est survenue lors de l\'analyse. Veuillez réessayer.');
224
+ console.error('Error:', error);
225
  });
226
+ }
227
+
228
+ // Event Listeners
229
+ document.addEventListener('DOMContentLoaded', function() {
230
+ const uploadZone = document.querySelector('.upload-zone');
231
+ const fileInput = document.getElementById('file-upload');
232
 
233
  uploadZone.addEventListener('click', () => fileInput.click());
234
 
 
251
  fileInput.addEventListener('change', (e) => {
252
  if (e.target.files.length) handleFile(e.target.files[0]);
253
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
  });
255
  </script>
256
  </body>
257
+ </html>