Docfile commited on
Commit
777dd2a
·
verified ·
1 Parent(s): 06bb0a2

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +316 -276
templates/index.html CHANGED
@@ -1,289 +1,329 @@
1
  <!DOCTYPE html>
2
  <html lang="fr">
3
-
4
  <head>
5
- <meta charset="UTF-8">
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>Mariam AI - Résolution d'exercices Physique-Chimie</title>
8
- <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
9
- <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
10
- <script src="https://cdn.tailwindcss.com"></script>
11
- <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
12
- <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
13
- <style>
14
- @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
15
-
16
- body {
17
- font-family: 'Poppins', sans-serif;
18
- }
19
-
20
- .loader {
21
- width: 48px;
22
- height: 48px;
23
- border: 5px solid #FFF;
24
- border-bottom-color: #3B82F6;
25
- border-radius: 50%;
26
- display: inline-block;
27
- box-sizing: border-box;
28
- animation: rotation 1s linear infinite;
29
- }
30
-
31
- @keyframes rotation {
32
- 0% {
33
- transform: rotate(0deg);
34
- }
35
-
36
- 100% {
37
- transform: rotate(360deg);
38
- }
39
- }
40
-
41
- .math-content {
42
- font-size: 1.1em;
43
- line-height: 1.6;
44
- overflow-x: auto;
45
- }
46
-
47
- .math-content p {
48
- margin-bottom: 1rem;
49
- }
50
-
51
- .math-content .MathJax {
52
- overflow-x: auto;
53
- overflow-y: hidden;
54
- padding: 0.5rem 0;
55
- }
56
-
57
- @media (max-width: 640px) {
58
- .math-content .MathJax {
59
- font-size: 0.9em;
60
- }
61
- }
62
-
63
- .math-hidden {
64
- visibility: hidden;
65
- }
66
- </style>
67
- <script>
68
- // Configuration de marked
69
- marked.setOptions({
70
- breaks: true,
71
- gfm: true,
72
- headerIds: false
73
- });
74
-
75
- // Configuration de MathJax
76
- MathJax = {
77
- tex: {
78
- inlineMath: [['$', '$'], ['\\(', '\\)']],
79
- displayMath: [['$$', '$$'], ['\\[', '\\]']],
80
- processEscapes: true,
81
- macros: {
82
- R: "{\\mathbb{R}}",
83
- N: "{\\mathbb{N}}",
84
- Z: "{\\mathbb{Z}}",
85
- vecv: ["\\begin{pmatrix}#1\\\\#2\\\\#3\\end{pmatrix}", 3]
86
- }
87
- },
88
- svg: {
89
- fontCache: 'global'
90
- },
91
- options: {
92
- renderActions: {
93
- addMenu: [],
94
- checkLoading: [150, (doc) => {
95
- document.querySelectorAll('.math-content').forEach(el => {
96
- el.classList.remove('math-hidden');
97
- });
98
- }]
99
- }
100
- }
101
- };
102
- </script>
 
 
 
 
 
 
103
  </head>
104
 
105
  <body class="bg-gray-50 min-h-screen">
