Docfile commited on
Commit
a3f3ee1
·
verified ·
1 Parent(s): 564705b

Update templates/philosophie.html

Browse files
Files changed (1) hide show
  1. templates/philosophie.html +106 -168
templates/philosophie.html CHANGED
@@ -1,104 +1,86 @@
 
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>Assistant de Philosophie</title>
7
 
8
  <script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
9
  <script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"></script>
10
 
11
  <link rel="preconnect" href="https://fonts.googleapis.com">
12
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
13
- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&family=Kalam&display=swap" rel="stylesheet">
14
-
15
 
16
  <style>
17
  :root {
18
- --primary-color: #3b82f6; /* Bleu doux */
19
- --primary-hover: #2563eb;
20
- --text-color-dark: #1f2937; /* Gris très foncé */
21
- --text-color-light: #4b5563; /* Gris moyen */
22
- --background-color: #f9fafb; /* Gris très clair */
23
  --container-bg: #ffffff;
24
- --border-color: #d1d5db;
25
- --border-focus-color: var(--primary-color);
26
- }
27
-
28
- /* === Reset et Base === */
29
- * {
30
- box-sizing: border-box;
31
  }
32
 
33
  body {
34
- font-family: 'Inter', sans-serif;
35
  background-color: var(--background-color);
36
  margin: 0;
37
- padding: 3rem 1.5rem;
38
- color: var(--text-color-dark);
39
  -webkit-font-smoothing: antialiased;
40
  -moz-osx-font-smoothing: grayscale;
41
  }
42
 
43
- /* === Layout et Conteneur principal === */
44
- #app {
45
- max-width: 800px;
46
  margin: 0 auto;
47
  background: var(--container-bg);
48
- padding: 2.5rem 3rem;
49
- border-radius: 16px;
50
- border: 1px solid var(--border-color);
51
- box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.05), 0 2px 4px -2px rgb(0 0 0 / 0.05);
52
  }
53
 
54
- /* === Typographie === */
55
  h1 {
56
  text-align: center;
57
- color: var(--text-color-dark);
58
- font-size: 2.25rem;
59
- font-weight: 700;
60
- margin-bottom: 0.25em;
61
  }
62
 
63
  .type-indicator {
64
  text-align: center;
65
- color: var(--text-color-light);
66
- font-size: 1rem;
67
- margin-bottom: 3rem;
68
- font-weight: 500;
69
- background-color: #f3f4f6;
70
- display: inline-block;
71
- padding: 0.25rem 0.75rem;
72
- border-radius: 999px;
73
- position: relative;
74
- left: 50%;
75
- transform: translateX(-50%);
76
- }
77
-
78
- label {
79
- display: block;
80
- margin-bottom: 0.5rem;
81
- font-weight: 500;
82
- color: var(--text-color-dark);
83
  }
84
 
85
- /* === Formulaires === */
86
  .form-group {
87
- margin-bottom: 1.5rem;
 
 
 
 
 
 
 
88
  }
89
 
90
  textarea, .form-select {
91
  width: 100%;
92
- padding: 0.875rem 1rem;
93
  border-radius: 8px;
94
  border: 1px solid var(--border-color);
95
- font-size: 1rem;
96
- line-height: 1.5;
97
- transition: border-color 0.2s, box-shadow 0.2s;
 
98
  background-color: #fff;
99
  -webkit-appearance: none;
100
  -moz-appearance: none;
101
  appearance: none;
 
102
  }
103
 
104
  .form-select {
@@ -110,34 +92,33 @@
110
  }
111
 
112
  textarea {
113
- min-height: 120px;
114
- resize: vertical;
115
  }
116
 
117
  textarea:focus, .form-select:focus {
118
  outline: none;
119
- border-color: var(--border-focus-color);
120
- box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);
121
  }
122
-
123
- /* === Boutons === */
124
  button {
125
  display: block;
 
126
  width: 100%;
127
- padding: 1rem;
128
  background-color: var(--primary-color);
129
  color: white;
130
  border: none;
131
  border-radius: 8px;
132
- font-size: 1.125rem;
133
- font-weight: 500;
134
  cursor: pointer;
135
- transition: background-color 0.2s, transform 0.1s;
136
  }
137
 
138
  button:hover:not(:disabled) {
139
  background-color: var(--primary-hover);
140
- transform: translateY(-1px);
141
  }
142
 
143
  button:disabled {
@@ -146,56 +127,41 @@
146
  }
147
 
148
  .download-container {
149
- margin-top: 1.5rem;
150
  }
