Docfile commited on
Commit
b9f0a22
·
verified ·
1 Parent(s): 8bbc1ad

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +283 -315
templates/index.html CHANGED
@@ -1,6 +1,4 @@
1
-
2
- <!DOCTYPE html>
3
-
4
  <html lang="fr">
5
  <head>
6
  <meta charset="UTF-8">
@@ -28,363 +26,333 @@
28
  <style>
29
  @import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap');
30
 
31
- body {
32
- font-family: 'Space Grotesk', sans-serif;
33
- background: linear-gradient(135deg, #F0F8FF 0%, #FFFFFF 100%);
34
- min-height: 100vh;
35
- color: #1e3a8a;
36
- }
37
-
38
- .glass-card {
39
- background: rgba(255, 255, 255, 0.95);
40
- backdrop-filter: blur(10px);
41
- border: 1px solid rgba(0, 0, 0, 0.1);
42
- box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.05);
43
- }
44
-
45
- .uploadArea {
46
- background: linear-gradient(145deg, rgba(219, 234, 254, 0.3) 0%, rgba(255, 255, 255, 0.2) 100%);
47
- border: 2px dashed #3b82f6;
48
- }
49
-
50
- .uploadArea:hover {
51
- border-color: #2563eb;
52
- transform: translateY(-2px);
53
- }
54
-
55
- .neon-button {
56
- background: linear-gradient(90deg, #2563eb 0%, #3b82f6 100%);
57
- box-shadow: 0 0 15px rgba(37, 99, 235, 0.3);
58
- transition: all 0.3s ease;
59
- color: white;
60
- }
61
-
62
- .neon-button:hover {
63
- box-shadow: 0 0 25px rgba(37, 99, 235, 0.5);
64
- transform: translateY(-2px);
65
- }
66
-
67
- .loader {
68
- width: 48px;
69
- height: 48px;
70
- border: 3px solid #3b82f6;
71
- border-bottom-color: transparent;
72
- border-radius: 50%;
73
- display: inline-block;
74
- box-sizing: border-box;
75
- animation: rotation 1s linear infinite;
76
- }
77
-
78
- @keyframes rotation {
79
- 0% { transform: rotate(0deg); }
80
- 100% { transform: rotate(360deg); }
81
- }
82
-
83
- .thought-box {
84
- transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
85
- max-height: 0;
86
- overflow: hidden;
87
- }
88
-
89
- .thought-box.open {
90
- max-height: 1000px;
91
- }
92
-
93
- .preview-container {
94
- display: flex;
95
- justify-content: center;
96
- align-items: center;
97
- margin-top: 20px;
98
- }
99
-
100
- .preview-image {
101
- max-width: 300px;
102
- max-height: 300px;
103
- border-radius: 8px;
104
- border: 2px solid #bfdbfe;
105
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
106
- }
107
-
108
- #thoughtsContent, #answerContent {
109
- max-height: 500px;
110
- overflow-y: auto;
111
- color: #1e3a8a;
112
- }
113
-
114
- .timestamp {
115
- color: #3b82f6;
116
- margin-left: 10px;
117
- font-size: 0.9em;
118
- }
119
-
120
- /* Pleine largeur pour les zones de réponse */
121
- #solution {
122
- margin: 2rem -50vw;
123
- width: 100vw;
124
- max-width: 100vw;
125
- position: relative;
126
- left: 50%;
127
- right: 50%;
128
- transform: translateX(-50%);
129
- padding: 2rem 0;
130
- background: rgba(255, 255, 255, 0.9);
131
- }
132
-
133
- .solution-card {
134
- width: 85%;
135
- margin: 0 auto;
136
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
137
- }
138
- </style>
139
- content_copy
140
- download
141
- Use code with caution.
142
  </head>
143
- <body class="p-4 md:p-8">
144
- <div class="container mx-auto max-w-4xl">
145
- <div class="glass-card rounded-3xl p-8 md:p-12">
146
  <div class="text-center mb-12">
147
- <h1 class="text-5xl font-bold text-blue-900 mb-4">Mariam M-0</h1>
148
- <p class="text-blue-600 text-lg">Solution Mathématique Intelligente</p>
149
  </div>
