Docfile commited on
Commit
4393455
·
verified ·
1 Parent(s): feed3c1

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +448 -105
templates/index.html CHANGED
@@ -24,6 +24,7 @@
24
  --gray-800: #1f2937;
25
  --success: #10b981;
26
  --error: #ef4444;
 
27
  --shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
28
  --shadow-lg: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
29
  }
@@ -237,7 +238,8 @@
237
  margin-top: 24px;
238
  }
239
 
240
- .flashcard, .quiz-question {
 
241
  background: var(--white);
242
  border-radius: 20px;
243
  padding: 24px;
@@ -245,26 +247,83 @@
245
  box-shadow: var(--shadow);
246
  border-left: 4px solid var(--primary-blue);
247
  transition: transform 0.3s ease;
 
 
 
248
  }
249
 
250
- .flashcard:hover, .quiz-question:hover {
251
  transform: translateX(4px);
252
  }
253
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
  .flashcard h3 {
255
  color: var(--primary-blue);
256
- margin-bottom: 12px;
257
  font-size: 1.1rem;
258
  font-weight: 600;
 
259
  }
260
 
261
- .flashcard .answer {
262
- color: var(--gray-600);
263
- padding: 16px;
264
- background: var(--gray-50);
265
- border-radius: 12px;
266
- margin-top: 12px;
267
- border: 1px solid var(--gray-100);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
  }
269
 
270
  .quiz-options {
@@ -279,6 +338,7 @@
279
  cursor: pointer;
280
  transition: all 0.3s ease;
281
  background: var(--white);
 
282
  }
283
 
284
  .quiz-option:hover {
@@ -286,44 +346,88 @@
286
  background: var(--extra-light-blue);
287
  }
288
 
289
- .quiz-option.correct {
 
 
 
 
 
290
  border-color: var(--success);
291
  background: #f0fdf4;
292
  }
293
 
294
- .quiz-option.incorrect {
295
  border-color: var(--error);
296
  background: #fef2f2;
297
  }
298
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
299
  .quiz-explanation {
300
  margin-top: 16px;
301
  padding: 16px;
302
  background: var(--extra-light-blue);
303
  border-radius: 12px;
304
  border-left: 4px solid var(--primary-blue);
 
305
  }
306
 
307
- .error-message {
308
- background: #fef2f2;
309
- color: var(--error);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
310
  padding: 16px 20px;
311
  border-radius: 12px;
312
- border: 1px solid #fecaca;
313
- margin-top: 16px;
 
 
 
 
 
 
 
314
  text-align: center;
315
  font-weight: 500;
316
  }
317
 
 
 
 
 
 
 
318
  .success-message {
319
  background: #f0fdf4;
320
  color: var(--success);
321
- padding: 16px 20px;
322
- border-radius: 12px;
323
  border: 1px solid #bbf7d0;
324
- margin-top: 16px;
325
- text-align: center;
326
- font-weight: 500;
327
  }
328
 
329
  .floating-elements {
@@ -372,7 +476,6 @@
372
  50% { transform: translateY(-20px) rotate(180deg); }
373
  }
374
 
375
- /* Animations d'entrée */
376
  .fade-in {
377
  animation: fadeIn 0.5s ease-out;
378
  }
@@ -388,7 +491,6 @@
388
  }
389
  }
390
 
391
- /* Responsive optimizations */
392
  @media (min-width: 640px) {
393
  .container {
394
  max-width: 640px;
@@ -405,7 +507,6 @@
405
  }
406
  }
407
 
