Docfile commited on
Commit
1c71f62
·
verified ·
1 Parent(s): e26ec59

Update templates/philosophie.html

Browse files
Files changed (1) hide show
  1. templates/philosophie.html +194 -292
templates/philosophie.html CHANGED
@@ -3,189 +3,117 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Philosophie</title>
7
- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
8
- <script src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert2/11.7.3/sweetalert2.all.min.js"></script>
9
- <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/4.3.0/marked.min.js"></script>
10
- <link href="https://cdnjs.cloudflare.com/ajax/libs/sweetalert2/11.7.3/sweetalert2.min.css" rel="stylesheet">
11
  <style>
12
- .container {
13
- max-width: 800px;
14
- margin: 0 auto;
15
- padding: 20px;
16
  }
17
- .card {
18
- background: white;
19
- border-radius: 8px;
20
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
21
- padding: 20px;
 
 
 
 
 
 
 
22
  }
23
  .form-group {
24
- margin-bottom: 20px;
 
 
 
 
 
 
 
25
  }
26
  .btn {
27
- padding: 10px 20px;
28
- border: none;
29
- border-radius: 4px;
30
  cursor: pointer;
31
- margin-right: 10px;
32
- font-weight: bold;
33
  }
34
  .btn-primary {
35
- background-color: #4A90E2;
36
- color: white;
37
- }
38
- .btn-secondary {
39
- background-color: #6c757d;
40
  color: white;
41
  }
42
- .btn-success {
43
- background-color: #28a745;
44
- color: white;
45
- }
46
- .select-wrapper {
47
- margin-bottom: 20px;
48
- }
49
- select, textarea {
50
- width: 100%;
51
- padding: 8px;
52
- border: 1px solid #ddd;
53
- border-radius: 4px;
54
- margin-top: 5px;
55
- }
56
- .hidden {
57
- display: none;
58
- }
59
- #loader {
60
- text-align: center;
61
- padding: 20px;
62
  }
63
- #response {
64
- margin-top: 20px;
65
- padding: 15px;
66
- background: #f8f9fa;
67
- border-radius: 4px;
68
- line-height: 1.6;
69
  }
70
- .course-info {
71
- margin-top: 10px;
72
- font-size: 0.9em;
73
- color: #666;
74
  }
75
- .course-meta {
76
- display: flex;
77
- justify-content: space-between;
78
- margin-bottom: 10px;
79
- padding: 5px;
80
- background: #f8f9fa;
81
- border-radius: 4px;
82
  }
83
  .type-label {
84
- background: #4A90E2;
85
- color: white;
86
- padding: 5px 10px;
87
- border-radius: 4px;
88
- margin-bottom: 15px;
89
- display: inline-block;
90
- }
91
-
92
- /* Styles Markdown */
93
- #response h1 {
94
- font-size: 2em;
95
- margin-bottom: 0.5em;
96
- border-bottom: 2px solid #eee;
97
- padding-bottom: 0.3em;
98
- }
99
- #response h2 {
100
- font-size: 1.5em;
101
- margin-bottom: 0.5em;
102
- border-bottom: 1px solid #eee;
103
- padding-bottom: 0.3em;
104
- }
105
- #response h3 {
106
- font-size: 1.3em;
107
- margin-bottom: 0.5em;
108
- }
109
- #response p {
110
- margin-bottom: 1em;
111
- }
112
- #response ul, #response ol {
113
- margin-bottom: 1em;
114
- padding-left: 2em;
115
  }
116
- #response li {
117
- margin-bottom: 0.5em;
118
- }
119
- #response blockquote {
120
- border-left: 4px solid #ddd;
121
- padding-left: 1em;
122
- margin-left: 0;
123
- color: #666;
124
- }
125
- #response code {
126
- background-color: #f5f5f5;
127
- padding: 0.2em 0.4em;
128
- border-radius: 3px;
129
- font-family: monospace;
130
- }
131
- #response pre {
132
- background-color: #f5f5f5;
133
- padding: 1em;
134
- border-radius: 4px;
135
- overflow-x: auto;
136
- margin-bottom: 1em;
137
- }
138
- #response pre code {
139
- background-color: transparent;
140
- padding: 0;
141
- }
142
- #response table {
143
- border-collapse: collapse;
144
- width: 100%;
145
- margin-bottom: 1em;
146
- }
147
- #response th, #response td {
148
- border: 1px solid #ddd;
149
- padding: 8px;
150
- text-align: left;
151
- }
152
- #response th {
153
- background-color: #f5f5f5;
154
- }
155
- #response img {
156
  max-width: 100%;
