Docfile commited on
Commit
1c9d3b3
·
verified ·
1 Parent(s): 854dd69

Update templates/philosophie.html

Browse files
Files changed (1) hide show
  1. templates/philosophie.html +299 -386
templates/philosophie.html CHANGED
@@ -3,306 +3,157 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Mariam AI - 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
- :root {
13
- --primary-color: #6366f1;
14
- --secondary-color: #4f46e5;
15
- --accent-color: #818cf8;
16
- --background-color: #f3f4f6;
17
- --card-background: #ffffff;
18
- --text-primary: #1f2937;
19
- --text-secondary: #4b5563;
20
- --success-color: #10b981;
21
- --warning-color: #f59e0b;
22
- --error-color: #ef4444;
23
- }
24
-
25
- * {
26
- margin: 0;
27
- padding: 0;
28
- box-sizing: border-box;
29
- font-family: 'Inter', system-ui, sans-serif;
30
- }
31
-
32
- body {
33
- background: var(--background-color);
34
- color: var(--text-primary);
35
- line-height: 1.6;
36
- }
37
-
38
- .container {
39
- max-width: 1000px;
40
- margin: 2rem auto;
41
- padding: 0 1.5rem;
42
- }
43
-
44
- .header {
45
- text-align: center;
46
- margin-bottom: 2rem;
47
- }
48
-
49
- .logo {
50
- font-size: 2.5rem;
51
- font-weight: 800;
52
- color: var(--primary-color);
53
- margin-bottom: 0.5rem;
54
- }
55
-
56
- .subtitle {
57
- color: var(--text-secondary);
58
- font-size: 1.1rem;
59
- }
60
-
61
- .card {
62
- background: var(--card-background);
63
- border-radius: 1rem;
64
- box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -1px rgba(0,0,0,0.06);
65
- padding: 2rem;
66
- margin-bottom: 2rem;
67
- }
68
-
69
- .form-group {
70
- margin-bottom: 1.5rem;
71
- }
72
-
73
- .form-group label {
74
- display: block;
75
- font-weight: 600;
76
- margin-bottom: 0.5rem;
77
- color: var(--text-primary);
78
- }
79
-
80
- select, textarea {
81
- width: 100%;
82
- padding: 0.75rem;
83
- border: 2px solid #e5e7eb;
84
- border-radius: 0.5rem;
85
- font-size: 1rem;
86
- transition: all 0.3s ease;
87
- }
88
-
89
- select:focus, textarea:focus {
90
- outline: none;
91
- border-color: var(--primary-color);
92
- box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2);
93
- }
94
-
95
- .btn {
96
- display: inline-flex;
97
- align-items: center;
98
- justify-content: center;
99
- padding: 0.75rem 1.5rem;
100
- border-radius: 0.5rem;
101
- font-weight: 600;
102
- transition: all 0.3s ease;
103
- cursor: pointer;
104
- border: none;
105
- gap: 0.5rem;
106
- }
107
-
108
- .btn-primary {
109
- background: var(--primary-color);
110
- color: white;
111
- }
112
-
113
- .btn-primary:hover {
114
- background: var(--secondary-color);
115
- }
116
-
117
- .btn-secondary {
118
- background: var(--text-secondary);
119
- color: white;
120
- }
121
-
122
- .btn-secondary:hover {
123
- background: var(--text-primary);
124
- }
125
-
126
- .type-badge {
127
- display: inline-flex;
128
- align-items: center;
129
- padding: 0.5rem 1rem;
130
- background: var(--accent-color);
131
- color: white;
132
- border-radius: 9999px;
133
- font-weight: 600;
134
- font-size: 0.875rem;
135
- margin-bottom: 1rem;
136
- }
137
-
138
- .course-meta {
139
- display: flex;
140
- justify-content: space-between;
141
- align-items: center;
142
- padding: 1rem;
143
- background: var(--background-color);
144
- border-radius: 0.5rem;
145
- margin: 1rem 0;
146
- }
147
-
148
- .course-meta span {
149
- display: flex;
150
- align-items: center;
151
- gap: 0.5rem;
152
- color: var(--text-secondary);
153
- font-size: 0.875rem;
154
- }
155
-
156
- #response {
157
- background: var(--background-color);
158
- padding: 1.5rem;
159
- border-radius: 0.5rem;
160
- margin-top: 1.5rem;
161
- }
162
-
163
- #response h1, #response h2, #response h3 {
164
- color: var(--text-primary);
165
- margin-bottom: 1rem;
166
- border-bottom: 2px solid #e5e7eb;
167
- padding-bottom: 0.5rem;
168
- }
169
-
170
- .actions {
171
- display: flex;
172
- gap: 1rem;
173
- margin-top: 1.5rem;
174
- }
175
-
176
- .loading-overlay {
177
- position: fixed;
178
- top: 0;
179
- left: 0;
180
- right: 0;
181
- bottom: 0;
182
- background: rgba(255, 255, 255, 0.9);
183
- display: flex;
184
- justify-content: center;
185
- align-items: center;
186
- z-index: 1000;
187
- }
188
-
189
- .loading-spinner {
190
- width: 50px;
191
- height: 50px;
192
- border: 4px solid var(--background-color);
193
- border-top: 4px solid var(--primary-color);
194
- border-radius: 50%;
195
- animation: spin 1s linear infinite;
196
- }
197
-
198
- @keyframes spin {
199
- 0% { transform: rotate(0deg); }
200
- 100% { transform: rotate(360deg); }
201
- }
202
-
203
- .hidden {
204
- display: none;
205
- }
206
-
207
- @media (max-width: 768px) {
208
- .container {
209
- padding: 1rem;
210
- }
211
-
212
- .card {
213
- padding: 1.5rem;
214
- }
215
-
216
- .course-meta {
217
- flex-direction: column;
218
- gap: 0.5rem;
219
- }
220
- }
221
- </style>
222
  </head>