408
- /* Accessibilité et focus states améliorés */
409
  @media (prefers-reduced-motion: reduce) {
410
  *, *::before, *::after {
411
  animation-duration: 0.01ms !important;
@@ -416,7 +517,6 @@
416
  </style>
417
  </head>
418
  <body>
419
- <!-- Éléments flottants décoratifs -->
420
  <div class="floating-elements">
421
  <div class="floating-circle"></div>
422
  <div class="floating-circle"></div>
@@ -479,15 +579,79 @@
479
  </div>
480
 
481
  <script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
482
  document.addEventListener('DOMContentLoaded', function() {
483
  const form = document.getElementById('generateForm');
484
  const generateBtn = document.getElementById('generateBtn');
485
  const resultsContainer = document.getElementById('results');
486
 
487
- form.addEventListener('submit', async function(e) {
488
  e.preventDefault();
489
 
490
- const topic = document.getElementById('topic').value.trim();
491
  const type = document.querySelector('input[name="type"]:checked').value;
492
 
493
  if (!topic) {
@@ -495,89 +659,199 @@
495
  return;
496
  }
497
 
498
- // Animation du bouton
499
  generateBtn.classList.add('loading');
500
  generateBtn.disabled = true;
501
  resultsContainer.innerHTML = '';
502
 
503
- try {
504
- const response = await fetch('/generate', {
505
- method: 'POST',
506
- headers: {
507
- 'Content-Type': 'application/json',
508
- },
509
- body: JSON.stringify({ topic, type })
510
- });
511
-
512
- const data = await response.json();
513
-
514
- if (data.success) {
515
- displayResults(data[type], type);
516
  showMessage(`${type === 'flashcards' ? 'Flashcards' : 'Quiz'} généré avec succès !`, 'success');
517
  } else {
518
- showMessage(data.error || 'Une erreur est survenue lors de la génération.', 'error');
519
  }
520
- } catch (error) {
521
- console.error('Erreur:', error);
522
- showMessage('Erreur de connexion. Veuillez réessayer.', 'error');
523
- } finally {
524
- // Restaurer le bouton
525
  generateBtn.classList.remove('loading');
526
  generateBtn.disabled = false;
527
- }
528
  });
529
 
530
- function displayResults(data, type) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
531
  resultsContainer.innerHTML = '';
 
532
 
533
  if (type === 'flashcards') {
534
- data.forEach((item, index) => {
535
- const flashcardEl = document.createElement('div');
536
- flashcardEl.className = 'flashcard fade-in';
537
- flashcardEl.style.animationDelay = `${index * 0.1}s`;
538
- flashcardEl.innerHTML = `
 
 
 
 
 
 
 
 
 
 
 
539
  <h3><i class="fas fa-question"></i> ${item.question}</h3>
540
- <div class="answer">
541
- <i class="fas fa-lightbulb"></i> ${item.answer}
 
 
 
542
  </div>
543
- `;
544
- resultsContainer.appendChild(flashcardEl);
 
 
 
545
  });
546
- } else {
547
- data.forEach((item, index) => {
548
- const quizEl = document.createElement('div');
549
- quizEl.className = 'quiz-question fade-in';
550
- quizEl.style.animationDelay = `${index * 0.1}s`;
551
-
552
- const optionsHtml = item.options.map(option => `
553
- <div class="quiz-option ${option === item.correctAnswer ? 'correct' : ''}"
554
- onclick="toggleExplanation(this)">
555
- <i class="fas ${option === item.correctAnswer ? 'fa-check' : 'fa-times'}"></i> ${option}
556
- </div>
557
- `).join('');
558
-
559
- quizEl.innerHTML = `
560
- <h3><i class="fas fa-question-circle"></i> ${item.question}</h3>
561
- <div class="quiz-options">${optionsHtml}</div>
562
- <div class="quiz-explanation" style="display: none;">
563
- <i class="fas fa-info-circle"></i> <strong>Explication :</strong> ${item.explanation}
564
- </div>
565
- `;
566
- resultsContainer.appendChild(quizEl);
 
 
 
 
 
 
 
 
 
 
 
 
567
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
568
  }
569
  }
570
 
571
  function showMessage(message, type) {
572
  const messageEl = document.createElement('div');
573
- messageEl.className = `${type}-message fade-in`;
574
  messageEl.innerHTML = `
575
  <i class="fas ${type === 'success' ? 'fa-check-circle' : 'fa-exclamation-circle'}"></i>
576
  ${message}
577
  `;
578
 
579
  // Supprimer les anciens messages
580
- const oldMessages = document.querySelectorAll('.error-message, .success-message');
581
  oldMessages.forEach(msg => msg.remove());
582
 
583
  resultsContainer.insertBefore(messageEl, resultsContainer.firstChild);
@@ -588,24 +862,6 @@
588
  }, 5000);
589
  }
590
 
591
- // Fonction globale pour l'interaction avec les quiz
592
- window.toggleExplanation = function(optionEl) {
593
- const quizQuestion = optionEl.closest('.quiz-question');
594
- const explanation = quizQuestion.querySelector('.quiz-explanation');
595
-
596
- // Marquer toutes les options comme incorrectes visuellement
597
- const options = quizQuestion.querySelectorAll('.quiz-option');
598
- options.forEach(opt => {
599
- if (!opt.classList.contains('correct')) {
600
- opt.classList.add('incorrect');
601
- }
602
- });
603
-
604
- // Afficher l'explication
605
- explanation.style.display = 'block';
606
- explanation.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
607
- };
608
-
609
  // Animation au focus des inputs
610
  const inputs = document.querySelectorAll('input[type="text"]');
611
  inputs.forEach(input => {
@@ -618,7 +874,7 @@
618
  });
619
  });
620
 
621
- // Animation des cartes au scroll (pour les écrans plus grands)
622
  const observerOptions = {
623
  threshold: 0.1,
624
  rootMargin: '0px 0px -50px 0px'
@@ -631,7 +887,94 @@
631
  }
632
  });