157
  height: auto;
 
 
158
  }
159
- #response hr {
160
- border: none;
161
- border-top: 1px solid #ddd;
162
- margin: 1em 0;
 
 
 
 
 
 
 
163
  }
164
  </style>
165
  </head>
166
- <body>
167
- <div class="container">
168
  <div class="card">
169
- <h1 class="text-3xl font-bold text-gray-800">Philosophie</h1>
170
-
171
- <!-- Sélection du type de dissertation -->
172
  <div class="form-group">
173
- <label for="type-select">Type de dissertation :</label>
174
  <select id="type-select" class="form-control">
175
- <option value="1">Type 1 </option>
176
- <option value="2">Type 2 </option>
 
177
  </select>
178
  </div>
179
 
180
- <div class="type-label" id="current-type-label">Sujet de type 1</div>
 
 
181
 
182
- <!-- Sélection du cours -->
183
- <div class="form-group">
184
- <label for="course-select">Sélectionner un cours :</label>
185
  <select id="course-select" class="form-control">
186
  <option value="">Choisir un cours...</option>
187
  </select>
188
- <div class="course-info">
 
189
  <div class="course-meta hidden">
190
  <span id="course-author"></span>
191
  <span id="course-date"></span>
@@ -193,176 +121,150 @@
193
  </div>
194
  </div>
195
 
196
- <!-- Zone de texte pour la question -->
197
- <div class="form-group">
198
- <label for="question">Entrez juste le sujet :</label>
199
- <textarea id="question" rows="4" class="form-control"></textarea>
200
  </div>
201
 
202
- <!-- Bouton de soumission -->
203
- <button id="submit-btn" class="btn btn-success">Soumettre</button>
 
 
 
 
 
 
 
 
 
204
 
205
  <!-- Loader -->
206
- <div id="loader" class="hidden">
207
- Chargement en cours...
208
- </div>
209
 
210
- <!-- Zone de réponse -->
211
  <div id="response" class="hidden"></div>
212
 
213
- <!-- Bouton de copie -->
214
- <button id="copy-btn" class="btn btn-secondary hidden">Copier la réponse</button>
 
 
215
  </div>
216
  </div>
217
 
218
  <script>