150
 
151
- <form id="problemForm" class="space-y-8" enctype="multipart/form-data">
152
- <div class="relative">
153
- <div class="uploadArea rounded-2xl p-12 text-center transition-all duration-300 cursor-pointer">
154
- <input type="file" id="imageInput" name="image" accept="image/*" class="absolute inset-0 w-full h-full opacity-0 cursor-pointer">
155
- <div class="space-y-4">
156
- <div class="w-20 h-20 mx-auto border-2 border-blue-400 rounded-full flex items-center justify-center">
157
- <svg class="w-10 h-10 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
158
- <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" />
159
- </svg>
 
 
 
160
  </div>
161
- <div class="text-blue-600 text-lg font-medium">Déposez votre image ici</div>
162
- <div class="text-blue-400 text-sm">ou cliquez pour sélectionner</div>
 
163
  </div>
164
  </div>
165
- <div id="imagePreview" class="preview-container hidden">
166
- <img id="previewImage" src="#" alt="Prévisualisation de l'image" class="preview-image">
167
- </div>
168
- </div>
169
 
170
- <button type="submit" class="neon-button w-full py-4 rounded-xl font-medium text-lg transition-all duration-300">
171
- Résoudre le problème
172
- </button>
173
- </form>
174
 
175
- <div id="loader" class="hidden mt-12">
176
- <div class="flex flex-col items-center justify-center space-y-4">
177
- <span class="loader"></span>
178
- <div class="text-blue-600 text-lg">Analyse en cours...</div>
 
179
  </div>
180
- </div>
181
 
182
- <div id="solution" class="hidden mt-12 space-y-8">
183
- <div class="glass-card solution-card rounded-2xl p-6">
184
- <button id="thoughtsToggle" class="w-full flex justify-between items-center text-left text-lg font-medium text-blue-900 hover:text-blue-600 transition-colors">
185
- <div class="flex items-center">
186
- <span>Processus de Réflexion</span>
187
- <span id="timestamp" class="timestamp"></span>
 
 
 
 
 
 
 
188
  </div>
189
- <svg class="w-6 h-6 transform transition-transform duration-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
190
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
191
- </svg>
192
- </button>
193
- <div id="thoughtsBox" class="thought-box">
194
- <div id="thoughtsContent" class="prose max-w-none mt-4"></div>
195
  </div>
196
- </div>
197
 
198
- <div class="glass-card solution-card rounded-2xl p-8">
199
- <h3 class="text-2xl font-bold text-blue-900 mb-6">Solution</h3>
200
- <div id="answerContent" class="prose max-w-none"></div>
 
201
  </div>
202
  </div>
203
  </div>
204
- </div>
205
-
206
- <script>
207
- // Le JavaScript reste identique à la version originale
208
- document.addEventListener('DOMContentLoaded', () => {
209
- const form = document.getElementById('problemForm');
210
- const imageInput = document.getElementById('imageInput');
211
- const loader = document.getElementById('loader');
212
- const solutionDiv = document.getElementById('solution');
213
- const thoughtsContent = document.getElementById('thoughtsContent');
214
- const answerContent = document.getElementById('answerContent');
215
- const thoughtsToggle = document.getElementById('thoughtsToggle');
216
- const thoughtsBox = document.getElementById('thoughtsBox');
217
- const imagePreview = document.getElementById('imagePreview');
218
- const previewImage = document.getElementById('previewImage');
219
- const timestamp = document.getElementById('timestamp');
220
-
221
- let startTime = null;
222
- let timerInterval = null;
223
-
224
- function updateTimestamp() {
225
- if (startTime) {
226
- const elapsed = Math.floor((Date.now() - startTime) / 1000);
227
- timestamp.textContent = elapsed + "s";
228
- }
229
- }
230
 
231
- function startTimer() {
232
- startTime = Date.now();
233
- timerInterval = setInterval(updateTimestamp, 1000);
234
- updateTimestamp();
235
- }
236
-
237
- function stopTimer() {
238
- if (timerInterval) {
239
- clearInterval(timerInterval);
240
- timerInterval = null;
 
 
 
 
 
 
 
 
 
 
 
 
241
  }
242
- startTime = null;
243
- timestamp.textContent = "";
244
- }
245
 
246
- thoughtsToggle.addEventListener('click', () => {
247
- thoughtsBox.classList.toggle('open');
248
- thoughtsToggle.querySelector('svg').classList.toggle('rotate-180');
249
- });
 
250
 
251
- imageInput.addEventListener('change', function(e) {
252
- const file = this.files[0];
253
- if (file) {
254
- const reader = new FileReader();
255
- reader.onload = function(e) {
256
- previewImage.src = e.target.result;
257
- imagePreview.classList.remove('hidden');
258
  }
259
- reader.readAsDataURL(file);
260
- } else {
261
- previewImage.src = "";
262
- imagePreview.classList.add('hidden');
263
  }
264
- });
265
 
266
- const dropZone = document.querySelector('.uploadArea');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
267
 
268
- ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
269
- dropZone.addEventListener(eventName, preventDefaults, false);
270
- });
271
 