151
  .secondary-button {
152
- background-color: transparent;
153
- color: var(--text-color-light);
154
- border: 1px solid var(--border-color);
155
  }
156
  .secondary-button:hover:not(:disabled) {
157
- background-color: #f9fafb;
158
  border-color: #9ca3af;
159
  }
160
 
161
- /* === Loader avec Pourcentage === */
162
- .loader-container {
163
- width: 100%;
164
- margin: 2.5rem 0;
165
- }
166
- .progress-bar {
167
- height: 12px;
168
- background-color: #e5e7eb;
169
- border-radius: 6px;
170
- overflow: hidden;
171
- }
172
- .progress-bar-inner {
173
- height: 100%;
174
- width: 0%;
175
- background-color: var(--primary-color);
176
- border-radius: 6px;
177
- transition: width 0.4s ease-in-out;
178
- }
179
- .progress-text {
180
- text-align: center;
181
- margin-top: 0.5rem;
182
- color: var(--text-color-light);
183
- font-weight: 500;
184
  }
 
185
 
186
- /* === Message d'erreur === */
187
  .error {
188
- color: #b91c1c;
189
  background-color: #fee2e2;
190
  text-align: center;
191
- margin-top: 1.5rem;
192
- padding: 1rem;
193
  border-radius: 8px;
194
- font-weight: 500;
195
- border: 1px solid #fecaca;
196
  }
197
 
198
- /* === Styles de la feuille de dissertation (INCHANGÉS) === */
199
  .dissertation-paper {
200
  font-family: 'Kalam', cursive;
201
  font-size: 20px;
@@ -206,7 +172,7 @@
206
  background-size: 100% 40px;
207
  border-left: 3px solid #ffaaab;
208
  padding-left: 4em;
209
- margin: 40px -48px -40px -48px; /* Ajusté au nouveau padding */
210
  padding-top: 30px;
211
  padding-bottom: 40px;
212
  padding-right: 30px;
@@ -226,11 +192,11 @@
226
  </style>
227
  </head>
228
  <body>
229
- <div id="app">
230
- <h1>Assistant Philosophique</h1>
231
- <p class="type-indicator">Méthode : [[ dissertationTypeLabel ]]</p>
232
 
233
- <form @submit.prevent="generateDissertation" v-if="!dissertation">
234
  <div class="form-group">
235
  <label for="dissertation-type">Choisir la méthodologie</label>
236
  <select id="dissertation-type" v-model="dissertationType" class="form-select">
@@ -240,7 +206,7 @@
240
  </div>
241
 
242
  <div class="form-group">
243
- <label for="course-context">Contexte du cours (optionnel)</label>
244
  <select id="course-context" v-model="selectedCourse" class="form-select">
245
  <option value="">-- Aucun cours en contexte --</option>
246
  <option v-for="course in courses" :key="course.id" :value="course.id">
@@ -250,47 +216,42 @@
250
  </div>
251
 
252
  <div class="form-group">
253
- <label for="question">Votre sujet de dissertation</label>
254
  <textarea id="question" v-model="question" placeholder="Entrez votre sujet ou la citation à analyser ici..."></textarea>
255
  </div>
256
  <button type="submit" :disabled="isLoading">
257
  [[ isLoading ? 'Génération en cours...' : 'Générer la dissertation' ]]
258
  </button>
259
  </form>
260
-
261
- <div v-if="isLoading" class="loader-container">
262
- <div class="progress-bar">
263
- <div class="progress-bar-inner" :style="{ width: loadingProgress + '%' }"></div>
264
- </div>
265
- <p class="progress-text">Analyse du sujet... [[ Math.round(loadingProgress) ]]%</p>
266
  </div>
267
 
 
268
  <p v-if="errorMessage" class="error">[[ errorMessage ]]</p>
269
-
270
- <div v-if="dissertation">
271
- <div class="download-container" data-html2canvas-ignore="true">
272
- <button class="secondary-button" @click="generatePDF">Télécharger la dissertation en PDF</button>
273
- </div>
274
- <div id="dissertation-content" class="dissertation-paper">
275
- <h2>Sujet : [[ dissertation.sujet ]]</h2>
276
- <p class="prof">Prof : [[ dissertation.prof ]]</p>
277
-
278
- <h3>Introduction</h3>
279
- <p class="indented">[[ dissertation.introduction ]]</p>
280
-
281
- <div v-for="partie in dissertation.parties" :key="partie.chapeau" class="avoid-page-break">
282
- <div class="development-block">
283
- <p class="indented">[[ partie.chapeau ]]</p>
284
- <p v-for="(arg, idx) in partie.arguments" :key="idx" class="indented">
285
- [[ arg.paragraphe_argumentatif ]]
286
- </p>
287
- </div>
288
- <p v-if="partie.transition" class="indented transition">[[ partie.transition ]]</p>
289
- </div>
290
 
291
- <h3>Conclusion</h3>
292
- <p class="indented">[[ dissertation.conclusion ]]</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
293
  </div>
 
 
 
 
294
  </div>
295
  </div>
296
 
@@ -302,11 +263,9 @@
302
  return {
303
  question: '',
304
  dissertationType: 'type1',
305
- courses: [],
306
- selectedCourse: '',
307
  isLoading: false,
308
- loadingProgress: 0, // Pour le nouveau loader
309
- progressInterval: null, // Pour stocker l'ID de l'intervalle
310
  errorMessage: null,
311
  dissertation: null
312
  }
@@ -317,13 +276,14 @@
317
  }