219
- $(document).ready(function() {
220
- // Configuration de marked
221
- marked.setOptions({
222
- breaks: true,
223
- gfm: true,
224
- headerIds: true,
225
- langPrefix: 'language-'
226
- });
227
-
228
- // Configuration des toasts SweetAlert2
229
- const Toast = Swal.mixin({
230
- toast: true,
231
- position: 'top-end',
232
- showConfirmButton: false,
233
- timer: 3000,
234
- timerProgressBar: true
235
- });
236
-
237
- // Gestion du changement de type
238
- $('#type-select').change(function() {
239
- const type = $(this).val();
240
- $('#current-type-label').text(`Sujet de type ${type}`);
241
- });
242
 
243
- // Charger les cours depuis la base de données
244
- $.ajax({
245
- url: '/api/philosophy/courses',
246
- method: 'GET',
247
- success: function(courses) {
248
- const select = $('#course-select');
249
  courses.forEach(course => {
250
- select.append(`<option value="${course.id}">${course.title}</option>`);
 
 
 
251
  });
252
- },
253
- error: function() {
254
- Toast.fire({
255
- icon: 'error',
256
- title: 'Erreur lors du chargement des cours'
257
- });
258
- }
259
- });
260
 
261
- // Gestion du changement de cours
262
- $('#course-select').change(function() {
263
- const courseId = $(this).val();
264
- if (courseId) {
265
- $.ajax({
266
- url: `/api/philosophy/courses/${courseId}`,
267
- method: 'GET',
268
- success: function(course) {
269
- $('.course-meta').removeClass('hidden');
270
- $('#course-author').text(`Professeur: ${course.author}`);
271
- $('#course-date').text(`Mis à jour: ${new Date(course.updated_at).toLocaleDateString()}`);
272
-
273
- Toast.fire({
274
- icon: 'success',
275
- title: 'Cours chargé avec succès'
276
- });
277
- },
278
- error: function() {
279
- Toast.fire({
280
- icon: 'error',
281
- title: 'Erreur lors du chargement des détails du cours'
282
- });
283
- }
284
- });
285
  } else {
286
- $('.course-meta').addClass('hidden');
 
 
287
  }
288
  });
289
 
290
- // Gestion de la soumission
291
- $('#submit-btn').click(function() {
292
- const question = $('#question').val().trim();
293
- const type = $('#type-select').val();
294
-
295
- if (!question) {
296
- Swal.fire({
297
- icon: 'warning',
298
- title: 'Attention',
299
- text: 'Veuillez saisir une question.'
300
- });
301
- return;
302
  }
 
303
 
304
- Swal.fire({
305
- title: 'Generation en cours',
306
- html: 'Veuillez patienter...',
307
- allowOutsideClick: false,
308
- didOpen: () => {
309
- Swal.showLoading();
310
- }
311
- });
312
-
313
- // Préparation des données
314
- const data = {
315
- question: question,
316
  type: type
317
  };
318
 
319
- // Ajout du courseId seulement s'il est sélectionné
320
- const courseId = $('#course-select').val();
321
- if (courseId) {
322
- data.courseId = courseId;
323
- }
324
 
325
- $.ajax({
326
- url: '/submit_philo',
327
- method: 'POST',
328
- contentType: 'application/json',
329
- data: JSON.stringify(data),
330
- success: function(data) {
331
- Swal.close();
332
- // Conversion du Markdown en HTML
333
- const htmlContent = marked.parse(data.response);
334
- $('#response').html(htmlContent).removeClass('hidden');
335
- $('#copy-btn').removeClass('hidden');
336
-
337
- Toast.fire({
338
- icon: 'success',
339
- title: 'Réponse générée avec succès'
340
- });
341
- },
342
- error: function(xhr) {
343
- Swal.fire({
344
- icon: 'error',
345
- title: 'Erreur',
346
- text: 'Une erreur est survenue lors de la génération de la réponse.'
347
- });
348
  }
349
- });
350
- });
351
 
352
- // Gestion de la copie de la réponse
353
- $('#copy-btn').click(function() {
354
- const response = $('#response').text();
355
- navigator.clipboard.writeText(response).then(function() {
356
- Toast.fire({
357
- icon: 'success',
358
- title: 'Réponse copiée avec succès'
359
- });
360
- }).catch(function() {
361
- Toast.fire({
362
- icon: 'error',
363
- title: 'Erreur lors de la copie'
364
  });
365
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
366
  });
367
  });
368
  </script>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Philosophie - Dissertation Assistant</title>
7
+ <link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
 
 
 
8
  <style>
9
+ .hidden {
10
+ display: none;
 
 
11
  }
12
+ .loader {
13
+ border: 4px solid #f3f3f3;
14
+ border-radius: 50%;
15
+ border-top: 4px solid #3498db;
16
+ width: 40px;
17
+ height: 40px;
18
+ animation: spin 1s linear infinite;
19
+ margin: 20px auto;
20
+ }
21
+ @keyframes spin {
22
+ 0% { transform: rotate(0deg); }
23
+ 100% { transform: rotate(360deg); }
24
  }
25
  .form-group {
26
+ margin-bottom: 1.5rem;
27
+ }
28
+ .form-control {
29
+ width: 100%;
30
+ padding: 0.5rem;
31
+ border: 1px solid #e2e8f0;
32
+ border-radius: 0.375rem;
33
+ margin-top: 0.5rem;
34
  }
35
  .btn {
36
+ padding: 0.5rem 1rem;
37
+ border-radius: 0.375rem;
38
+ font-weight: 500;
39
  cursor: pointer;
40
+ transition: all 0.2s;
 
41
  }
42
  .btn-primary {
43
+ background-color: #4299e1;
 
 
 
 
44
  color: white;
45
  }
46
+ .btn-primary:hover {
47
+ background-color: #3182ce;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  }
49
+ .btn-secondary {
50
+ background-color: #cbd5e0;
51
+ color: #2d3748;
52
+ margin-top: 1rem;
 
 
53
  }
54
+ .btn-secondary:hover {
55
+ background-color: #a0aec0;
 
 
56
  }
57
+ .card {
58
+ background-color: white;
59
+ border-radius: 0.5rem;
60
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
61
+ padding: 1.5rem;
62
+ margin: 1rem auto;
63
+ max-width: 800px;
64
  }
65
  .type-label {
66
+ margin: 1rem 0;
67
+ font-weight: 500;
68
+ color: #4a5568;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  }
70
+ #image-preview img {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  max-width: 100%;
72
  height: auto;
73
+ border-radius: 0.375rem;
74
+ margin-top: 1rem;
75
  }
76
+ #response {
77
+ margin-top: 1.5rem;
78
+ padding: 1rem;
79
+ border: 1px solid #e2e8f0;
80
+ border-radius: 0.375rem;
81
+ white-space: pre-wrap;
82
+ }
83
+ .course-meta {
84
+ font-size: 0.875rem;
85
+ color: #718096;
86
+ margin-top: 0.5rem;
87
  }
88
  </style>
89
  </head>
90
+ <body class="bg-gray-100 min-h-screen py-8">
91
+ <div class="container mx-auto px-4">
92
  <div class="card">
93
+ <h1 class="text-3xl font-bold text-gray-800 mb-6">Philosophie</h1>
94
+
95
+ <!-- Type Selection -->
96
  <div class="form-group">
97
+ <label class="block text-gray-700 font-medium">Type de dissertation :</label>
98
  <select id="type-select" class="form-control">
99
+ <option value="1">Type 1</option>
100
+ <option value="2">Type 2</option>
101
+ <option value="3">Type 3 (Image)</option>
102
  </select>
103
  </div>
104
 
105
+ <div id="current-type-label" class="type-label">
106
+ Sujet de type 1
107
+ </div>
108
 
109
+ <!-- Course Selection (for types 1 and 2) -->
110
+ <div id="course-section" class="form-group">
111
+ <label class="block text-gray-700 font-medium">Sélectionner un cours :</label>
112
  <select id="course-select" class="form-control">
113
  <option value="">Choisir un cours...</option>
114
  </select>
115
+
116
+ <div id="course-info">
117
  <div class="course-meta hidden">
118
  <span id="course-author"></span>
119
  <span id="course-date"></span>
 
121
  </div>
122
  </div>
123
 
124
+ <!-- Text Input (for types 1 and 2) -->
125
+ <div id="text-input-section" class="form-group">
126
+ <label class="block text-gray-700 font-medium">Entrez juste le sujet :</label>
127
+ <textarea id="question-input" class="form-control" rows="4"></textarea>
128
  </div>
129
 
130
+ <!-- Image Upload (for type 3) -->
131
+ <div id="image-upload-section" class="form-group hidden">
132
+ <label class="block text-gray-700 font-medium">Sélectionnez une image :</label>
133
+ <input type="file" id="image-input" accept="image/*" class="form-control">
134
+ <div id="image-preview" class="mt-3"></div>
135
+ </div>
136
+
137
+ <!-- Submit Button -->
138
+ <button id="submit-btn" class="btn btn-primary w-full">
139
+ Soumettre
140
+ </button>
141
 
142
  <!-- Loader -->
143
+ <div id="loader" class="loader hidden"></div>
 
 
144
 
145
+ <!-- Response Section -->
146
  <div id="response" class="hidden"></div>
147
 
148
+ <!-- Copy Button -->
149
+ <button id="copy-btn" class="btn btn-secondary w-full">
150
+ Copier la réponse
151
+ </button>
152
  </div>
153
  </div>
154
 
155
  <script>
156
+ document.addEventListener('DOMContentLoaded', function() {
157
+ const typeSelect = document.getElementById('type-select');
158
+ const courseSection = document.getElementById('course-section');
159
+ const textInputSection = document.getElementById('text-input-section');
160
+ const imageUploadSection = document.getElementById('image-upload-section');
161
+ const typeLabel = document.getElementById('current-type-label');
162
+ const imageInput = document.getElementById('image-input');
163
+ const imagePreview = document.getElementById('image-preview');
164
+ const submitBtn = document.getElementById('submit-btn');
165
+ const loader = document.getElementById('loader');
166
+ const response = document.getElementById('response');
167
+ const copyBtn = document.getElementById('copy-btn');
168
+ const courseSelect = document.getElementById('course-select');
 
 
 
 
 
 
 
 
 
 
169
 
170
+ // Load courses on page load
171
+ fetch('/api/philosophy/courses')
172
+ .then(response => response.json())
173
+ .then(courses => {
 
 
174
  courses.forEach(course => {
175
+ const option = document.createElement('option');
176
+ option.value = course.id;
177
+ option.textContent = course.title;
178
+ courseSelect.appendChild(option);
179
  });
180
+ })
181
+ .catch(error => console.error('Error loading courses:', error));
 
 
 
 
 
 
182
 
183
+ typeSelect.addEventListener('change', function() {
184
+ const selectedType = this.value;
185
+ typeLabel.textContent = `Sujet de type ${selectedType}`;
186
+
187
+ if (selectedType === '3') {
188
+ courseSection.classList.add('hidden');
189
+ textInputSection.classList.add('hidden');
190
+ imageUploadSection.classList.remove('hidden');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
  } else {
192
+ courseSection.classList.remove('hidden');
193
+ textInputSection.classList.remove('hidden');
194
+ imageUploadSection.classList.add('hidden');
195
  }
196
  });
197
 
198
+ imageInput.addEventListener('change', function(e) {
199
+ const file = e.target.files[0];
200
+ if (file) {
201
+ const reader = new FileReader();
202
+ reader.onload = function(e) {
203
+ const img = document.createElement('img');
204
+ img.src = e.target.result;
205
+ img.className = 'max-w-full h-auto';
206
+ imagePreview.innerHTML = '';
207
+ imagePreview.appendChild(img);
208
+ };
209
+ reader.readAsDataURL(file);
210
  }
211
+ });
212
 
213
+ submitBtn.addEventListener('click', async function() {
214
+ const type = typeSelect.value;
215
+ let data = {
 
 
 
 
 
 
 
 
 
216
  type: type
217
  };
218
 
219
+ loader.classList.remove('hidden');
220
+ response.classList.add('hidden');
 
 
 
221
 
222
+ try {
223
+ if (type === '3') {
224
+ const imagePreviewImg = imagePreview.querySelector('img');
225
+ if (!imagePreviewImg) {
226
+ alert('Veuillez sélectionner une image');
227
+ return;
228
+ }
229
+ data.image = imagePreviewImg.src;
230
+ } else {
231
+ const questionInput = document.getElementById('question-input');
232
+ if (!questionInput.value.trim()) {
233
+ alert('Veuillez entrer un sujet');
234
+ return;
235
+ }
236
+ data.question = questionInput.value;
237
+ data.courseId = courseSelect.value;
 
 
 
 
 
 
 
238
  }
 
 
239
 
240
+ const res = await fetch('/submit_philo', {
241
+ method: 'POST',
242
+ headers: {
243
+ 'Content-Type': 'application/json',
244
+ },
245
+ body: JSON.stringify(data)
 
 
 
 
 
 
246
  });
247
+
248
+ const result = await res.json();
249
+
250
+ if (result.error) {
251
+ throw new Error(result.error);
252
+ }
253
+
254
+ response.innerHTML = result.response.replace(/\n/g, '<br>');
255
+ response.classList.remove('hidden');
256
+ } catch (error) {
257
+ alert('Erreur : ' + error.message);
258
+ } finally {
259
+ loader.classList.add('hidden');
260
+ }
261
+ });
262
+
263
+ copyBtn.addEventListener('click', function() {
264
+ const responseText = response.innerText;
265
+ navigator.clipboard.writeText(responseText)
266
+ .then(() => alert('Réponse copiée !'))
267
+ .catch(err => alert('Erreur lors de la copie : ' + err));
268
  });
269
  });
270
  </script>