272
- function preventDefaults(e) {
273
- e.preventDefault();
274
- e.stopPropagation();
275
- }
276
 
277
- ['dragenter', 'dragover'].forEach(eventName => {
278
- dropZone.addEventListener(eventName, highlight, false);
279
- });
 
280
 
281
- ['dragleave', 'drop'].forEach(eventName => {
282
- dropZone.addEventListener(eventName, unhighlight, false);
283
- });
284
 
285
- function highlight(e) {
286
- dropZone.classList.add('border-blue-600');
287
- }
288
 
289
- function unhighlight(e) {
290
- dropZone.classList.remove('border-blue-600');
291
- }
 
 
 
 
292
 
293
- dropZone.addEventListener('drop', handleDrop, false);
294
 
295
- function handleDrop(e) {
296
- const dt = e.dataTransfer;
297
- const files = dt.files;
298
 
299
- if (files.length) {
300
- imageInput.files = files;
301
- const file = files[0];
302
- const reader = new FileReader();
303
- reader.onload = function(e) {
304
- previewImage.src = e.target.result;
305
- imagePreview.classList.remove('hidden');
 
 
306
  }
307
- reader.readAsDataURL(file);
308
  }
309
- }
310
 
311
- form.addEventListener('submit', async (event) => {
312
- event.preventDefault();
313
- const file = imageInput.files[0];
314
- if (!file) {
315
- alert('Veuillez sélectionner une image.');
316
- return;
317
- }
318
 
319
- startTimer();
320
-
321
- loader.classList.remove('hidden');
322
- solutionDiv.classList.add('hidden');
323
- thoughtsContent.innerHTML = '';
324
- answerContent.innerHTML = '';
325
- thoughtsBox.classList.add('open');
326
-
327
- const formData = new FormData();
328
- formData.append('image', file);
329
-
330
- try {
331
- let currentMode = null;
332
- const response = await fetch('/solve', {
333
- method: 'POST',
334
- body: formData
335
- });
336
-
337
- const reader = response.body.getReader();
338
- const decoder = new TextDecoder();
339
- let buffer = '';
340
-
341
- while (true) {
342
- const { done, value } = await reader.read();
343
- if (done) {
344
- stopTimer();
345
- break;
346
- }
347
 
348
- buffer += decoder.decode(value, { stream: true });
349
- let eolIndex;
350
 
351
- while ((eolIndex = buffer.indexOf('\n\n')) >= 0) {
352
- const line = buffer.slice(0, eolIndex).trim();
353
- buffer = buffer.slice(eolIndex + 2);
354
 
355
- if (line.startsWith('data:')) {
356
- const data = JSON.parse(line.slice(5));
357
-
358
- if (data.mode) {
359
- currentMode = data.mode;
360
- loader.classList.add('hidden');
361
- solutionDiv.classList.remove('hidden');
362
- }
363
-
364
- if (data.content) {
365
- const content = data.content;
366
- if (currentMode === 'thinking') {
367
- thoughtsContent.innerHTML += `<p>${content}</p>`;
368
- thoughtsContent.scrollTop = thoughtsContent.scrollHeight;
369
- } else if (currentMode === 'answering') {
370
- answerContent.innerHTML += content;
371
- if (window.MathJax) {
372
- MathJax.typesetPromise([answerContent]).catch((err) => console.log('MathJax error:', err));
 
373
  }
374
  }
375
  }
376
  }
377
  }
378
- }
379
 
380
- } catch (error) {
381
- console.error('Erreur:', error);
382
- alert('Une erreur est survenue lors du traitement de la requête.');
383
- loader.classList.add('hidden');
384
- stopTimer();
385
- }
 
386
  });