633
  }, observerOptions);
634
- });
635
- </script>
636
- </body>
637
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  --gray-800: #1f2937;
25
  --success: #10b981;
26
  --error: #ef4444;
27
+ --warning: #f59e0b;
28
  --shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
29
  --shadow-lg: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
30
  }
 
238
  margin-top: 24px;
239
  }
240
 
241
+ /* Flashcards */
242
+ .flashcard {
243
  background: var(--white);
244
  border-radius: 20px;
245
  padding: 24px;
 
247
  box-shadow: var(--shadow);
248
  border-left: 4px solid var(--primary-blue);
249
  transition: transform 0.3s ease;
250
+ cursor: pointer;
251
+ position: relative;
252
+ min-height: 120px;
253
  }
254
 
255
+ .flashcard:hover {
256
  transform: translateX(4px);
257
  }
258
 
259
+ .flashcard.flipped .card-front {
260
+ opacity: 0;
261
+ transform: rotateY(90deg);
262
+ }
263
+
264
+ .flashcard.flipped .card-back {
265
+ opacity: 1;
266
+ transform: rotateY(0deg);
267
+ }
268
+
269
+ .card-front, .card-back {
270
+ position: absolute;
271
+ top: 0;
272
+ left: 0;
273
+ right: 0;
274
+ bottom: 0;
275
+ padding: 24px;
276
+ transition: all 0.6s ease;
277
+ backface-visibility: hidden;
278
+ display: flex;
279
+ align-items: center;
280
+ justify-content: center;
281
+ text-align: center;
282
+ }
283
+
284
+ .card-back {
285
+ opacity: 0;
286
+ transform: rotateY(-90deg);
287
+ background: var(--gray-50);
288
+ border-radius: 20px;
289
+ color: var(--gray-600);
290
+ }
291
+
292
  .flashcard h3 {
293
  color: var(--primary-blue);
 
294
  font-size: 1.1rem;
295
  font-weight: 600;
296
+ margin: 0;
297
  }
298
 
299
+ .flip-indicator {
300
+ position: absolute;
301
+ top: 10px;
302
+ right: 15px;
303
+ color: var(--gray-400);
304
+ font-size: 0.8rem;
305
+ }
306
+
307
+ /* Quiz Questions */
308
+ .quiz-question {
309
+ background: var(--white);
310
+ border-radius: 20px;
311
+ padding: 24px;
312
+ margin-bottom: 16px;
313
+ box-shadow: var(--shadow);
314
+ border-left: 4px solid var(--primary-blue);
315
+ transition: transform 0.3s ease;
316
+ }
317
+
318
+ .quiz-question:hover {
319
+ transform: translateX(4px);
320
+ }
321
+
322
+ .quiz-question h3 {
323
+ color: var(--primary-blue);
324
+ margin-bottom: 16px;
325
+ font-size: 1.1rem;
326
+ font-weight: 600;
327
  }
328
 
329
  .quiz-options {
 
338
  cursor: pointer;
339
  transition: all 0.3s ease;
340
  background: var(--white);
341
+ position: relative;
342
  }
343
 
344
  .quiz-option:hover {
 
346
  background: var(--extra-light-blue);
347
  }
348
 
349
+ .quiz-option.selected {
350
+ border-color: var(--primary-blue);
351
+ background: var(--extra-light-blue);
352
+ }
353
+
354
+ .quiz-option.correct-answer {
355
  border-color: var(--success);
356
  background: #f0fdf4;
357
  }