106
- <!-- Navbar -->
107
- <nav class="bg-white shadow-lg">
108
- <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
109
- <div class="flex justify-between items-center h-16">
110
- <div class="flex items-center">
111
- <i class="fas fa-atom text-blue-600 text-2xl mr-2"></i>
112
- <span class="font-bold text-xl text-gray-800">Mariam AI</span>
113
- </div>
114
- </div>
115
- </div>
116
- </nav>
117
-
118
- <!-- Main Content -->
119
- <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
120
- <div class="bg-white rounded-lg shadow-xl p-6 md:p-8">
121
- <div class="text-center mb-8">
122
- <h1 class="text-3xl font-bold text-gray-800 mb-2">Assistant Physique-Chimie</h1>
123
- <p class="text-gray-600">Uploadez une photo de votre exercice pour obtenir une résolution détaillée</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  </div>
125
-
126
- <!-- Upload Section -->
127
- <form id="upload-form" enctype="multipart/form-data">
128
- <div class="flex flex-col items-center justify-center w-full">
129
- <label for="image-input"
130
- class="flex flex-col items-center justify-center w-full h-64 border-2 border-blue-300 border-dashed rounded-lg cursor-pointer bg-gray-50 hover:bg-gray-100 transition duration-300">
131
- <div class="flex flex-col items-center justify-center pt-5 pb-6">
132
- <i class="fas fa-cloud-upload-alt text-4xl text-blue-500 mb-4"></i>
133
- <p class="mb-2 text-sm text-gray-500"><span class="font-semibold">Cliquez pour
134
- upload</span> ou glissez-déposez</p>
135
- <p class="text-xs text-gray-500">PNG, JPG ou JPEG</p>
136
- </div>
137
- <input id="image-input" type="file" name="image" class="hidden" accept="image/*" />
138
- </label>
139
- <button type="submit" id="submit-button"
140
- class="mt-4 bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-lg hidden">
141
- Soumettre
142
- </button>
143
- </div>
144
- </form>
145
-
146
- <!-- Preview Section -->
147
- <div class="mt-8">
148
- <img id="image-preview" class="max-w-full h-auto mx-auto rounded-lg shadow-md hidden" alt="Preview">
149
- </div>
150
-
151
- <!-- Loading Animation -->
152
- <div id="loading" class="hidden flex justify-center items-center my-8">
153
- <span class="loader"></span>
154
- <span class="ml-3 text-gray-600">Analyse en cours...</span>
155
- </div>
156
-
157
- <!-- Result Section -->
158
- <div id="result-container" class="hidden mt-8">
159
- <h2 class="text-xl font-semibold text-gray-800 mb-4">Résolution détaillée :</h2>
160
- <div class="flex items-center mb-4">
161
- <button id="copy-button"
162
- class="bg-gray-200 hover:bg-gray-300 text-gray-800 font-bold py-2 px-4 rounded-lg">
163
- <i class="fas fa-copy mr-2"></i>Copier
164
- </button>
165
- <button id="save-button"
166
- class="ml-4 bg-green-200 hover:bg-green-300 text-green-800 font-bold py-2 px-4 rounded-lg">
167
- <i class="fas fa-save mr-2"></i>Sauvegarder
168
- </button>
169
- </div>
170
- <div id="result" class="bg-gray-50 rounded-lg p-6 prose max-w-none math-content math-hidden"></div>
171
- </div>
172
- </div>
173
- </div>
174
-
175
- <script>
176
- const form = document.getElementById('upload-form');
177
- const imageInput = document.getElementById('image-input');
178
- const submitButton = document.getElementById('submit-button');
179
- const imagePreview = document.getElementById('image-preview');
180
- const loading = document.getElementById('loading');
181
- const resultContainer = document.getElementById('result-container');
182
- const result = document.getElementById('result');
183
- const copyButton = document.getElementById('copy-button');
184
- const saveButton = document.getElementById('save-button');
185
- let generatedResult = '';
186
-
187
- imageInput.addEventListener('change', function (e) {
188
- const file = e.target.files[0];
189
- if (file) {
190
- // Show preview
191
- const reader = new FileReader();
192
- reader.onload = function (e) {
193
- imagePreview.src = e.target.result;
194
- imagePreview.classList.remove('hidden');
195
- submitButton.classList.remove('hidden');
196
- };
197
- reader.readAsDataURL(file);
198
- } else {
199
- imagePreview.src = "";
200
- imagePreview.classList.add('hidden');
201
- submitButton.classList.add('hidden');
202
- }
203
  });
204
-
205
- form.addEventListener('submit', async function (e) {
206
- e.preventDefault();
207
-
208
- // Show loading
209
- loading.classList.remove('hidden');
210
- resultContainer.classList.add('hidden');
211
- result.classList.add('math-hidden');
 
 
 
 
 
 
 
 
 
 
 
212
  submitButton.classList.add('hidden');
213
-
214
- const formData = new FormData(form);
215
-
216
- try {
217
- const response = await fetch('/generate', {
218
- method: 'POST',
219
- body: formData
220
- });
221
-
222
- const data = await response.json();
223
- generatedResult = data.result;
224
-
225
- // Hide loading
226
- loading.classList.add('hidden');
227
-
228
- // Show result
229
- resultContainer.classList.remove('hidden');
230
- result.innerHTML = marked.parse(generatedResult);
231
-
232
- // Rendre les maths avec MathJax
233
- setTimeout(() => {
234
- MathJax.typesetPromise([result])
235
- .then(() => {
236
- result.classList.remove('math-hidden');
237
- })
238
- .catch((err) => {
239
- console.error('Erreur MathJax:', err);
240
- result.innerHTML = "Erreur lors du rendu des mathématiques.";
241
- result.classList.remove('math-hidden');
242
- });
243
- }, 0);
244
-
245
- } catch (error) {
246
- console.error('Erreur:', error);
247
- loading.classList.add('hidden');
248
- alert('Une erreur est survenue lors du traitement de l\'image.');
249
- }
250
- });
251
-
252
- // Copier la réponse
253
- copyButton.addEventListener('click', function () {
254
- navigator.clipboard.writeText(generatedResult)
255
- .then(() => {
256
- // Message de confirmation (optionnel)
257
- alert('Réponse copiée dans le presse-papiers!');
258
- })
259
- .catch(err => {
260
- console.error('Erreur lors de la copie:', err);
261
- });
262
- });
263
-
264
- // Sauvegarder la réponse dans le localStorage
265
- saveButton.addEventListener('click', function () {
266
- const timestamp = new Date().toLocaleString();
267
- const file = imageInput.files[0];
268
-
269
- if (file) {
270
- const reader = new FileReader();
271
- reader.onload = function (e) {
272
- const savedData = {
273
- timestamp: timestamp,
274
- image: e.target.result, // On sauvegarde la data URL de l'image
275
- result: generatedResult
276
- };
277
-
278
- localStorage.setItem('savedResult-' + Date.now(), JSON.stringify(savedData));
279
- alert('Réponse sauvegardée!');
 
 
 
 
 
 
 
280
  };
281
- reader.readAsDataURL(file); // On lit l'image comme une data URL
282
- } else {
283
- alert('Aucune image sélectionnée.');
284
- }
285
- });
286
- </script>
 
 
 
 
 