387
- });
388
- </script>
389
  </body>
390
- </html>
 
1
+ <!DOCTYPE html>
 
 
2
  <html lang="fr">
3
  <head>
4
  <meta charset="UTF-8">
 
26
  <style>
27
  @import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap');
28
 
29
+ body {
30
+ font-family: 'Space Grotesk', sans-serif;
31
+ background-color: white;
32
+ }
33
+
34
+ .card {
35
+ background: white;
36
+ border: 1px solid #e5e7eb;
37
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
38
+ }
39
+
40
+ .uploadArea {
41
+ background: #f3f4f6;
42
+ border: 2px dashed #d1d5db;
43
+ }
44
+
45
+ .uploadArea:hover {
46
+ border-color: #3b82f6;
47
+ transform: translateY(-2px);
48
+ }
49
+
50
+ .blue-button {
51
+ background: #3b82f6;
52
+ transition: all 0.3s ease;
53
+ }
54
+
55
+ .blue-button:hover {
56
+ background: #2563eb;
57
+ transform: translateY(-2px);
58
+ }
59
+
60
+ .loader {
61
+ width: 48px;
62
+ height: 48px;
63
+ border: 3px solid #3b82f6;
64
+ border-bottom-color: transparent;
65
+ border-radius: 50%;
66
+ display: inline-block;
67
+ box-sizing: border-box;
68
+ animation: rotation 1s linear infinite;
69
+ }
70
+
71
+ @keyframes rotation {
72
+ 0% { transform: rotate(0deg); }
73
+ 100% { transform: rotate(360deg); }
74
+ }
75
+
76
+ .thought-box {
77
+ transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
78
+ max-height: 0;
79
+ overflow: hidden;
80
+ }
81
+
82
+ .thought-box.open {
83
+ max-height: 1000px;
84
+ }
85
+
86
+ .preview-container {
87
+ display: flex;
88
+ justify-content: center;
89
+ align-items: center;
90
+ margin-top: 20px;
91
+ }
92
+
93
+ .preview-image {
94
+ max-width: 300px;
95
+ max-height: 300px;
96
+ border-radius: 8px;
97
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
98
+ }
99
+
100
+ #thoughtsContent, #answerContent {
101
+ max-height: 500px;
102
+ overflow-y: auto;
103
+ }
104
+
105
+ .timestamp {
106
+ color: #3b82f6;
107
+ margin-left: 10px;
108
+ font-size: 0.9em;
109
+ }
110
+ </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  </head>
112
+ <body class="p-4">
113
+ <div class="container mx-auto">
114
+ <div class="card rounded-lg p-8">
115
  <div class="text-center mb-12">
116
+ <h1 class="text-4xl font-bold text-blue-600 mb-4">Mariam M-0</h1>
117
+ <p class="text-gray-600 text-lg">Solution Mathématique Intelligente</p>
118
  </div>
119
 
120
+ <form id="problemForm" class="space-y-8" enctype="multipart/form-data">
121
+ <div class="relative">
122
+ <div class="uploadArea rounded-lg p-12 text-center transition-all duration-300 cursor-pointer">
123
+ <input type="file" id="imageInput" name="image" accept="image/*" class="absolute inset-0 w-full h-full opacity-0 cursor-pointer">
124
+ <div class="space-y-4">
125
+ <div class="w-20 h-20 mx-auto border-2 border-blue-400 rounded-full flex items-center justify-center">
126
+ <svg class="w-10 h-10 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
127
+ <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" />
128
+ </svg>
129
+ </div>
130
+ <div class="text-gray-700 text-lg font-medium">Déposez votre image ici</div>
131
+ <div class="text-gray-500 text-sm">ou cliquez pour sélectionner</div>
132
  </div>