223
- <body>
224
- <div class="container">
225
- <div class="header">
226
- <h1 class="logo">Mariam AI</h1>
227
- <p class="subtitle">Assistant de dissertation philosophique</p>
228
- </div>
229
-
230
- <div class="card">
231
- <div class="type-badge" id="current-type-label">
232
- <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" viewBox="0 0 20 20" fill="currentColor" style="width: 20px; height: 20px; margin-right: 8px;">
233
- <path d="M17.414 2.586a2 2 0 00-2.828 0L7 10.172V13h2.828l7.586-7.586a2 2 0 000-2.828z" />
234
- <path fill-rule="evenodd" d="M2 6a2 2 0 012-2h4a1 1 0 010 2H4v10h10v-4a1 1 0 112 0v4a2 2 0 01-2 2H4a2 2 0 01-2-2V6z" clip-rule="evenodd" />
235
- </svg>
236
- Sujet de type 1
237
- </div>
238
-
239
- <div class="form-group">
240
- <label for="type-select">Type de dissertation</label>
241
- <select id="type-select">
242
- <option value="1">Type 1 - Dissertation classique</option>
243
- <option value="2">Type 2 - Analyse de texte</option>
244
- </select>
245
- </div>
246
-
247
- <div class="form-group">
248
- <label for="course-select">Sélectionner un cours</label>
249
- <select id="course-select">
250
- <option value="">Choisir un cours...</option>
251
- </select>
252
-
253
- <div class="course-meta hidden">
254
- <span id="course-author">
255
- <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" style="width: 20px; height: 20px;">
256
- <path fill-rule="evenodd" d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z" clip-rule="evenodd" />
257
- </svg>
258
- <span></span>
259
- </span>
260
- <span id="course-date">
261
- <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" style="width: 20px; height: 20px;">
262
- <path fill-rule="evenodd" d="M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z" clip-rule="evenodd" />
263
- </svg>
264
- <span></span>
265
  </span>
266
  </div>
267
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
268
 
