Docfile commited on
Commit
4d925a0
·
verified ·
1 Parent(s): 2eeed13

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +221 -229
templates/index.html CHANGED
@@ -1,6 +1,5 @@
1
  <!DOCTYPE html>
2
  <html lang="fr">
3
- <!-- [Head section reste identique jusqu'aux styles] -->
4
  <head>
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -12,23 +11,10 @@
12
  <style>
13
  @import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700&family=Poppins:wght@300;400;500;600&display=swap');
14
 
15
- .fade-in {
16
- animation: fadeIn 0.5s ease-in;
17
- }
18
-
19
- .slide-up {
20
- animation: slideUp 0.5s ease-out;
21
- }
22
-
23
- @keyframes fadeIn {
24
- from { opacity: 0; }
25
- to { opacity: 1; }
26
- }
27
-
28
- @keyframes slideUp {
29
- from { transform: translateY(20px); opacity: 0; }
30
- to { transform: translateY(0); opacity: 1; }
31
- }
32
 
33
  .gradient-text {
34
  background: linear-gradient(45deg, #FF6B6B, #4ECDC4);
@@ -36,89 +22,31 @@
36
  background-clip: text;
37
  color: transparent;
38
  }
39
-
40
  .upload-zone {
41
  background: linear-gradient(145deg, #ffffff, #f3f4f6);
42
- box-shadow: 20px 20px 60px #d1d1d1,
43
- -20px -20px 60px #ffffff;
44
- }
45
-
46
- .upload-zone:hover {
47
- transform: scale(1.01);
48
  transition: all 0.3s ease;
49
  }
50
-
51
- .waves {
52
- position: absolute;
53
- bottom: 0;
54
- left: 0;
55
- width: 100%;
56
- overflow: hidden;
57
- line-height: 0;
58
- transform: rotate(180deg);
59
- }
60
-
61
- .waves svg {
62
- position: relative;
63
- display: block;
64
- width: calc(100% + 1.3px);
65
- height: 150px;
66
- }
67
-
68
- .prose {
69
- max-width: none;
70
- color: #374151;
71
  }
72
-
73
- .prose h1, .prose h2, .prose h3 {
74
- color: #1F2937;
75
- font-family: 'Playfair Display', serif;
76
- margin-top: 2em;
77
- margin-bottom: 1em;
78
- }
79
-
80
- .prose p {
81
- margin-bottom: 1.5em;
82
- line-height: 1.8;
83
- }
84
-
85
-
86
-
87
- /* [Styles précédents restent identiques] */
88
-
89
- .button-submit {
90
- background: linear-gradient(45deg, #4F46E5, #818CF8);
91
- transition: all 0.3s ease;
92
- }
93
-
94
- .button-submit:hover {
95
- transform: translateY(-2px);
96
- box-shadow: 0 10px 20px rgba(79, 70, 229, 0.2);
97
- }
98
-
99
- .option-card {
100
- transition: all 0.3s ease;
101
- }
102
-
103
- .option-card:hover {
104
- transform: translateY(-5px);
105
- }
106
-
107
- .file-input {
108
- display: none;
109
- }
110
- </style>
111
  </head>
112
  <body class="bg-gradient-to-br from-gray-50 to-gray-100 min-h-screen relative">
113
- <!-- [Waves section reste identique] -->
114
- <div class="waves">
115
  <svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 120" preserveAspectRatio="none">
116
  <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>
117
  </svg>
118
  </div>
119
 
120
-
121
-
122
  <div class="max-w-6xl mx-auto px-4 py-12 relative z-10">
123
  <!-- Header -->
124
  <header class="text-center mb-16 fade-in">
@@ -132,48 +60,29 @@
132
 
133
  <!-- Main Content -->
134
  <div class="bg-white rounded-2xl shadow-xl p-6 md:p-8 mb-8 slide-up">
135
- <!-- Document Type Selection -->
136
- <div class="mb-8 grid md:grid-cols-2 gap-6">
137
- <div class="option-card p-6 rounded-xl border-2 border-gray-200 hover:border-indigo-500 cursor-pointer transition-all"
138
- onclick="selectDocType('iconographic')">
139
- <input type="radio" name="docType" value="iconographic" class="sr-only" checked>
140
- <div class="flex items-center mb-4">
141
- <svg class="w-8 h-8 text-indigo-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
142
- <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"/>
143
- </svg>
144
- <h3 class="ml-3 text-lg font-semibold">Document Iconographique</h3>
145
- </div>
146
- <p class="text-gray-600 text-sm">Images, photos, illustrations, publicités, etc.</p>
147
- </div>
148
-
149
- <div class="option-card p-6 rounded-xl border-2 border-gray-200 hover:border-indigo-500 cursor-pointer transition-all"
150
- onclick="selectDocType('textual')">
151
- <input type="radio" name="docType" value="textual" class="sr-only">
152
- <div class="flex items-center mb-4">
153
- <svg class="w-8 h-8 text-indigo-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
154
- <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"/>
155
- </svg>
156
- <h3 class="ml-3 text-lg font-semibold">Document Textuel</h3>
157
- </div>
158
- <p class="text-gray-600 text-sm">Textes, articles, documents écrits, etc.</p>
159
- </div>
160
- </div>
161
-
162
- <!-- File Selection -->
163
  <div class="mb-8">
164
- <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">
165
- <svg class="w-6 h-6 text-indigo-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
166
- <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"/>
167
- </svg>
168
- <span class="text-indigo-700 font-medium">Sélectionner depuis la galerie</span>
169
- </button>
170
-
171
- <input type="file" id="file-upload" class="file-input" accept="image/*,text/*"
172
- capture="environment" multiple>
 
 
 
 
 
 
 
 
173
  </div>
174
 
175
  <!-- Upload Zone -->
176
- <div class="upload-zone border-2 border-dashed border-gray-300 rounded-2xl p-8 text-center cursor-pointer transition-all duration-300 relative overflow-hidden">
177
  <div class="space-y-4">
178
  <div class="w-20 h-20 mx-auto rounded-full bg-indigo-50 flex items-center justify-center">
179
  <svg class="w-10 h-10 text-indigo-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -181,28 +90,34 @@
181
  </svg>
182
  </div>
183
  <div class="text-sm text-gray-600">
184
- <p>Déposez votre fichier ici</p>
185
- <p class="text-xs text-gray-500 mt-2">ou</p>
186
- <p class="text-indigo-600 font-medium mt-2">Cliquez pour sélectionner</p>
 
 
 
 
187
  </div>
 
188
  </div>
189
  </div>
190
 
191
  <!-- Preview -->
192
- <div id="preview" class="mt-12 hidden slide-up">
193
  <h3 class="text-xl font-medium text-gray-900 mb-6">Aperçu du document</h3>
194
  <div class="preview-container border rounded-xl p-6 bg-gray-50">
195
  <img id="image-preview" class="max-w-full h-auto hidden rounded-lg shadow-lg" alt="Aperçu">
196
- <pre id="text-preview" class="text-sm text-gray-700 whitespace-pre-wrap hidden bg-white p-4 rounded-lg shadow-inner"></pre>
 
197
  </div>
198
  </div>
199
 
200
  <!-- Submit Button -->
201
- <div class="mt-8">
202
- <button id="submit-button"
203
- 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"
204
- onclick="submitAnalysis()">
205
- Analyser le document
206
  </button>
207
  </div>
208
 
@@ -225,122 +140,199 @@
225
  </div>
226
 
227
  <script>
228
- let selectedFile = null;
229
-
230
- function selectDocType(type) {
231
- document.querySelectorAll('.option-card').forEach(card => {
232
- card.classList.remove('border-indigo-500');
233
- card.classList.add('border-gray-200');
234
- });
235
-
236
- const selectedCard = document.querySelector(`[onclick="selectDocType('${type}')"]`);
237
- selectedCard.classList.remove('border-gray-200');
238
- selectedCard.classList.add('border-indigo-500');
239
-
240
- const radio = selectedCard.querySelector('input[type="radio"]');
241
- radio.checked = true;
242
- }
243
-
244
- function openFileSelection() {
245
- document.getElementById('file-upload').click();
246
- }
247
-
248
- function handleFile(file) {
249
- selectedFile = file;
250
- const submitButton = document.getElementById('submit-button');
251
- submitButton.classList.remove('hidden');
252
-
253
- // Preview logic
254
  const preview = document.getElementById('preview');
255
  const imagePreview = document.getElementById('image-preview');
256
  const textPreview = document.getElementById('text-preview');
257
-
258
- preview.classList.remove('hidden');
259
- preview.classList.add('fade-in');
260
-
261
- const docType = document.querySelector('input[name="docType"]:checked').value;
262
-
263
- if (docType === 'iconographic' && file.type.startsWith('image/')) {
264
- imagePreview.classList.remove('hidden');
265
- textPreview.classList.add('hidden');
266
- const reader = new FileReader();
267
- reader.onload = (e) => {
268
- imagePreview.src = e.target.result;
269
- imagePreview.classList.add('fade-in');
270
- };
271
- reader.readAsDataURL(file);
272
- } else {
273
- imagePreview.classList.add('hidden');
274
- textPreview.classList.remove('hidden');
275
- const reader = new FileReader();
276
- reader.onload = (e) => {
277
- textPreview.textContent = e.target.result;
278
- textPreview.classList.add('fade-in');
279
- };
280
- reader.readAsText(file);
281
- }
282
- }
283
-
284
- function submitAnalysis() {
285
- if (!selectedFile) return;
286
-
287
- const formData = new FormData();
288
- formData.append('file', selectedFile);
289
- formData.append('docType', document.querySelector('input[name="docType"]:checked').value);
290
-
291
- const loading = document.getElementById('loading');
292
  const results = document.getElementById('results');
293
  const analysisContent = document.getElementById('analysis-content');
 
 
 
294
 
295
- loading.classList.remove('hidden');
296
- loading.classList.add('fade-in');
297
-
298
- fetch('/upload', {
299
- method: 'POST',
300
- body: formData
301
- })
302
- .then(response => response.json())
303
- .then(data => {
304
- loading.classList.add('hidden');
305
- results.classList.remove('hidden');
306
- results.classList.add('slide-up');
307
- analysisContent.innerHTML = marked.parse(data.analysis);
308
- Prism.highlightAll();
309
- })
310
- .catch(error => {
311
- loading.classList.add('hidden');
312
- alert('Une erreur est survenue lors de l\'analyse. Veuillez réessayer.');
313
- console.error('Error:', error);
314
  });
315
- }
316
 
317
- // Event Listeners
318
- document.addEventListener('DOMContentLoaded', function() {
319
- const uploadZone = document.querySelector('.upload-zone');
320
- const fileInput = document.getElementById('file-upload');
321
 
322
- uploadZone.addEventListener('click', () => fileInput.click());
323
-
 
 
 
 
 
 
 
324
  uploadZone.addEventListener('dragover', (e) => {
325
  e.preventDefault();
326
  uploadZone.classList.add('border-indigo-500', 'bg-indigo-50');
327
  });
328
-
329
  uploadZone.addEventListener('dragleave', () => {
330
  uploadZone.classList.remove('border-indigo-500', 'bg-indigo-50');
331
  });
332
-
333
  uploadZone.addEventListener('drop', (e) => {
334
  e.preventDefault();
335
  uploadZone.classList.remove('border-indigo-500', 'bg-indigo-50');
336
  const files = e.dataTransfer.files;
337
- if (files.length) handleFile(files[0]);
 
 
338
  });
339
 
 
340
  fileInput.addEventListener('change', (e) => {
341
- if (e.target.files.length) handleFile(e.target.files[0]);
 
 
342
  });
343
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
344
  </script>
345
  </body>
346
  </html>
 
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">
 
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 { animation: fadeIn 0.5s ease-in; }
15
+ .slide-up { animation: slideUp 0.5s ease-out; }
16
+ @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
17
+ @keyframes slideUp { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
  .gradient-text {
20
  background: linear-gradient(45deg, #FF6B6B, #4ECDC4);
 
22
  background-clip: text;
23
  color: transparent;
24
  }
 
25
  .upload-zone {
26
  background: linear-gradient(145deg, #ffffff, #f3f4f6);
27
+ box-shadow: 20px 20px 60px #d1d1d1, -20px -20px 60px #ffffff;
 
 
 
 
 
28
  transition: all 0.3s ease;
29
  }
30
+ .upload-zone:hover { transform: scale(1.01); }
31
+ .waves { position: absolute; bottom: 0; left: 0; width: 100%; overflow: hidden; line-height: 0; transform: rotate(180deg); }
32
+ .waves svg { position: relative; display: block; width: calc(100% + 1.3px); height: 150px; }
33
+ .prose { max-width: none; color: #374151; }
34
+ .prose h1, .prose h2, .prose h3 { color: #1F2937; font-family: 'Playfair Display', serif; margin-top: 2em; margin-bottom: 1em; }
35
+ .prose p { margin-bottom: 1.5em; line-height: 1.8; }
36
+ /* Style pour le bouton désactivé */
37
+ button:disabled {
38
+ opacity: 0.5;
39
+ cursor: not-allowed;
 
 
 
 
 
 
 
 
 
 
 
40
  }
41
+ </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  </head>
43
  <body class="bg-gradient-to-br from-gray-50 to-gray-100 min-h-screen relative">
44
+ <div class="waves">
 
45
  <svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 120" preserveAspectRatio="none">
46
  <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>
47
  </svg>
48
  </div>
49
 
 
 
50
  <div class="max-w-6xl mx-auto px-4 py-12 relative z-10">
51
  <!-- Header -->
52
  <header class="text-center mb-16 fade-in">
 
60
 
61
  <!-- Main Content -->
62
  <div class="bg-white rounded-2xl shadow-xl p-6 md:p-8 mb-8 slide-up">
63
+ <!-- File Type Selection -->
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  <div class="mb-8">
65
+ <label class="block text-lg font-medium text-gray-700 mb-4">Type de document</label>
66
+ <div class="flex gap-6">
67
+ <label class="relative flex items-center group cursor-pointer">
68
+ <input type="radio" name="fileType" value="image" checked
69
+ class="peer sr-only">
70
+ <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>
71
+ <!-- Changement de label -->
72
+ <span class="ml-3 text-gray-700 group-hover:text-indigo-500 transition-colors">Document iconographique</span>
73
+ </label>
74
+ <label class="relative flex items-center group cursor-pointer">
75
+ <input type="radio" name="fileType" value="text"
76
+ class="peer sr-only">
77
+ <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>
78
+ <!-- Changement de label -->
79
+ <span class="ml-3 text-gray-700 group-hover:text-indigo-500 transition-colors">Document textuel</span>
80
+ </label>
81
+ </div>
82
  </div>
83
 
84
  <!-- Upload Zone -->
85
+ <div id="upload-zone" class="upload-zone border-2 border-dashed border-gray-300 rounded-2xl p-8 text-center cursor-pointer transition-all duration-300 relative overflow-hidden">
86
  <div class="space-y-4">
87
  <div class="w-20 h-20 mx-auto rounded-full bg-indigo-50 flex items-center justify-center">
88
  <svg class="w-10 h-10 text-indigo-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
 
90
  </svg>
91
  </div>
92
  <div class="text-sm text-gray-600">
93
+ <!-- Le clic sur ce label ouvrira la galerie grâce au "for" -->
94
+ <label for="file-upload" 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">
95
+ <span>Déposez votre fichier ici</span>
96
+ </label>
97
+ <p class="pl-1">ou <label for="file-upload" class="cursor-pointer text-indigo-600 hover:text-indigo-500 font-medium">cliquez pour sélectionner</label></p>
98
+ <!-- Input caché qui ouvre la galerie -->
99
+ <input id="file-upload" name="file" type="file" class="sr-only">
100
  </div>
101
+ <p class="text-xs text-gray-500">PNG, JPG, GIF, PDF, TXT jusqu'à 10MB</p>
102
  </div>
103
  </div>
104
 
105
  <!-- Preview -->
106
+ <div id="preview" class="mt-8 hidden slide-up"> <!-- Ajustement marge -->
107
  <h3 class="text-xl font-medium text-gray-900 mb-6">Aperçu du document</h3>
108
  <div class="preview-container border rounded-xl p-6 bg-gray-50">
109
  <img id="image-preview" class="max-w-full h-auto hidden rounded-lg shadow-lg" alt="Aperçu">
110
+ <pre id="text-preview" class="text-sm text-gray-700 whitespace-pre-wrap hidden bg-white p-4 rounded-lg shadow-inner max-h-60 overflow-auto"></pre> <!-- Ajout max-height et overflow -->
111
+ <p id="file-info" class="text-sm text-gray-600 mt-4"></p> <!-- Pour afficher le nom du fichier -->
112
  </div>
113
  </div>
114
 
115
  <!-- Submit Button -->
116
+ <div class="mt-8 text-center"> <!-- Ajout marge -->
117
+ <button id="submit-button"
118
+ disabled
119
+ class="bg-indigo-600 text-white font-medium py-3 px-8 rounded-lg shadow-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition duration-150 ease-in-out disabled:opacity-50 disabled:cursor-not-allowed">
120
+ Soumettre pour analyse
121
  </button>
122
  </div>
123
 
 
140
  </div>
141
 
142
  <script>
143
+ document.addEventListener('DOMContentLoaded', function() {
144
+ const uploadZone = document.getElementById('upload-zone');
145
+ const fileInput = document.getElementById('file-upload');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  const preview = document.getElementById('preview');
147
  const imagePreview = document.getElementById('image-preview');
148
  const textPreview = document.getElementById('text-preview');
149
+ const fileInfo = document.getElementById('file-info'); // Élément pour nom fichier
150
+ const submitButton = document.getElementById('submit-button'); // Le bouton soumettre
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  const results = document.getElementById('results');
152
  const analysisContent = document.getElementById('analysis-content');
153
+ const loading = document.getElementById('loading');
154
+
155
+ let selectedFile = null; // Variable pour stocker le fichier sélectionné
156
 
157
+ // Configuration de marked pour le rendu Markdown
158
+ marked.setOptions({
159
+ breaks: true, gfm: true, headerIds: true, sanitize: false
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  });
 
161
 
162
+ // --- Gestion de la sélection du fichier ---
 
 
 
163
 
164
+ // Clic sur la zone d'upload ouvre l'input file
165
+ uploadZone.addEventListener('click', (e) => {
166
+ // Empêche le clic sur le label interne de déclencher deux fois l'ouverture
167
+ if (e.target.tagName !== 'LABEL' && e.target.tagName !== 'INPUT') {
168
+ fileInput.click();
169
+ }
170
+ });
171
+
172
+ // Gestion du Drag & Drop
173
  uploadZone.addEventListener('dragover', (e) => {
174
  e.preventDefault();
175
  uploadZone.classList.add('border-indigo-500', 'bg-indigo-50');
176
  });
 
177
  uploadZone.addEventListener('dragleave', () => {
178
  uploadZone.classList.remove('border-indigo-500', 'bg-indigo-50');
179
  });
 
180
  uploadZone.addEventListener('drop', (e) => {
181
  e.preventDefault();
182
  uploadZone.classList.remove('border-indigo-500', 'bg-indigo-50');
183
  const files = e.dataTransfer.files;
184
+ if (files.length) {
185
+ handleFileSelection(files[0]); // Gérer la sélection du fichier
186
+ }
187
  });
188
 
189
+ // Gestion du changement dans l'input file (sélection via galerie)
190
  fileInput.addEventListener('change', (e) => {
191
+ if (e.target.files.length) {
192
+ handleFileSelection(e.target.files[0]); // Gérer la sélection du fichier
193
+ }
194
  });
195
+
196
+ // Fonction pour gérer la SELECTION et l'APERÇU (sans soumettre)
197
+ function handleFileSelection(file) {
198
+ selectedFile = file; // Stocker le fichier
199
+ const fileType = document.querySelector('input[name="fileType"]:checked').value;
200
+
201
+ // Afficher l'aperçu
202
+ preview.classList.remove('hidden');
203
+ preview.classList.add('fade-in');
204
+
205
+ // Cacher les anciens résultats si présents
206
+ results.classList.add('hidden');
207
+ analysisContent.innerHTML = '';
208
+
209
+ // Afficher le nom du fichier
210
+ fileInfo.textContent = `Fichier sélectionné : ${file.name}`;
211
+
212
+ if (fileType === 'image') {
213
+ imagePreview.classList.remove('hidden', 'fade-in'); // Reset animation
214
+ textPreview.classList.add('hidden');
215
+ const reader = new FileReader();
216
+ reader.onload = (e) => {
217
+ imagePreview.src = e.target.result;
218
+ void imagePreview.offsetWidth; // Force reflow pour rejouer animation
219
+ imagePreview.classList.add('fade-in');
220
+ };
221
+ reader.readAsDataURL(file);
222
+ } else { // text
223
+ imagePreview.classList.add('hidden');
224
+ textPreview.classList.remove('hidden', 'fade-in'); // Reset animation
225
+ const reader = new FileReader();
226
+ reader.onload = (e) => {
227
+ textPreview.textContent = e.target.result;
228
+ void textPreview.offsetWidth; // Force reflow
229
+ textPreview.classList.add('fade-in');
230
+ };
231
+ reader.readAsText(file);
232
+ }
233
+
234
+ // Activer le bouton Soumettre
235
+ submitButton.disabled = false;
236
+ }
237
+
238
+ // --- Gestion de la SOUMISSION ---
239
+
240
+ submitButton.addEventListener('click', () => {
241
+ if (!selectedFile) {
242
+ alert("Veuillez d'abord sélectionner un fichier.");
243
+ return;
244
+ }
245
+
246
+ const fileType = document.querySelector('input[name="fileType"]:checked').value;
247
+ const formData = new FormData();
248
+ formData.append('file', selectedFile);
249
+ formData.append('fileType', fileType);
250
+
251
+ // Afficher le spinner de chargement
252
+ loading.classList.remove('hidden');
253
+ loading.classList.add('fade-in');
254
+ submitButton.disabled = true; // Désactiver pendant le chargement
255
+
256
+ // Simuler un appel API (remplacez par votre appel fetch réel)
257
+ console.log("Envoi du fichier:", selectedFile.name, "Type:", fileType);
258
+ // Décommentez et adaptez cette partie pour votre appel réel
259
+ /*
260
+ fetch('/upload', {
261
+ method: 'POST',
262
+ body: formData
263
+ })
264
+ .then(response => {
265
+ if (!response.ok) {
266
+ throw new Error(`Erreur HTTP: ${response.status}`);
267
+ }
268
+ return response.json();
269
+ })
270
+ .then(data => {
271
+ loading.classList.add('hidden');
272
+ results.classList.remove('hidden');
273
+ results.classList.add('slide-up');
274
+ analysisContent.innerHTML = marked.parse(data.analysis || "Aucune analyse reçue.");
275
+ Prism.highlightAll();
276
+ // Optionnel: réinitialiser après succès
277
+ // selectedFile = null;
278
+ // fileInput.value = ''; // Réinitialiser l'input file
279
+ // preview.classList.add('hidden');
280
+ // fileInfo.textContent = '';
281
+ // submitButton.disabled = true;
282
+ })
283
+ .catch(error => {
284
+ loading.classList.add('hidden');
285
+ submitButton.disabled = false; // Réactiver en cas d'erreur
286
+ alert(`Une erreur est survenue lors de l'analyse : ${error.message}. Veuillez réessayer.`);
287
+ console.error('Error:', error);
288
+ // Cacher les résultats si une erreur survient
289
+ results.classList.add('hidden');
290
+ analysisContent.innerHTML = '';
291
+ });
292
+ */
293
+
294
+ // --- Simulation (à remplacer par le fetch ci-dessus) ---
295
+ setTimeout(() => {
296
+ loading.classList.add('hidden');
297
+ results.classList.remove('hidden');
298
+ results.classList.add('slide-up');
299
+ // Exemple de contenu Markdown simulé
300
+ const simulatedMarkdown = `
301
+ # Analyse du document : ${selectedFile.name}
302
+
303
+ Ceci est une **simulation** de l'analyse.
304
+
305
+ ## Section 1: Résumé
306
+
307
+ Le document de type *${fileType}* a été traité.
308
+
309
+ ## Section 2: Traduction (Exemple)
310
+
311
+ * **Original (Espagnol):** Hola Mundo
312
+ * **Traduction (Français):** Bonjour le Monde
313
+
314
+ \`\`\`javascript
315
+ // Exemple de bloc de code
316
+ function greet() {
317
+ console.log("Simulation terminée !");
318
+ }
319
+ \`\`\`
320
+ `;
321
+ analysisContent.innerHTML = marked.parse(simulatedMarkdown);
322
+ Prism.highlightAll(); // Appliquer PrismJS au contenu généré
323
+ // Ne pas réinitialiser ici pour pouvoir voir le résultat de la simulation
324
+ // selectedFile = null;
325
+ // fileInput.value = '';
326
+ // preview.classList.add('hidden');
327
+ // fileInfo.textContent = '';
328
+ // submitButton.disabled = true; // Garder désactivé après simulation ou le réactiver si besoin
329
+ submitButton.disabled = false; // Réactiver après la simulation pour permettre une autre soumission
330
+ }, 2000); // Simule un délai réseau de 2 secondes
331
+ // --- Fin de la Simulation ---
332
+
333
+ }); // Fin de l'event listener du bouton submit
334
+
335
+ }); // Fin du DOMContentLoaded
336
  </script>
337
  </body>
338
  </html>