133
+ </div>
134
+ <div id="imagePreview" class="preview-container hidden">
135
+ <img id="previewImage" src="#" alt="Prévisualisation de l'image" class="preview-image">
136
  </div>
137
  </div>
 
 
 
 
138
 
139
+ <button type="submit" class="blue-button w-full py-4 rounded-lg text-white font-medium text-lg transition-all duration-300">
140
+ Résoudre le problème
141
+ </button>
142
+ </form>
143
 
144
+ <div id="loader" class="hidden mt-12">
145
+ <div class="flex flex-col items-center justify-center space-y-4">
146
+ <span class="loader"></span>
147
+ <div class="text-gray-600 text-lg">Analyse en cours...</div>
148
+ </div>
149
  </div>
 
150
 
151
+ <div id="solution" class="hidden mt-12 space-y-8">
152
+ <div class="card rounded-lg p-6 w-full">
153
+ <button id="thoughtsToggle" class="w-full flex justify-between items-center text-left text-lg font-medium text-gray-700 hover:text-blue-600 transition-colors">
154
+ <div class="flex items-center">
155
+ <span>Processus de Réflexion</span>
156
+ <span id="timestamp" class="timestamp"></span>
157
+ </div>
158
+ <svg class="w-6 h-6 transform transition-transform duration-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
159
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
160
+ </svg>
161
+ </button>
162
+ <div id="thoughtsBox" class="thought-box">
163
+ <div id="thoughtsContent" class="prose max-w-none text-gray-600 mt-4"></div>
164
  </div>
 
 
 
 
 
 
165
  </div>
 
166
 
167
+ <div class="card rounded-lg p-8 w-full">
168
+ <h3 class="text-2xl font-bold text-gray-800 mb-6">Solution</h3>
169
+ <div id="answerContent" class="prose max-w-none text-gray-700"></div>
170
+ </div>
171
  </div>
172
  </div>
173
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
 
175
+ <script>
176
+ document.addEventListener('DOMContentLoaded', () => {
177
+ const form = document.getElementById('problemForm');
178
+ const imageInput = document.getElementById('imageInput');
179
+ const loader = document.getElementById('loader');
180
+ const solutionDiv = document.getElementById('solution');
181
+ const thoughtsContent = document.getElementById('thoughtsContent');
182
+ const answerContent = document.getElementById('answerContent');
183
+ const thoughtsToggle = document.getElementById('thoughtsToggle');
184
+ const thoughtsBox = document.getElementById('thoughtsBox');
185
+ const imagePreview = document.getElementById('imagePreview');
186
+ const previewImage = document.getElementById('previewImage');
187
+ const timestamp = document.getElementById('timestamp');
188
+
189
+ let startTime = null;
190
+ let timerInterval = null;
191
+
192
+ function updateTimestamp() {
193
+ if (startTime) {
194
+ const elapsed = Math.floor((Date.now() - startTime) / 1000);
195
+ timestamp.textContent = elapsed + "s";
196
+ }
197
  }
 
 
 
198
 
199
+ function startTimer() {
200
+ startTime = Date.now();
201
+ timerInterval = setInterval(updateTimestamp, 1000);
202
+ updateTimestamp();
203
+ }
204
 
205
+ function stopTimer() {
206
+ if (timerInterval) {
207
+ clearInterval(timerInterval);
208
+ timerInterval = null;
 
 
 
209
  }
210
+ startTime = null;
211
+ timestamp.textContent = "";
 
 
212
  }
 
213
 
214
+ thoughtsToggle.addEventListener('click', () => {
215
+ thoughtsBox.classList.toggle('open');
216
+ thoughtsToggle.querySelector('svg').classList.toggle('rotate-180');
217
+ });
218
+
219
+ imageInput.addEventListener('change', function(e) {
220
+ const file = this.files[0];
221
+ if (file) {
222
+ const reader = new FileReader();
223
+ reader.onload = function(e) {
224
+ previewImage.src = e.target.result;
225
+ imagePreview.classList.remove('hidden');
226
+ }
227
+ reader.readAsDataURL(file);
228
+ } else {
229
+ previewImage.src = "";
230
+ imagePreview.classList.add('hidden');
231
+ }
232
+ });
233
 
234
+ const dropZone = document.querySelector('.uploadArea');
 
 
235
 
236
+ ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
237
+ dropZone.addEventListener(eventName, preventDefaults, false);
238
+ });
 
