Docfile commited on
Commit
ae3231c
·
verified ·
1 Parent(s): 678d7e7

Create index.html

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