287
  </body>
288
 
289
  </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">
6
+ <title>Mariam AI - Résolution d'exercices Physique-Chimie</title>
7
+ <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
8
+ <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
9
+ <script src="https://cdn.tailwindcss.com"></script>
10
+ <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
11
+ <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
12
+ <style>
13
+ @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
14
+
15
+ body {
16
+ font-family: 'Poppins', sans-serif;
17
+ }
18
+
19
+ .loader {
20
+ width: 48px;
21
+ height: 48px;
22
+ border: 5px solid #FFF;
23
+ border-bottom-color: #3B82F6;
24
+ border-radius: 50%;
25
+ display: inline-block;
26
+ box-sizing: border-box;
27
+ animation: rotation 1s linear infinite;
28
+ }
29
+
30
+ @keyframes rotation {
31
+ 0% {
32
+ transform: rotate(0deg);
33
+ }
34
+
35
+ 100% {
36
+ transform: rotate(360deg);
37
+ }
38
+ }
39
+
40
+ .math-content {
41
+ font-size: 1.1em;
42
+ line-height: 1.6;
43
+ overflow-x: auto;
44
+ }
45
+
46
+ .math-content p {
47
+ margin-bottom: 1rem;
48
+ }
49
+
50
+ .math-content .MathJax {
51
+ overflow-x: auto;
52
+ overflow-y: hidden;
53
+ padding: 0.5rem 0;
54
+ }
55
+
56
+ @media (max-width: 640px) {
57
+ .math-content .MathJax {
58
+ font-size: 0.9em;
59
+ }
60
+ }
61
+
62
+ .math-hidden {
63
+ visibility: hidden;
64
+ }
65
+ .saved-result-item img {
66
+ max-width: 200px; /* Ajustez la taille maximale de l'image selon vos besoins */
67
+ max-height: 150px;
68
+ width: auto;
69
+ height: auto;
70
+ }
71
+ </style>
72
+ <script>
73
+ // Configuration de marked
74
+ marked.setOptions({
75
+ breaks: true,
76
+ gfm: true,
77
+ headerIds: false
78
+ });
79
+
80
+ // Configuration de MathJax
81
+ MathJax = {
82
+ tex: {
83
+ inlineMath: [['$', '$'], ['\\(', '\\)']],
84
+ displayMath: [['$$', '$$'], ['\\[', '\\]']],
85
+ processEscapes: true,
86
+ macros: {
87
+ R: "{\\mathbb{R}}",
88
+ N: "{\\mathbb{N}}",
89
+ Z: "{\\mathbb{Z}}",
90
+ vecv: ["\\begin{pmatrix}#1\\\\#2\\\\#3\\end{pmatrix}", 3]
91
+ }
92
+ },
93
+ svg: {
94
+ fontCache: 'global'
95
+ },
96
+ options: {
97
+ renderActions: {
98
+ addMenu: [],
99
+ checkLoading: [150, (doc) => {
100
+ document.querySelectorAll('.math-content').forEach(el => {
101
+ el.classList.remove('math-hidden');
102
+ });
103
+ }]
104
+ }
105
+ }
106
+ };
107
+ </script>
108
  </head>
109
 
110
  <body class="bg-gray-50 min-h-screen">