318
  },
319
  mounted() {
 
320
  this.fetchCourses();
321
  },
322
  methods: {
323
  async fetchCourses() {
324
  try {
325
  const response = await fetch('/api/philosophy/courses');
326
- if (!response.ok) throw new Error('Impossible de charger les cours.');
327
  const data = await response.json();
328
  if (data.error) throw new Error(data.error);
329
  this.courses = data;
@@ -332,28 +292,6 @@
332
  console.error("Erreur de chargement des cours:", error);
333
  }
334
  },
335
-
336
- // Méthode pour simuler la progression
337
- startProgressSimulation() {
338
- this.loadingProgress = 0;
339
- this.progressInterval = setInterval(() => {
340
- // Fait progresser la barre, mais ralentit en approchant de 99%
341
- if (this.loadingProgress < 99) {
342
- const increment = Math.random() * (100 - this.loadingProgress) / 25;
343
- this.loadingProgress = Math.min(99, this.loadingProgress + increment);
344
- }
345
- }, 200);
346
- },
347
-
348
- stopProgressSimulation() {
349
- clearInterval(this.progressInterval);
350
- this.loadingProgress = 100;
351
- // On cache la barre après une courte temporisation
352
- setTimeout(() => {
353
- this.isLoading = false;
354
- }, 500);
355
- },
356
-
357
  async generateDissertation() {
358
  if (!this.question.trim()) {
359
  this.errorMessage = "Veuillez entrer un sujet de dissertation.";
@@ -362,8 +300,6 @@
362
  this.isLoading = true;
363
  this.errorMessage = null;
364
  this.dissertation = null;
365
- this.startProgressSimulation(); // Démarrer la simulation
366
-
367
  try {
368
  const response = await fetch('/api/generate_dissertation', {
369
  method: 'POST',
@@ -371,7 +307,7 @@
371
  body: JSON.stringify({
372
  question: this.question,
373
  type: this.dissertationType,
374
- courseId: this.selectedCourse
375
  })
376
  });
377
  const data = await response.json();
@@ -382,7 +318,7 @@
382
  } catch (error) {
383
  this.errorMessage = error.message;
384
  } finally {
385
- this.stopProgressSimulation(); // Terminer la simulation
386
  }
387
  },
388
 
@@ -414,13 +350,15 @@
414
  await html2pdf().set(options).from(element).save();
415
  } catch (err) {
416
  console.error('Erreur html2pdf:', err);
417
- this.errorMessage = "Erreur lors de la génération du PDF.";
418
  }
419
  }
420
  }
421
  });
422
 
 
423
  app.config.compilerOptions.delimiters = ['[[', ']]'];
 
424
  app.mount('#app');
425
  </script>
426
  </body>
 
1
+
2
  <!DOCTYPE html>
3
  <html lang="fr">
4
  <head>
5
  <meta charset="UTF-8" />
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
7
+ <title>Assistant de Philosophie (Vue.js)</title>
8
 
9
  <script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
10
  <script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"></script>
11
 
12
  <link rel="preconnect" href="https://fonts.googleapis.com">
13
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
14
+ <link href="https://fonts.googleapis.com/css2?family=Kalam&family=Lato:wght@400;700&display=swap" rel="stylesheet">
 
15
 
16
  <style>
17
  :root {
18
+ --primary-color: #4f46e5; /* Indigo */
19
+ --primary-hover: #4338ca;
20
+ --text-color: #374151; /* Gris foncé */
21
+ --background-color: #f8f9fa;
 
22
  --container-bg: #ffffff;
23
+ --border-color: #e5e7eb;
 
 
 
 
 
 
24
  }
25
 