358
 
359
+ .quiz-option.incorrect-answer {
360
  border-color: var(--error);
361
  background: #fef2f2;
362
  }
363
 
364
+ .quiz-option .option-icon {
365
+ position: absolute;
366
+ right: 16px;
367
+ top: 50%;
368
+ transform: translateY(-50%);
369
+ opacity: 0;
370
+ transition: opacity 0.3s ease;
371
+ }
372
+
373
+ .quiz-option.correct-answer .option-icon,
374
+ .quiz-option.incorrect-answer .option-icon {
375
+ opacity: 1;
376
+ }
377
+
378
  .quiz-explanation {
379
  margin-top: 16px;
380
  padding: 16px;
381
  background: var(--extra-light-blue);
382
  border-radius: 12px;
383
  border-left: 4px solid var(--primary-blue);
384
+ display: none;
385
  }
386
 
387
+ .quiz-explanation.show {
388
+ display: block;
389
+ animation: slideDown 0.3s ease;
390
+ }
391
+
392
+ @keyframes slideDown {
393
+ from {
394
+ opacity: 0;
395
+ transform: translateY(-10px);
396
+ }
397
+ to {
398
+ opacity: 1;
399
+ transform: translateY(0);
400
+ }
401
+ }
402
+
403
+ .quiz-score {
404
+ background: linear-gradient(135deg, var(--primary-blue), var(--light-blue));
405
+ color: var(--white);
406
  padding: 16px 20px;
407
  border-radius: 12px;
408
+ text-align: center;
409
+ font-weight: 600;
410
+ margin-bottom: 16px;
411
+ }
412
+
413
+ .message {
414
+ padding: 16px 20px;
415
+ border-radius: 12px;
416
+ margin-bottom: 16px;
417
  text-align: center;
418
  font-weight: 500;
419
  }
420
 
421
+ .error-message {
422
+ background: #fef2f2;
423
+ color: var(--error);
424
+ border: 1px solid #fecaca;
425
+ }
426
+
427
  .success-message {
428
  background: #f0fdf4;
429
  color: var(--success);
 
 
430
  border: 1px solid #bbf7d0;
 
 
 
431
  }
432
 
433
  .floating-elements {
 
476
  50% { transform: translateY(-20px) rotate(180deg); }
477
  }
478
 
 
479
  .fade-in {
480
  animation: fadeIn 0.5s ease-out;
481
  }
 
491
  }
492
  }
493
 
 
494
  @media (min-width: 640px) {
495
  .container {
496
  max-width: 640px;
 
507
  }
508
  }