111
+ <!-- Navbar -->
112
+ <nav class="bg-white shadow-lg">
113
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
114
+ <div class="flex justify-between items-center h-16">
115
+ <div class="flex items-center">
116
+ <i class="fas fa-atom text-blue-600 text-2xl mr-2"></i>
117
+ <span class="font-bold text-xl text-gray-800">Mariam AI</span>
118
+ </div>
119
+ </div>
120
+ </div>
121
+ </nav>
122
+
123
+ <!-- Main Content -->
124
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
125
+ <div class="bg-white rounded-lg shadow-xl p-6 md:p-8">
126
+ <div class="text-center mb-8">
127
+ <h1 class="text-3xl font-bold text-gray-800 mb-2">Assistant Physique-Chimie</h1>
128
+ <p class="text-gray-600">Uploadez une photo de votre exercice pour obtenir une résolution détaillée</p>
129
+ </div>
130
+
131
+ <!-- Upload Section -->
132
+ <form id="upload-form" enctype="multipart/form-data">
133
+ <div class="flex flex-col items-center justify-center w-full">
134
+ <label for="image-input"
135
+ class="flex flex-col items-center justify-center w-full h-64 border-2 border-blue-300 border-dashed rounded-lg cursor-pointer bg-gray-50 hover:bg-gray-100 transition duration-300">
136
+ <div class="flex flex-col items-center justify-center pt-5 pb-6">
137
+ <i class="fas fa-cloud-upload-alt text-4xl text-blue-500 mb-4"></i>
138
+ <p class="mb-2 text-sm text-gray-500"><span class="font-semibold">Cliquez pour
139
+ upload</span> ou glissez-déposez</p>
140
+ <p class="text-xs text-gray-500">PNG, JPG ou JPEG</p>
141
+ </div>
142
+ <input id="image-input" type="file" name="image" class="hidden" accept="image/*" />
143
+ </label>
144
+ <button type="submit" id="submit-button"
145
+ class="mt-4 bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-lg hidden">
146
+ Soumettre
147
+ </button>
148
+ </div>
149
+ </form>
150
+
151
+ <!-- Preview Section -->
152
+ <div class="mt-8">
153
+ <img id="image-preview" class="max-w-full h-auto mx-auto rounded-lg shadow-md hidden" alt="Preview">
154
+ </div>
155
+
156
+ <!-- Loading Animation -->
157
+ <div id="loading" class="hidden flex justify-center items-center my-8">
158
+ <span class="loader"></span>
159
+ <span class="ml-3 text-gray-600">Analyse en cours...</span>
160
+ </div>
161
+
162
+ <!-- Result Section -->
163
+ <div id="result-container" class="hidden mt-8">
164
+ <h2 class="text-xl font-semibold text-gray-800 mb-4">Résolution détaillée :</h2>
165
+ <div class="flex items-center mb-4">
166
+ <button id="copy-button"
167
+ class="bg-gray-200 hover:bg-gray-300 text-gray-800 font-bold py-2 px-4 rounded-lg">
168
+ <i class="fas fa-copy mr-2"></i>Copier
169
+ </button>
170
+ <button id="save-button"
171
+ class="ml-4 bg-green-200 hover:bg-green-300 text-green-800 font-bold py-2 px-4 rounded-lg">
172
+ <i class="fas fa-save mr-2"></i>Sauvegarder
173
+ </button>
174
+ </div>
175
+ <div id="result" class="bg-gray-50 rounded-lg p-6 prose max-w-none math-content math-hidden"></div>
176
+ </div>
177
+ <!-- Section pour afficher les résultats sauvegardés -->
178
+ <div id="saved-results" class="mt-8">
179
+ <h2 class="text-xl font-semibold text-gray-800 mb-4">Résolutions Sauvegardées :</h2>
180
+ <div id="saved-results-list" class="space-y-4">
181
  </div>