26
  body {
27
+ font-family: 'Lato', sans-serif;
28
  background-color: var(--background-color);
29
  margin: 0;
30
+ padding: 2rem;
31
+ color: var(--text-color);
32
  -webkit-font-smoothing: antialiased;
33
  -moz-osx-font-smoothing: grayscale;
34
  }
35
 
36
+ .container {
37
+ max-width: 960px;
 
38
  margin: 0 auto;
39
  background: var(--container-bg);
40
+ padding: 40px;
41
+ border-radius: 12px;
42
+ box-shadow: 0 6px 20px rgba(0,0,0,0.08);
 
43
  }
44
 
 
45
  h1 {
46
  text-align: center;
47
+ color: #111827;
48
+ margin-bottom: 0.5em;
 
 
49
  }
50
 
51
  .type-indicator {
52
  text-align: center;
53
+ color: #6b7280;
54
+ font-size: 1.1em;
55
+ margin-bottom: 2em;
56
+ font-weight: bold;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  }
58
 
 
59
  .form-group {
60
+ margin-bottom: 20px;
61
+ }
62
+
63
+ label {
64
+ display: block;
65
+ margin-bottom: 8px;
66
+ font-weight: 700;
67
+ color: #4b5563;
68
  }
69
 
70
  textarea, .form-select {
71
  width: 100%;
72
+ padding: 15px;
73
  border-radius: 8px;
74
  border: 1px solid var(--border-color);
75
+ min-height: 58px;
76
+ font-size: 16px;
77
+ line-height: 1.6;
78
+ transition: border-color 0.3s, box-shadow 0.3s;
79
  background-color: #fff;
80
  -webkit-appearance: none;
81
  -moz-appearance: none;
82
  appearance: none;
83
+ box-sizing: border-box;
84
  }
85
 
86
  .form-select {
 
92
  }
93
 
94
  textarea {
95
+ min-height: 100px;
 
96
  }
97
 
98
  textarea:focus, .form-select:focus {
99
  outline: none;
100
+ border-color: var(--primary-color);
101
+ box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.2);
102
  }
103
+
 
104
  button {
105
  display: block;
106
+ box-sizing: border-box;
107
  width: 100%;
108
+ padding: 16px;
109
  background-color: var(--primary-color);
110
  color: white;
111
  border: none;
112
  border-radius: 8px;
113
+ font-size: 18px;
114
+ font-weight: 700;
115
  cursor: pointer;
116
+ transition: background-color 0.3s, transform 0.2s;
117
  }
118
 
119
  button:hover:not(:disabled) {
120
  background-color: var(--primary-hover);
121
+ transform: translateY(-2px);
122
  }
123
 
124
  button:disabled {
 
127
  }
128
 
129
  .download-container {
130
+ margin-top: 15px;
131
  }
132
  .secondary-button {
133
+ background-color: #f3f4f6;
134
+ color: #374151;
135
+ border: 1px solid #d1d5db;
136
  }
137
  .secondary-button:hover:not(:disabled) {
138
+ background-color: #e5e7eb;
139
  border-color: #9ca3af;
140
  }
141
 
142
+ .loader {
143
+ display: block;
144
+ border: 8px solid #f3f3f3;
145
+ border-top: 8px solid var(--primary-color);
146
+ border-radius: 50%;
147
+ width: 50px;
148
+ height: 50px;
149
+ animation: spin 1s linear infinite;
150
+ margin: 30px auto;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  }
152
+ @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
153
 
 
154
  .error {
155
+ color: #ef4444;
156
  background-color: #fee2e2;
157
  text-align: center;
158
+ margin-top: 20px;
159
+ padding: 15px;
160
  border-radius: 8px;
161
+ font-weight: bold;
 
162
  }
163
 