509
 
 
510
  @media (prefers-reduced-motion: reduce) {
511
  *, *::before, *::after {
512
  animation-duration: 0.01ms !important;
 
517
  </style>
518
  </head>
519
  <body>
 
520
  <div class="floating-elements">
521
  <div class="floating-circle"></div>
522
  <div class="floating-circle"></div>
 
579
  </div>
580
 
581
  <script>
582
+ // Données de démonstration
583
+ const DEMO_DATA = {
584
+ flashcards: {
585
+ "histoire": [
586
+ { question: "Quand a eu lieu la Révolution française ?", answer: "La Révolution française a eu lieu de 1789 à 1799." },
587
+ { question: "Qui était le roi de France au début de la Révolution ?", answer: "Louis XVI était le roi de France au début de la Révolution française." },
588
+ { question: "Qu'est-ce que la Déclaration des droits de l'homme et du citoyen ?", answer: "Document fondamental adopté en 1789, proclamant les droits naturels et inaliénables de l'homme." },
589
+ { question: "Que s'est-il passé le 14 juillet 1789 ?", answer: "Prise de la Bastille par le peuple parisien, symbole du début de la Révolution." },
590
+ { question: "Qu'est-ce que la Terreur ?", answer: "Période de la Révolution française (1793-1794) marquée par la répression violente des opposants." }
591
+ ],
592
+ "python": [
593
+ { question: "Comment déclarer une liste en Python ?", answer: "ma_liste = [] ou ma_liste = [1, 2, 3]" },
594
+ { question: "Quelle est la différence entre une liste et un tuple ?", answer: "Les listes sont mutables (modifiables) alors que les tuples sont immutables." },
595
+ { question: "Comment créer une fonction en Python ?", answer: "def ma_fonction(): suivi du code indenté" },
596
+ { question: "Qu'est-ce qu'une boucle for ?", answer: "Structure qui permet de répéter des instructions pour chaque élément d'une séquence." },
597
+ { question: "Comment gérer les exceptions ?", answer: "Avec try/except : try: code_risque except Exception: gestion_erreur" }
598
+ ]
599
+ },
600
+ quiz: {
601
+ "histoire": [
602
+ {
603
+ question: "En quelle année a commencé la Révolution française ?",
604
+ options: ["1789", "1799", "1792", "1794"],
605
+ correctAnswer: "1789",
606
+ explanation: "La Révolution française a commencé en 1789 avec la convocation des États généraux et la prise de la Bastille."
607
+ },
608
+ {
609
+ question: "Qui était surnommé 'l'Incorruptible' ?",
610
+ options: ["Danton", "Robespierre", "Marat", "Saint-Just"],
611
+ correctAnswer: "Robespierre",
612
+ explanation: "Maximilien de Robespierre était surnommé 'l'Incorruptible' pour son intégrité morale supposée."
613
+ },
614
+ {
615
+ question: "Quel événement marque la fin de la Révolution française ?",
616
+ options: ["Coup d'État du 18 Brumaire", "Mort de Robespierre", "Concordat", "Bataille de Waterloo"],
617
+ correctAnswer: "Coup d'État du 18 Brumaire",
618
+ explanation: "Le coup d'État du 18 Brumaire (1799) par Napoléon Bonaparte marque traditionnellement la fin de la Révolution française."
619
+ }
620
+ ],
621
+ "python": [
622
+ {
623
+ question: "Quel est le type de données de '123' en Python ?",
624
+ options: ["int", "float", "str", "bool"],
625
+ correctAnswer: "str",
626
+ explanation: "Les guillemets indiquent que '123' est une chaîne de caractères (string), pas un nombre."
627
+ },
628
+ {
629
+ question: "Comment obtenir la longueur d'une liste ?",
630
+ options: ["list.length()", "len(list)", "size(list)", "length(list)"],
631
+ correctAnswer: "len(list)",
632
+ explanation: "La fonction len() retourne le nombre d'éléments dans une séquence."
633
+ },
634
+ {
635
+ question: "Que fait l'opérateur % en Python ?",
636
+ options: ["Division", "Modulo", "Pourcentage", "Multiplication"],
637
+ correctAnswer: "Modulo",
638
+ explanation: "L'opérateur % retourne le reste de la division euclidienne."
639
+ }
640
+ ]
641
+ }
642
+ };
643
+
644
+ let currentQuizAnswers = {};
645
+
646
  document.addEventListener('DOMContentLoaded', function() {
647
  const form = document.getElementById('generateForm');
648
  const generateBtn = document.getElementById('generateBtn');
649
  const resultsContainer = document.getElementById('results');
650
 
651
+ form.addEventListener('submit', function(e) {
652
  e.preventDefault();
653
 
654
+ const topic = document.getElementById('topic').value.trim().toLowerCase();
655
  const type = document.querySelector('input[name="type"]:checked').value;
656
 
657
  if (!topic) {
 
659
  return;
660
  }
661
 
 
662
  generateBtn.classList.add('loading');
663
  generateBtn.disabled = true;
664
  resultsContainer.innerHTML = '';
665
 
666
+ // Simulation d'un délai de génération
667
+ setTimeout(() => {
668
+ const data = window.generateContent(topic, type);
669
+ if (data) {
670
+ displayResults(data, type, topic);
 
 
 
 
 
 
 
 
671
  showMessage(`${type === 'flashcards' ? 'Flashcards' : 'Quiz'} généré avec succès !`, 'success');
672
  } else {
673
+ showMessage('Sujet non reconnu. Essayez "histoire", "python", "mathématiques" ou "sciences" pour une démonstration.', 'error');
674
  }
675
+
 
 
 
 
676
  generateBtn.classList.remove('loading');
677
  generateBtn.disabled = false;
678
+ }, 1500);
679
  });
680
 
681
+ function generateContent(topic, type) {
682
+ // Recherche par mots-clés
683
+ const keywords = {
684
+ 'histoire': ['histoire', 'révolution', 'française', 'france', 'roi', 'louis'],
685
+ 'python': ['python', 'programmation', 'code', 'langage', 'développement']
686
+ };
687
+
688
+ for (const [key, words] of Object.entries(keywords)) {
689
+ if (words.some(word => topic.includes(word))) {
690
+ return DEMO_DATA[type][key];
691
+ }
692
+ }
693
+
694
+ return null;
695
+ }
696
+
697
+ function displayResults(data, type, topic) {
698
  resultsContainer.innerHTML = '';
699
+ currentQuizAnswers = {};
700
 
701
  if (type === 'flashcards') {
702
+ displayFlashcards(data);
703
+ } else {
704
+ displayQuiz(data);
705
+ }
706
+ }
707
+
708
+ function displayFlashcards(flashcards) {
709
+ flashcards.forEach((item, index) => {
710
+ const flashcardEl = document.createElement('div');
711
+ flashcardEl.className = 'flashcard fade-in';
712
+ flashcardEl.style.animationDelay = `${index * 0.1}s`;
713
+ flashcardEl.innerHTML = `
714
+ <div class="flip-indicator">
715
+ <i class="fas fa-redo"></i> Cliquez pour retourner
716
+ </div>
717
+ <div class="card-front">
718
  <h3><i class="fas fa-question"></i> ${item.question}</h3>
719
+ </div>
720
+ <div class="card-back">
721
+ <div>
722
+ <i class="fas fa-lightbulb"></i>
723
+ <p style="margin-top: 10px;">${item.answer}</p>
724
  </div>
725
+ </div>
726
+ `;
727
+
728
+ flashcardEl.addEventListener('click', function() {
729
+ this.classList.toggle('flipped');
730
  });
731
+
732
+ resultsContainer.appendChild(flashcardEl);
733
+ });
734
+ }
735
+
736
+ function displayQuiz(questions) {
737
+ questions.forEach((item, questionIndex) => {
738
+ const quizEl = document.createElement('div');
739
+ quizEl.className = 'quiz-question fade-in';
740
+ quizEl.style.animationDelay = `${questionIndex * 0.1}s`;
741
+
742
+ const optionsHtml = item.options.map((option, optionIndex) => `
743
+ <div class="quiz-option" data-question="${questionIndex}" data-option="${option}">
744
+ ${option}
745
+ <i class="fas fa-check option-icon" style="color: var(--success);"></i>
746
+ <i class="fas fa-times option-icon" style="color: var(--error);"></i>
747
+ </div>
748
+ `).join('');
749
+
750
+ quizEl.innerHTML = `
751
+ <h3><i class="fas fa-question-circle"></i> ${item.question}</h3>
752
+ <div class="quiz-options">${optionsHtml}</div>
753
+ <div class="quiz-explanation">
754
+ <i class="fas fa-info-circle"></i> <strong>Explication :</strong> ${item.explanation}
755
+ </div>
756
+ `;
757
+
758
+ // Ajouter les événements aux options
759
+ const options = quizEl.querySelectorAll('.quiz-option');
760
+ options.forEach(option => {
761
+ option.addEventListener('click', function() {
762
+ handleQuizAnswer(this, item, questionIndex);
763
+ });
764
  });
765
+
766
+ resultsContainer.appendChild(quizEl);
767
+ });
768
+
769
+ // Ajouter le score à la fin
770
+ setTimeout(() => {
771
+ addQuizScore(questions.length);
772
+ }, questions.length * 100 + 500);
773
+ }
774
+
775
+ function handleQuizAnswer(selectedOption, question, questionIndex) {
776
+ const allOptions = selectedOption.parentNode.querySelectorAll('.quiz-option');
777
+ const explanation = selectedOption.closest('.quiz-question').querySelector('.quiz-explanation');
778
+
779
+ // Empêcher de répondre plusieurs fois à la même question
780
+ if (currentQuizAnswers[questionIndex]) {
781
+ return;
782
+ }
783
+
784
+ currentQuizAnswers[questionIndex] = {
785
+ selected: selectedOption.dataset.option,
786
+ correct: question.correctAnswer,
787
+ isCorrect: selectedOption.dataset.option === question.correctAnswer
788
+ };
789
+
790
+ // Marquer la réponse sélectionnée
791
+ selectedOption.classList.add('selected');
792
+
793
+ // Révéler les bonnes et mauvaises réponses
794
+ allOptions.forEach(option => {
795
+ const isCorrect = option.dataset.option === question.correctAnswer;
796
+ const isSelected = option === selectedOption;
797
+
798
+ if (isCorrect) {
799
+ option.classList.add('correct-answer');
800
+ } else if (isSelected) {
801
+ option.classList.add('incorrect-answer');
802
+ }
803
+
804
+ // Désactiver toutes les options
805
+ option.style.pointerEvents = 'none';
806
+ });
807
+
808
+ // Afficher l'explication
809
+ explanation.classList.add('show');
810
+
811
+ updateQuizScore();
812
+ }
813
+
814
+ function addQuizScore(totalQuestions) {
815
+ const scoreEl = document.createElement('div');
816
+ scoreEl.className = 'quiz-score fade-in';
817
+ scoreEl.innerHTML = `
818
+ <h3><i class="fas fa-chart-bar"></i> Score Final</h3>
819
+ <div id="score-display">Répondez aux questions pour voir votre score</div>
820
+ `;
821
+ resultsContainer.insertBefore(scoreEl, resultsContainer.firstChild);
822
+ updateQuizScore();
823
+ }
824
+
825
+ function updateQuizScore() {
826
+ const scoreDisplay = document.getElementById('score-display');
827
+ if (!scoreDisplay) return;
828
+
829
+ const totalAnswered = Object.keys(currentQuizAnswers).length;
830
+ const correctAnswers = Object.values(currentQuizAnswers).filter(answer => answer.isCorrect).length;
831
+ const totalQuestions = Object.keys(currentQuizAnswers).length > 0 ?
832
+ Math.max(...Object.keys(currentQuizAnswers).map(Number)) + 1 : 0;
833
+
834
+ if (totalAnswered === 0) {
835
+ scoreDisplay.innerHTML = 'Répondez aux questions pour voir votre score';
836
+ } else {
837
+ const percentage = Math.round((correctAnswers / totalAnswered) * 100);
838
+ scoreDisplay.innerHTML = `
839
+ ${correctAnswers}/${totalAnswered} bonnes réponses (${percentage}%)
840
+ ${totalAnswered < totalQuestions ? '<br><small>Continuez à répondre...</small>' : ''}
841
+ `;
842
  }
843
  }
844
 
845
  function showMessage(message, type) {
846
  const messageEl = document.createElement('div');
847
+ messageEl.className = `message ${type}-message fade-in`;
848
  messageEl.innerHTML = `
849
  <i class="fas ${type === 'success' ? 'fa-check-circle' : 'fa-exclamation-circle'}"></i>
850
  ${message}
851
  `;
852
 
853
  // Supprimer les anciens messages
854
+ const oldMessages = document.querySelectorAll('.message');
855
  oldMessages.forEach(msg => msg.remove());
856
 
857
  resultsContainer.insertBefore(messageEl, resultsContainer.firstChild);
 
862
  }, 5000);
863
  }
864
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
865
  // Animation au focus des inputs
866
  const inputs = document.querySelectorAll('input[type="text"]');
867
  inputs.forEach(input => {
 
874
  });
875
  });