269
- <div class="form-group">
270
- <label for="question">Sujet de dissertation</label>
271
- <textarea id="question" rows="4" placeholder="Entrez votre sujet de dissertation ici..."></textarea>
272
- </div>
273
-
274
- <div class="actions">
275
- <button id="submit-btn" class="btn btn-primary">
276
- <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" style="width: 20px; height: 20px;">
277
- <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z" clip-rule="evenodd" />
278
- </svg>
279
- Générer
280
- </button>
281
-
282
- <button id="copy-btn" class="btn btn-secondary hidden">
283
- <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" style="width: 20px; height: 20px;">
284
- <path d="M8 3a1 1 0 011-1h2a1 1 0 110 2H9a1 1 0 01-1-1z" />
285
- <path d="M6 3a2 2 0 00-2 2v11a2 2 0 002 2h8a2 2 0 002-2V5a2 2 0 00-2-2 3 3 0 01-3 3H9a3 3 0 01-3-3z" />
286
- </svg>
287
- Copier
288
- </button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
289
  </div>
290
-
291
- <div id="response" class="hidden"></div>
292
  </div>
293
  </div>
294
 
295
  <script>
296
  $(document).ready(function() {
297
- // Configuration de marked
298
  marked.setOptions({
299
  breaks: true,
300
  gfm: true,
301
  headerIds: true,
302
- langPrefix: 'language-'
 
 
303
  });
304
 
305
- // Configuration des toasts SweetAlert2
306
  const Toast = Swal.mixin({
307
  toast: true,
308
  position: 'top-end',
@@ -310,206 +161,268 @@
310
  timer: 3000,
311
  timerProgressBar: true,
312
  customClass: {
313
- popup: 'colored-toast'
314
  }
315
  });
316
 
 
 
 
 
 
 
 
 
 
 
 
 
317
  // Gestion du changement de type
318
  $('#type-select').change(function() {
319
  const type = $(this).val();
320
- const typeText = type === "1" ? "Dissertation classique" : "Analyse de texte";
321
- $('#current-type-label').html(`
322
- <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" viewBox="0 0 20 20" fill="currentColor" style="width: 20px; height: 20px; margin-right: 8px;">
323
- <path d="M17.414 2.586a2 2 0 00-2.828 0L7 10.172V13h2.828l7.586-7.586a2 2 0 000-2.828z" />
324
- <path fill-rule="evenodd" d="M2 6a2 2 0 012-2h4a1 1 0 010 2H4v10h10v-4a1 1 0 112 0v4a2 2 0 01-2 2H4a2 2 0 01-2-2V6z" clip-rule="evenodd" />
325
- </svg>
326
- Sujet de type ${type} - ${typeText}
327
- `);
328
  });
329
 
330
- // Charger les cours
331
- $.ajax({
332
- url: '/api/philosophy/courses',
333
- method: 'GET',
334
- success: function(courses) {
 
 
 
 
 
 
 
 
 
 
 
335
  const select = $('#course-select');
336
  courses.forEach(course => {
337
  select.append(`<option value="${course.id}">${course.title}</option>`);
338
  });
339
- },
340
- error: function() {
341
  Toast.fire({
342
  icon: 'error',
343
- title: 'Erreur lors du chargement des cours'
 
344
  });
345
- }
346
- });
347
 
348
- // Gestion du changement de cours
349
  $('#course-select').change(function() {
350
  const courseId = $(this).val();
351
  if (courseId) {
352
- $.ajax({url: `/api/philosophy/courses/${courseId}`,
 
353
  method: 'GET',
 
 
 
354
  success: function(course) {
355
- $('.course-meta').removeClass('hidden');
356
- $('#course-author span').text(`Prof. ${course.author}`);
357
- $('#course-date span').text(`Mis à jour le ${new Date(course.updated_at).toLocaleDateString('fr-FR')}`);
358
-
359
- Toast.fire({
360
- icon: 'success',
361
- title: 'Cours chargé avec succès',
362
- background: '#10b981',
363
- color: '#ffffff'
364
- });
365
  },
366
  error: function() {
367
  Toast.fire({
368
  icon: 'error',
369
- title: 'Erreur lors du chargement des détails du cours',
370
- background: '#ef4444',
371
- color: '#ffffff'
372
  });
373
  }
374
  });
375
  } else {
376
- $('.course-meta').addClass('hidden');
 
 
377
  }
378
  });
379
 
380
- // Gestion de la soumission
381
  $('#submit-btn').click(function() {
382
  const question = $('#question').val().trim();
383
- const type = $('#type-select').val();
384
-
385
  if (!question) {
 
 
 
 
 
 
386
  Swal.fire({
387
  icon: 'warning',
388
- title: 'Attention',
389
- text: 'Veuillez saisir un sujet de dissertation.',
390
- confirmButtonColor: var(--primary-color),
391
- background: '#ffffff',
 
 
 
 
392
  customClass: {
393
- title: 'swal-title',
394
- content: 'swal-text'
395
  }
396
  });
397
  return;
398
  }
399
 
400
- // Animation de chargement personnalisée
401
  Swal.fire({
402
  title: 'Génération en cours',
403
  html: `
404
- <div class="loading-animation">
405
- <div class="loading-spinner"></div>
406
- <p style="margin-top: 1rem; color: var(--text-secondary)">
407
- L'IA analyse votre sujet...
408
- </p>
 
 
 
 
 
 
409
  </div>
410
  `,
411
  allowOutsideClick: false,
412
  showConfirmButton: false,
413
  customClass: {
414
- popup: 'loading-popup'
415
  }
416
  });
417
 
418
- // Préparation des données
419
  const data = {
420
  question: question,
421
- type: type,
422
- model: "mariam-ai-v2" // Version spécifique du modèle
423
  };
424
 
425
- // Ajout du courseId si sélectionné
426
- const courseId = $('#course-select').val();
427
- if (courseId) {
428
- data.courseId = courseId;
429
- }
430
-
431
  $.ajax({
432
- url: '/api/philosophy/generate',
433
  method: 'POST',
434
  contentType: 'application/json',
435
  data: JSON.stringify(data),
436
- success: function(response) {
437
  Swal.close();
438
-
439
- // Animation de transition
440
- $('#response').fadeOut(200, function() {
441
- // Conversion du Markdown en HTML avec syntax highlighting
442
- const htmlContent = marked.parse(response.content);
443
- $(this)
444
- .html(htmlContent)
445
- .fadeIn(400)
446
- .removeClass('hidden');
447
- });
448
 
449
- $('#copy-btn').removeClass('hidden');
450
-
451
- Toast.fire({
452
- icon: 'success',
453
- title: 'Dissertation générée avec succès',
454
- background: '#10b981',
455
- color: '#ffffff'
456
- });
 
 
 
457
 
458
  // Scroll smooth vers la réponse
459
  $('html, body').animate({
460
  scrollTop: $('#response').offset().top - 100
461
  }, 800);
 
 
 
 
 
 
462
  },
463
- error: function(xhr) {
464
  Swal.fire({
465
  icon: 'error',
466
- title: 'Erreur',
467
- text: xhr.responseJSON?.message || 'Une erreur est survenue lors de la génération de la dissertation.',
468
- confirmButtonColor: var(--primary-color),
469
- background: '#ffffff'
 
 
470
  });
471
  }
472
  });
473
  });
474
 
475
- // Gestion de la copie avec animation
476
  $('#copy-btn').click(function() {
477
  const response = $('#response').text();
 
 
 
 
478
  navigator.clipboard.writeText(response)
479
- .then(function() {
480
- // Animation du bouton
481
- const $btn = $('#copy-btn');
482
- $btn.css('transform', 'scale(0.95)');
483
- setTimeout(() => $btn.css('transform', 'scale(1)'), 200);
 
 
 
484
 
485
  Toast.fire({
486
  icon: 'success',
487
- title: 'Copié dans le presse-papiers',
488
- background: '#10b981',
489
- color: '#ffffff'
490
  });
491
  })
492
- .catch(function() {
 
 
 
 
 
 
 
 
493
  Toast.fire({
494
  icon: 'error',
495
- title: 'Erreur lors de la copie',
496
- background: '#ef4444',
497
- color: '#ffffff'
498
  });
499
  });
500
  });
501
 
502
- // Gestion des raccourcis clavier
503
- $(document).keydown(function(e) {
504
- // Ctrl/Cmd + Enter pour générer
505
- if ((e.ctrlKey || e.metaKey) && e.keyCode === 13) {
506
- $('#submit-btn').click();
 
507
  }
508
- // Ctrl/Cmd + C pour copier la réponse si elle existe
509
- if ((e.ctrlKey || e.metaKey) && e.keyCode === 67 && !$('#response').hasClass('hidden')) {
510
- $('#copy-btn').click();
511
  }
512
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
513
  });
514
  </script>
515
  </body>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Mariam AI - Assistant Philosophique</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
+ <script src="https://cdn.tailwindcss.com"></script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  </head>
13
+ <body class="bg-gradient-to-br from-violet-50 to-indigo-50 min-h-screen">
14
+ <!-- Navbar -->
15
+ <nav class="bg-white/80 backdrop-blur-md border-b border-gray-200 fixed w-full z-50">
16
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
17
+ <div class="flex justify-between items-center h-16">
18
+ <div class="flex items-center">
19
+ <div class="text-2xl font-bold bg-gradient-to-r from-violet-600 to-indigo-600 text-transparent bg-clip-text">
20
+ Mariam AI
21
+ </div>
22
+ </div>
23
+ <div class="flex items-center space-x-4">
24
+ <span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-violet-100 text-violet-800">
25
+ <span class="w-2 h-2 bg-violet-400 rounded-full animate-pulse mr-2"></span>
26
+ Assistant Philosophique
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  </span>
28
  </div>
29
  </div>
30
+ </div>
31
+ </nav>
32
+
33
+ <!-- Main Content -->
34
+ <div class="pt-24 pb-12 px-4 sm:px-6 lg:px-8">
35
+ <div class="max-w-4xl mx-auto">
36
+ <!-- Main Card -->
37
+ <div class="bg-white/80 backdrop-blur-md rounded-2xl shadow-xl border border-gray-100 overflow-hidden">
38
+ <!-- Header Section -->
39
+ <div class="bg-gradient-to-r from-violet-600 to-indigo-600 p-6 text-white">
40
+ <h2 class="text-2xl font-bold">Générateur de Dissertation</h2>
41
+ <p class="mt-2 opacity-90">Créez des dissertations philosophiques pertinentes et structurées</p>
42
+ </div>
43
 
44
+ <!-- Content Section -->
45
+ <div class="p-8 space-y-8">
46
+ <!-- Type Selection -->
47
+ <div class="space-y-3">
48
+ <label class="block text-sm font-medium text-gray-700">Type de dissertation</label>
49
+ <div class="relative">
50
+ <select id="type-select" class="w-full rounded-xl border-gray-200 shadow-sm focus:border-violet-500 focus:ring-violet-500 appearance-none bg-white py-3 px-4 pr-10">
51
+ <option value="1">Type 1 - Dissertation classique</option>
52
+ <option value="2">Type 2 - Analyse comparative</option>
53
+ </select>
54
+ <div class="absolute inset-y-0 right-0 flex items-center px-4 pointer-events-none">
55
+ <svg class="h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
56
+ <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
57
+ </svg>
58
+ </div>
59
+ </div>
60
+ <div id="current-type-label" class="inline-flex px-4 py-2 rounded-xl text-sm font-medium bg-gradient-to-r from-violet-50 to-indigo-50 text-violet-700 border border-violet-200">
61
+ Sujet de type 1
62
+ </div>
63
+ </div>
64
+
65
+ <!-- Course Selection -->
66
+ <div class="space-y-3">
67
+ <label class="block text-sm font-medium text-gray-700">Sélection du cours</label>
68
+ <div class="relative">
69
+ <select id="course-select" class="w-full rounded-xl border-gray-200 shadow-sm focus:border-violet-500 focus:ring-violet-500 appearance-none bg-white py-3 px-4 pr-10">
70
+ <option value="">Choisir un cours...</option>
71
+ </select>
72
+ <div class="absolute inset-y-0 right-0 flex items-center px-4 pointer-events-none">
73
+ <svg class="h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
74
+ <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
75
+ </svg>
76
+ </div>
77
+ </div>
78
+ <div class="course-meta hidden">
79
+ <div class="bg-gradient-to-r from-gray-50 to-white rounded-xl p-4 border border-gray-100">
80
+ <div class="flex justify-between items-center">
81
+ <span id="course-author" class="flex items-center space-x-2">
82
+ <svg class="h-5 w-5 text-violet-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
83
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
84
+ </svg>
85
+ <span class="text-gray-600"></span>
86
+ </span>
87
+ <span id="course-date" class="flex items-center space-x-2">
88
+ <svg class="h-5 w-5 text-violet-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
89
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
90
+ </svg>
91
+ <span class="text-gray-600"></span>
92
+ </span>
93
+ </div>
94
+ </div>
95
+ </div>
96
+ </div>
97
+
98
+ <!-- Question Input -->
99
+ <div class="space-y-3">
100
+ <label class="block text-sm font-medium text-gray-700">Sujet de dissertation</label>
101
+ <div class="relative">
102
+ <textarea id="question" rows="4"
103
+ class="w-full rounded-xl border-gray-200 shadow-sm focus:border-violet-500 focus:ring-violet-500 resize-none bg-white py-3 px-4"
104
+ placeholder="Saisissez votre sujet de dissertation..."></textarea>
105
+ <div class="absolute bottom-3 right-3 flex items-center space-x-2 text-gray-400">
106
+ <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
107
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z" />
108
+ </svg>
109
+ </div>
110
+ </div>
111
+ </div>
112
+
113
+ <!-- Submit Button -->
114
+ <button id="submit-btn" class="w-full py-4 px-6 rounded-xl bg-gradient-to-r from-violet-600 to-indigo-600 text-white font-medium shadow-lg shadow-violet-200 hover:shadow-xl hover:shadow-violet-300 transform hover:-translate-y-0.5 transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-violet-500 focus:ring-offset-2">
115
+ <span class="flex items-center justify-center space-x-2">
116
+ <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
117
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
118
+ </svg>
119
+ <span>Générer la dissertation</span>
120
+ </span>
121
+ </button>
122
+
123
+ <!-- Response Section -->
124
+ <div id="response" class="hidden mt-8 prose prose-violet max-w-none">
125
+ <div class="bg-gradient-to-r from-gray-50 to-white rounded-xl p-6 border border-gray-100">
126
+ <!-- La réponse sera insérée ici -->
127
+ </div>
128
+ </div>
129
+
130
+ <!-- Copy Button -->
131
+ <button id="copy-btn" class="hidden w-full py-3 px-6 rounded-xl bg-gray-50 text-gray-700 font-medium border border-gray-200 hover:bg-gray-100 transform hover:-translate-y-0.5 transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2">
132
+ <span class="flex items-center justify-center space-x-2">
133
+ <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
134
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
135
+ </svg>
136
+ <span>Copier la dissertation</span>
137
+ </span>
138
+ </button>
139
+ </div>
140
  </div>
 
 
141
  </div>
142
  </div>
143
 
144
  <script>
145
  $(document).ready(function() {
146
+ // Configuration de marked avec support de la syntaxe GFM
147
  marked.setOptions({
148
  breaks: true,
149
  gfm: true,
150
  headerIds: true,
151
+ langPrefix: 'language-',
152
+ smartLists: true,
153
+ smartypants: true
154
  });
155
 
156
+ // Configuration des notifications
157
  const Toast = Swal.mixin({
158
  toast: true,
159
  position: 'top-end',
 
161
  timer: 3000,
162
  timerProgressBar: true,
163
  customClass: {
164
+ popup: 'rounded-lg shadow-xl border border-gray-100'
165
  }
166
  });
167
 
168
+ // Animation des boutons
169
+ function addButtonAnimation(buttonId) {
170
+ $(`#${buttonId}`).on('mousedown', function() {
171
+ $(this).addClass('scale-95');
172
+ }).on('mouseup mouseleave', function() {
173
+ $(this).removeClass('scale-95');
174
+ });
175
+ }
176
+
177
+ addButtonAnimation('submit-btn');
178
+ addButtonAnimation('copy-btn');
179
+
180
  // Gestion du changement de type
181
  $('#type-select').change(function() {
182
  const type = $(this).val();
183
+ const labels = {
184
+ '1': 'Dissertation classique',
185
+ '2': 'Analyse comparative'
186
+ };
187
+ $('#current-type-label').text(`Type ${type} - ${labels[type]}`);
 
 
 
188
  });
189
 
190
+ // Chargement des cours avec animation
191
+ function loadCourses() {
192
+ return $.ajax({
193
+ url: '/api/philosophy/courses',
194
+ method: 'GET',
195
+ beforeSend: function() {
196
+ $('#course-select').addClass('animate-pulse');
197
+ },
198
+ complete: function() {
199
+ $('#course-select').removeClass('animate-pulse');
200
+ }
201
+ });
202
+ }
203
+
204
+ loadCourses()
205
+ .done(function(courses) {
206
  const select = $('#course-select');
207
  courses.forEach(course => {
208
  select.append(`<option value="${course.id}">${course.title}</option>`);
209
  });
210
+ })
211
+ .fail(function() {
212
  Toast.fire({
213
  icon: 'error',
214
+ title: 'Erreur de chargement des cours',
215
+ text: 'Veuillez réessayer ultérieurement'
216
  });
217
+ });
 
218
 
219
+ // Gestion du changement de cours avec animations
220
  $('#course-select').change(function() {
221
  const courseId = $(this).val();
222
  if (courseId) {
223
+ $.ajax({
224
+ url: `/api/philosophy/courses/${courseId}`,
225
  method: 'GET',
226
+ beforeSend: function() {
227
+ $('.course-meta').addClass('animate-pulse');
228
+ },
229
  success: function(course) {
230
+ $('.course-meta').removeClass('hidden animate-pulse')
231
+ .addClass('animate-fadeIn');
232
+ $('#course-author span').text(`Pr. ${course.author}`);
233
+ $('#course-date span').text(new Date(course.updated_at).toLocaleDateString('fr-FR', {
234
+ day: 'numeric',
235
+ month: 'long',
236
+ year: 'numeric' }));
 
 
 
237
  },
238
  error: function() {
239
  Toast.fire({
240
  icon: 'error',
241
+ title: 'Erreur',
242
+ text: 'Impossible de charger les détails du cours'
 
243
  });
244
  }
245
  });
246
  } else {
247
+ $('.course-meta').addClass('animate-fadeOut').on('animationend', function() {
248
+ $(this).addClass('hidden').removeClass('animate-fadeOut');
249
+ });
250
  }
251
  });
252
 
253
+ // Gestion de la soumission avec animations avancées
254
  $('#submit-btn').click(function() {
255
  const question = $('#question').val().trim();
256
+
 
257
  if (!question) {
258
+ // Animation de secousse sur le champ vide
259
+ $('#question').addClass('animate-shake border-red-300');
260
+ setTimeout(() => {
261
+ $('#question').removeClass('animate-shake border-red-300');
262
+ }, 1000);
263
+
264
  Swal.fire({
265
  icon: 'warning',
266
+ title: 'Champ requis',
267
+ text: 'Veuillez saisir votre sujet de dissertation',
268
+ showClass: {
269
+ popup: 'animate__animated animate__fadeInDown'
270
+ },
271
+ hideClass: {
272
+ popup: 'animate__animated animate__fadeOutUp'
273
+ },
274
  customClass: {
275
+ popup: 'rounded-2xl',
276
+ confirmButton: 'bg-violet-600 hover:bg-violet-700 text-white font-medium py-2 px-4 rounded-lg transition-colors duration-200'
277
  }
278
  });
279
  return;
280
  }
281
 
282
+ // Animation de chargement sophistiquée
283
  Swal.fire({
284
  title: 'Génération en cours',
285
  html: `
286
+ <div class="space-y-4">
287
+ <div class="flex justify-center">
288
+ <div class="w-16 h-16 relative">
289
+ <div class="absolute inset-0 rounded-full border-4 border-violet-200 animate-ping"></div>
290
+ <div class="absolute inset-0 rounded-full border-4 border-violet-500 animate-pulse"></div>
291
+ </div>
292
+ </div>
293
+ <div class="text-gray-600">
294
+ <p class="animate-pulse">Analyse philosophique en cours...</p>
295
+ <p class="text-sm mt-2 text-gray-500">Veuillez patienter quelques instants</p>
296
+ </div>
297
  </div>
298
  `,
299
  allowOutsideClick: false,
300
  showConfirmButton: false,
301
  customClass: {
302
+ popup: 'rounded-2xl'
303
  }
304
  });
305
 
 
306
  const data = {
307
  question: question,
308
+ type: $('#type-select').val(),
309
+ courseId: $('#course-select').val() || null
310
  };
311
 
 
 
 
 
 
 
312
  $.ajax({
313
+ url: '/submit_philo',
314
  method: 'POST',
315
  contentType: 'application/json',
316
  data: JSON.stringify(data),
317
+ success: function(data) {
318
  Swal.close();
 
 
 
 
 
 
 
 
 
 
319
 
320
+ // Conversion et animation de la réponse
321
+ const htmlContent = marked.parse(data.response);
322
+ $('#response')
323
+ .html(htmlContent)
324
+ .removeClass('hidden')
325
+ .addClass('animate-fadeIn');
326
+
327
+ // Animation du bouton de copie
328
+ $('#copy-btn')
329
+ .removeClass('hidden')
330
+ .addClass('animate-slideUp');
331
 
332
  // Scroll smooth vers la réponse
333
  $('html, body').animate({
334
  scrollTop: $('#response').offset().top - 100
335
  }, 800);
336
+
337
+ Toast.fire({
338
+ icon: 'success',
339
+ title: 'Dissertation générée avec succès',
340
+ timer: 2000
341
+ });
342
  },
343
+ error: function() {
344
  Swal.fire({
345
  icon: 'error',
346
+ title: 'Erreur de génération',
347
+ text: 'Une erreur est survenue lors de la génération de votre dissertation.',
348
+ customClass: {
349
+ popup: 'rounded-2xl',
350
+ confirmButton: 'bg-violet-600 hover:bg-violet-700 text-white font-medium py-2 px-4 rounded-lg transition-colors duration-200'
351
+ }
352
  });
353
  }
354
  });
355
  });
356
 
357
+ // Gestion de la copie avec retour visuel amélioré
358
  $('#copy-btn').click(function() {
359
  const response = $('#response').text();
360
+
361
+ // Animation du bouton pendant la copie
362
+ $(this).addClass('scale-95 bg-violet-100');
363
+
364
  navigator.clipboard.writeText(response)
365
+ .then(() => {
366
+ // Success animation
367
+ $(this).removeClass('scale-95 bg-violet-100')
368
+ .addClass('bg-green-50 text-green-700');
369
+
370
+ setTimeout(() => {
371
+ $(this).removeClass('bg-green-50 text-green-700');
372
+ }, 1000);
373
 
374
  Toast.fire({
375
  icon: 'success',
376
+ title: 'Copié avec succès',
377
+ text: 'Le contenu a été copié dans votre presse-papiers',
378
+ timer: 2000
379
  });
380
  })
381
+ .catch(() => {
382
+ // Error animation
383
+ $(this).removeClass('scale-95 bg-violet-100')
384
+ .addClass('bg-red-50 text-red-700');
385
+
386
+ setTimeout(() => {
387
+ $(this).removeClass('bg-red-50 text-red-700');
388
+ }, 1000);
389
+
390
  Toast.fire({
391
  icon: 'error',
392
+ title: 'Erreur de copie',
393
+ text: 'Impossible de copier le contenu',
394
+ timer: 3000
395
  });
396
  });
397
  });
398
 
399
+ // Ajout des styles d'animation personnalisés
400
+ const style = document.createElement('style');
401
+ style.textContent = `
402
+ @keyframes fadeIn {
403
+ from { opacity: 0; transform: translateY(10px); }
404
+ to { opacity: 1; transform: translateY(0); }
405
  }
406
+ @keyframes slideUp {
407
+ from { opacity: 0; transform: translateY(20px); }
408
+ to { opacity: 1; transform: translateY(0); }
409
  }
410
+ @keyframes shake {
411
+ 0%, 100% { transform: translateX(0); }
412
+ 25% { transform: translateX(-5px); }
413
+ 75% { transform: translateX(5px); }
414
+ }
415
+ .animate-fadeIn {
416
+ animation: fadeIn 0.5s ease-out forwards;
417
+ }
418
+ .animate-slideUp {
419
+ animation: slideUp 0.5s ease-out forwards;
420
+ }
421
+ .animate-shake {
422
+ animation: shake 0.5s ease-in-out;
423
+ }
424
+ `;
425
+ document.head.appendChild(style);
426
  });
427
  </script>
428
  </body>