164
+ /* Styles de la feuille de dissertation */
165
  .dissertation-paper {
166
  font-family: 'Kalam', cursive;
167
  font-size: 20px;
 
172
  background-size: 100% 40px;
173
  border-left: 3px solid #ffaaab;
174
  padding-left: 4em;
175
+ margin: 40px -40px -40px -40px;
176
  padding-top: 30px;
177
  padding-bottom: 40px;
178
  padding-right: 30px;
 
192
  </style>
193
  </head>
194
  <body>
195
+ <div id="app" class="container">
196
+ <h1>Assistant de Dissertation Philosophique</h1>
197
+ <p class="type-indicator">Méthodologie : [[ dissertationTypeLabel ]]</p>
198
 
199
+ <form @submit.prevent="generateDissertation">
200
  <div class="form-group">
201
  <label for="dissertation-type">Choisir la méthodologie</label>
202
  <select id="dissertation-type" v-model="dissertationType" class="form-select">
 
206
  </div>
207
 
208
  <div class="form-group">
209
+ <label for="course-context">Choisir un cours comme contexte (optionnel)</label>
210
  <select id="course-context" v-model="selectedCourse" class="form-select">
211
  <option value="">-- Aucun cours en contexte --</option>
212
  <option v-for="course in courses" :key="course.id" :value="course.id">
 
216
  </div>
217
 
218
  <div class="form-group">
219
+ <label for="question">Entrez votre sujet de dissertation</label>
220
  <textarea id="question" v-model="question" placeholder="Entrez votre sujet ou la citation à analyser ici..."></textarea>
221
  </div>
222
  <button type="submit" :disabled="isLoading">
223
  [[ isLoading ? 'Génération en cours...' : 'Générer la dissertation' ]]
224
  </button>
225
  </form>
226
+
227
+ <div v-if="dissertation" class="download-container" data-html2canvas-ignore="true">
228
+ <button class="secondary-button" @click="generatePDF">Télécharger la dissertation en PDF</button>
 
 
 
229
  </div>
230
 
231
+ <div v-if="isLoading" class="loader"></div>
232
  <p v-if="errorMessage" class="error">[[ errorMessage ]]</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233
 
234
+ <div v-if="dissertation" id="dissertation-content" class="dissertation-paper">
235
+
236
+ <h2>Sujet : [[ dissertation.sujet ]]</h2>
237
+ <p class="prof">Prof : [[ dissertation.prof ]]</p>
238
+
239
+ <h3>Introduction</h3>
240
+ <p class="indented">[[ dissertation.introduction ]]</p>
241
+
242
+ <div v-for="partie in dissertation.parties" :key="partie.chapeau" class="avoid-page-break">
243
+ <div class="development-block">
244
+ <p class="indented">[[ partie.chapeau ]]</p>
245
+ <p v-for="(arg, idx) in partie.arguments" :key="idx" class="indented">
246
+ [[ arg.paragraphe_argumentatif ]]
247
+ </p>
248
+ </div>
249
+ <p v-if="partie.transition" class="indented transition">[[ partie.transition ]]</p>
250
  </div>
251
+
252
+ <h3>Conclusion</h3>
253
+ <p class="indented">[[ dissertation.conclusion ]]</p>
254
+
255
  </div>
256
  </div>
257
 
 
263
  return {
264
  question: '',
265
  dissertationType: 'type1',
266
+ courses: [], // Pour stocker la liste des cours
267
+ selectedCourse: '', // Pour stocker l'ID du cours sélectionné
268
  isLoading: false,
 
 
269
  errorMessage: null,
270
  dissertation: null
271
  }
 
276
  }
277
  },
278
  mounted() {
279
+ // Au chargement du composant, on récupère la liste des cours
280
  this.fetchCourses();
281
  },
282
  methods: {
283
  async fetchCourses() {
284
  try {
285
  const response = await fetch('/api/philosophy/courses');
286
+ if (!response.ok) throw new Error('Impossible de charger les cours. Vérifiez la connexion à la base de données.');
287
  const data = await response.json();
288
  if (data.error) throw new Error(data.error);
289
  this.courses = data;
 
292
  console.error("Erreur de chargement des cours:", error);
293
  }
294
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
295
  async generateDissertation() {
296
  if (!this.question.trim()) {
297
  this.errorMessage = "Veuillez entrer un sujet de dissertation.";
 
300
  this.isLoading = true;
301
  this.errorMessage = null;
302
  this.dissertation = null;
 
 
303
  try {
304
  const response = await fetch('/api/generate_dissertation', {
305
  method: 'POST',
 
307
  body: JSON.stringify({
308
  question: this.question,
309
  type: this.dissertationType,
310
+ courseId: this.selectedCourse // On envoie l'ID du cours sélectionné
311
  })
312
  });
313
  const data = await response.json();
 
318
  } catch (error) {
319
  this.errorMessage = error.message;
320
  } finally {
321
+ this.isLoading = false;
322
  }
323
  },
324
 
 
350
  await html2pdf().set(options).from(element).save();
351
  } catch (err) {
352
  console.error('Erreur html2pdf:', err);
353
+ this.errorMessage = "Erreur lors de la génération du PDF. Voir la console pour les détails.";
354
  }
355
  }
356
  }
357
  });
358
 
359
+ // ⚠️ Changer les délimiteurs pour éviter le conflit avec Jinja2
360
  app.config.compilerOptions.delimiters = ['[[', ']]'];
361
+
362
  app.mount('#app');
363
  </script>
364
  </body>