876
 
877
+ // Animation des cartes au scroll
878
  const observerOptions = {
879
  threshold: 0.1,
880
  rootMargin: '0px 0px -50px 0px'
 
887
  }
888
  });
889
  }, observerOptions);
890
+
891
+ // Ajouter des sujets supplémentaires pour la démonstration
892
+ const additionalTopics = {
893
+ flashcards: {
894
+ "mathématiques": [
895
+ { question: "Qu'est-ce qu'une fonction linéaire ?", answer: "Une fonction de la forme f(x) = ax + b où a et b sont des constantes." },
896
+ { question: "Comment calcule-t-on l'aire d'un cercle ?", answer: "Aire = π × r² où r est le rayon du cercle." },
897
+ { question: "Qu'est-ce que le théorème de Pythagore ?", answer: "Dans un triangle rectangle : a² + b² = c² où c est l'hypoténuse." },
898
+ { question: "Combien vaut π (pi) approximativement ?", answer: "π ≈ 3,14159..." },
899
+ { question: "Qu'est-ce qu'un nombre premier ?", answer: "Un nombre entier supérieur à 1 qui n'a que deux diviseurs : 1 et lui-même." }
900
+ ],
901
+ "sciences": [
902
+ { question: "Quelle est la vitesse de la lumière ?", answer: "La vitesse de la lumière est d'environ 300 000 km/s dans le vide." },
903
+ { question: "Qu'est-ce que la photosynthèse ?", answer: "Processus par lequel les plantes convertissent la lumière solaire en énergie chimique." },
904
+ { question: "Combien y a-t-il d'éléments dans le tableau périodique ?", answer: "Il y a 118 éléments chimiques connus dans le tableau périodique." },
905
+ { question: "Qu'est-ce que l'ADN ?", answer: "L'acide désoxyribonucléique, molécule qui contient l'information génétique." },
906
+ { question: "Quelle est la température d'ébullition de l'eau ?", answer: "L'eau bout à 100°C (373 K) sous pression atmosphérique normale." }
907
+ ]
908
+ },
909
+ quiz: {
910
+ "mathématiques": [
911
+ {
912
+ question: "Combien font 2³ (2 puissance 3) ?",
913
+ options: ["6", "8", "9", "12"],
914
+ correctAnswer: "8",
915
+ explanation: "2³ = 2 × 2 × 2 = 8"
916
+ },
917
+ {
918
+ question: "Dans un triangle, la somme des angles fait :",
919
+ options: ["90°", "180°", "270°", "360°"],
920
+ correctAnswer: "180°",
921
+ explanation: "La somme des angles intérieurs d'un triangle fait toujours 180°."
922
+ },
923
+ {
924
+ question: "Qu'est-ce que √16 ?",
925
+ options: ["2", "4", "6", "8"],
926
+ correctAnswer: "4",
927
+ explanation: "√16 = 4 car 4 × 4 = 16"
928
+ }
929
+ ],
930
+ "sciences": [
931
+ {
932
+ question: "Quel gaz représente environ 78% de l'atmosphère terrestre ?",
933
+ options: ["Oxygène", "Azote", "Argon", "Dioxyde de carbone"],
934
+ correctAnswer: "Azote",
935
+ explanation: "L'azote (N₂) compose environ 78% de l'atmosphère terrestre."
936
+ },
937
+ {
938
+ question: "Combien de chromosomes possède l'être humain ?",
939
+ options: ["44", "46", "48", "50"],
940
+ correctAnswer: "46",
941
+ explanation: "L'être humain possède 46 chromosomes (23 paires)."
942
+ },
943
+ {
944
+ question: "Quelle planète est la plus proche du Soleil ?",
945
+ options: ["Vénus", "Terre", "Mercure", "Mars"],
946
+ correctAnswer: "Mercure",
947
+ explanation: "Mercure est la planète la plus proche du Soleil dans notre système solaire."
948
+ }
949
+ ]
950
+ }
951
+ };
952
+
953
+ // Fusionner avec les données existantes
954
+ Object.keys(additionalTopics.flashcards).forEach(topic => {
955
+ DEMO_DATA.flashcards[topic] = additionalTopics.flashcards[topic];
956
+ });
957
+ Object.keys(additionalTopics.quiz).forEach(topic => {
958
+ DEMO_DATA.quiz[topic] = additionalTopics.quiz[topic];
959
+ });
960
+
961
+ // Mise à jour de la fonction generateContent pour inclure plus de sujets
962
+ function generateContentUpdated(topic, type) {
963
+ const keywords = {
964
+ 'histoire': ['histoire', 'révolution', 'française', 'france', 'roi', 'louis', 'historique'],
965
+ 'python': ['python', 'programmation', 'code', 'langage', 'développement', 'informatique'],
966
+ 'mathématiques': ['math', 'mathématiques', 'calcul', 'géométrie', 'algèbre', 'nombre'],
967
+ 'sciences': ['science', 'physique', 'chimie', 'biologie', 'nature', 'expérience']
968
+ };
969
+
970
+ for (const [key, words] of Object.entries(keywords)) {
971
+ if (words.some(word => topic.includes(word))) {
972
+ return DEMO_DATA[type][key];
973
+ }
974
+ }
975
+
976
+ return null;
977
+ }
978
+
979
+ // Remplacer la fonction generateContent originale
980
+ window.generateContent = generateContentUpdated;