Docfile commited on
Commit
2ae82a2
·
verified ·
1 Parent(s): eec1359

Create index.html

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