239
 
240
+ function preventDefaults(e) {
241
+ e.preventDefault();
242
+ e.stopPropagation();
243
+ }
244
 
245
+ ['dragenter', 'dragover'].forEach(eventName => {
246
+ dropZone.addEventListener(eventName, highlight, false);
247
+ });
248
 
249
+ ['dragleave', 'drop'].forEach(eventName => {
250
+ dropZone.addEventListener(eventName, unhighlight, false);
251
+ });
252
 
253
+ function highlight(e) {
254
+ dropZone.classList.add('border-blue-400');
255
+ }
256
+
257
+ function unhighlight(e) {
258
+ dropZone.classList.remove('border-blue-400');
259
+ }
260
 
261
+ dropZone.addEventListener('drop', handleDrop, false);
262
 
263
+ function handleDrop(e) {
264
+ const dt = e.dataTransfer;
265
+ const files = dt.files;
266
 
267
+ if (files.length) {
268
+ imageInput.files = files;
269
+ const file = files[0];
270
+ const reader = new FileReader();
271
+ reader.onload = function(e) {
272
+ previewImage.src = e.target.result;
273
+ imagePreview.classList.remove('hidden');
274
+ }
275
+ reader.readAsDataURL(file);
276
  }
 
277
  }
 
278
 
279
+ form.addEventListener('submit', async (event) => {
280
+ event.preventDefault();
281
+ const file = imageInput.files[0];
282
+ if (!file) {
283
+ alert('Veuillez sélectionner une image.');
284
+ return;
285
+ }
286
 
287
+ startTimer();
288
+
289
+ loader.classList.remove('hidden');
290
+ solutionDiv.classList.add('hidden');
291
+ thoughtsContent.innerHTML = '';
292
+ answerContent.innerHTML = '';
293
+ thoughtsBox.classList.add('open');
294
+
295
+ const formData = new FormData();
296
+ formData.append('image', file);
297
+
298
+ try {
299
+ let currentMode = null;
300
+ const response = await fetch('/solve', {
301
+ method: 'POST',
302
+ body: formData
303
+ });
304
+
305
+ const reader = response.body.getReader();
306
+ const decoder = new TextDecoder();
307
+ let buffer = '';
308
+
309
+ while (true) {
310
+ const { done, value } = await reader.read();
311
+ if (done) {
312
+ stopTimer();
313
+ break;
314
+ }
315
 
316
+ buffer += decoder.decode(value, { stream: true });
317
+ let eolIndex;
318
 
319
+ while ((eolIndex = buffer.indexOf('\n\n')) >= 0) {
320
+ const line = buffer.slice(0, eolIndex).trim();
321
+ buffer = buffer.slice(eolIndex + 2);
322
 
323
+ if (line.startsWith('data:')) {
324
+ const data = JSON.parse(line.slice(5));
325
+
326
+ if (data.mode) {
327
+ currentMode = data.mode;
328
+ loader.classList.add('hidden');
329
+ solutionDiv.classList.remove('hidden');
330
+ }
331
+
332
+ if (data.content) {
333
+ const content = data.content;
334
+ if (currentMode === 'thinking') {
335
+ thoughtsContent.innerHTML += `<p>${content}</p>`;
336
+ thoughtsContent.scrollTop = thoughtsContent.scrollHeight;
337
+ } else if (currentMode === 'answering') {
338
+ answerContent.innerHTML += content;
339
+ if (window.MathJax) {
340
+ MathJax.typesetPromise([answerContent]).catch((err) => console.log('MathJax error:', err));
341
+ }
342
  }
343
  }
344
  }
345
  }
346
  }
 
347
 
348
+ } catch (error) {
349
+ console.error('Erreur:', error);
350
+ alert('Une erreur est survenue lors du traitement de la requête.');
351
+ loader.classList.add('hidden');
352
+ stopTimer();
353
+ }
354
+ });
355
  });
356
+ </script>
 
357
  </body>
358
+ </html>