Docfile commited on
Commit
691a7ba
·
verified ·
1 Parent(s): 87b75f2

Create index.html

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