182
+ </div>
183
+ </div>
184
+ </div>
185
+
186
+ <script>
187
+ const form = document.getElementById('upload-form');
188
+ const imageInput = document.getElementById('image-input');
189
+ const submitButton = document.getElementById('submit-button');
190
+ const imagePreview = document.getElementById('image-preview');
191
+ const loading = document.getElementById('loading');
192
+ const resultContainer = document.getElementById('result-container');
193
+ const result = document.getElementById('result');
194
+ const copyButton = document.getElementById('copy-button');
195
+ const saveButton = document.getElementById('save-button');
196
+ let generatedResult = '';
197
+
198
+ // Fonction pour afficher les résultats sauvegardés
199
+ function displaySavedResults() {
200
+ const savedResultsList = document.getElementById('saved-results-list');
201
+ savedResultsList.innerHTML = '';
202
+
203
+ for (let i = 0; i < localStorage.length; i++) {
204
+ const key = localStorage.key(i);
205
+ if (key.startsWith('savedResult-')) {
206
+ const savedData = JSON.parse(localStorage.getItem(key));
207
+ const resultItem = document.createElement('div');
208
+ resultItem.classList.add('saved-result-item', 'bg-gray-100', 'p-4', 'rounded-lg', 'shadow');
209
+ resultItem.innerHTML = `
210
+ <p class="text-sm text-gray-600 mb-2">Sauvegardé le : ${savedData.timestamp}</p>
211
+ <img src="${savedData.image}" alt="Image sauvegardée" class="mb-2">
212
+ <div class="math-content">${marked.parse(savedData.result)}</div>
213
+ `;
214
+ savedResultsList.appendChild(resultItem);
215
+ }
216
+ }
217
+ // Re-rendu MathJax pour les éléments chargés dynamiquement
218
+ MathJax.typesetPromise().catch((err) => {
219
+ console.error('Erreur MathJax:', err);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
  });
221
+ }
222
+
223
+ // Appeler displaySavedResults au chargement de la page
224
+ window.addEventListener('DOMContentLoaded', displaySavedResults);
225
+
226
+ imageInput.addEventListener('change', function (e) {
227
+ const file = e.target.files[0];
228
+ if (file) {
229
+ // Show preview
230
+ const reader = new FileReader();
231
+ reader.onload = function (e) {
232
+ imagePreview.src = e.target.result;
233
+ imagePreview.classList.remove('hidden');
234
+ submitButton.classList.remove('hidden');
235
+ };
236
+ reader.readAsDataURL(file);
237
+ } else {
238
+ imagePreview.src = "";
239
+ imagePreview.classList.add('hidden');
240
  submitButton.classList.add('hidden');
241
+ }
242
+ });
243
+
244
+ form.addEventListener('submit', async function (e) {
245
+ e.preventDefault();
246
+
247
+ // Show loading
248
+ loading.classList.remove('hidden');
249
+ resultContainer.classList.add('hidden');
250
+ result.classList.add('math-hidden');
251
+ submitButton.classList.add('hidden');
252
+
253
+ const formData = new FormData(form);
254
+
255
+ try {
256
+ const response = await fetch('/generate', {
257
+ method: 'POST',
258
+ body: formData
259
+ });
260
+
261
+ const data = await response.json();
262
+ generatedResult = data.result;
263
+
264
+ // Hide loading
265
+ loading.classList.add('hidden');
266
+
267
+ // Show result
268
+ resultContainer.classList.remove('hidden');
269
+ result.innerHTML = marked.parse(generatedResult);
270
+
271
+ // Rendre les maths avec MathJax
272
+ setTimeout(() => {
273
+ MathJax.typesetPromise([result])
274
+ .then(() => {
275
+ result.classList.remove('math-hidden');
276
+ })
277
+ .catch((err) => {
278
+ console.error('Erreur MathJax:', err);
279
+ result.innerHTML = "Erreur lors du rendu des mathématiques.";
280
+ result.classList.remove('math-hidden');
281
+ });
282
+ }, 0);
283
+
284
+ } catch (error) {
285
+ console.error('Erreur:', error);
286
+ loading.classList.add('hidden');
287
+ alert('Une erreur est survenue lors du traitement de l\'image.');
288
+ }
289
+ });
290
+
291
+ // Copier la réponse
292
+ copyButton.addEventListener('click', function () {
293
+ navigator.clipboard.writeText(generatedResult)
294
+ .then(() => {
295
+ // Message de confirmation (optionnel)
296
+ alert('Réponse copiée dans le presse-papiers!');
297
+ })
298
+ .catch(err => {
299
+ console.error('Erreur lors de la copie:', err);
300
+ });
301
+ });
302
+
303
+ // Sauvegarder la réponse dans le localStorage
304
+ saveButton.addEventListener('click', function () {
305
+ const timestamp = new Date().toLocaleString();
306
+ const file = imageInput.files[0];
307
+
308
+ if (file) {
309
+ const reader = new FileReader();
310
+ reader.onload = function (e) {
311
+ const savedData = {
312
+ timestamp: timestamp,
313
+ image: e.target.result, // On sauvegarde la data URL de l'image
314
+ result: generatedResult
315
  };
316
+
317
+ localStorage.setItem('savedResult-' + Date.now(), JSON.stringify(savedData));
318
+ alert('Réponse sauvegardée!');
319
+ displaySavedResults(); // Mettre à jour l'affichage des résultats sauvegardés
320
+ };
321
+ reader.readAsDataURL(file); // On lit l'image comme une data URL
322
+ } else {
323
+ alert('Aucune image sélectionnée.');
324
+ }
325
+ });
326
+ </script>
327
  </body>
328
 
329
  </html>