Docfile commited on
Commit
4acd37f
·
verified ·
1 Parent(s): 5331cbc

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +914 -250
templates/index.html CHANGED
@@ -1,270 +1,934 @@
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>Générateur de Flashcards & Quiz</title>
7
- <!-- Inclusion de Tailwind CSS -->
8
- <script src="https://cdn.tailwindcss.com"></script>
9
- <!-- Inclusion de Google Fonts -->
10
- <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet" />
11
- <style>
12
- body {
13
- font-family: 'Roboto', sans-serif;
14
- }
15
- /* Animation de survol pour les cartes et options */
16
- .hover-transform {
17
- transition: transform 0.3s ease, box-shadow 0.3s ease;
18
- }
19
- .hover-transform:hover {
20
- transform: translateY(-4px);
21
- box-shadow: 0 8px 16px rgba(0,0,0,0.1);
22
- }
23
- /* Animation de chargement personnalisée */
24
- .spinner {
25
- border: 4px solid rgba(0, 0, 0, 0.1);
26
- width: 3rem;
27
- height: 3rem;
28
- border-radius: 50%;
29
- border-left-color: #4f46e5;
30
- animation: spin 1s linear infinite;
31
- }
32
- @keyframes spin {
33
- to { transform: rotate(360deg); }
34
- }
35
- </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  </head>
37
- <body class="bg-gray-50">
38
- <!-- En-tête -->
39
- <header class="bg-gradient-to-r from-indigo-600 to-blue-500 py-6 shadow-lg">
40
- <h1 class="text-center text-white text-4xl font-bold">Générateur de Flashcards & Quiz</h1>
41
- </header>
42
-
43
- <main class="container mx-auto px-4 py-8">
44
- <!-- Section de configuration -->
45
- <section class="max-w-2xl mx-auto mb-10">
46
- <div class="bg-white rounded-xl shadow-lg p-8">
47
- <div class="mb-6">
48
- <label for="topic" class="block text-gray-700 text-lg font-medium mb-2">Sujet</label>
49
- <input type="text" id="topic" placeholder="Entrez un sujet..."
50
- class="w-full border border-gray-300 rounded-md p-3 focus:outline-none focus:ring-2 focus:ring-indigo-500" />
51
- </div>
52
- <div class="mb-6">
53
- <span class="block text-gray-700 text-lg font-medium mb-2">Type de contenu</span>
54
- <div class="flex space-x-6">
55
- <label class="flex items-center space-x-2">
56
- <input type="radio" name="contentType" value="flashcards" checked
57
- class="form-radio h-5 w-5 text-indigo-600" />
58
- <span class="text-gray-800">Flashcards</span>
59
- </label>
60
- <label class="flex items-center space-x-2">
61
- <input type="radio" name="contentType" value="quiz"
62
- class="form-radio h-5 w-5 text-indigo-600" />
63
- <span class="text-gray-800">Quiz</span>
64
- </label>
65
- </div>
66
- </div>
67
- <button id="generateBtn" class="w-full bg-indigo-600 text-white font-semibold py-3 rounded-md shadow hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 transition">
68
- Générer
69
- </button>
70
- </div>
71
- </section>
72
-
73
- <!-- Indicateur de chargement -->
74
- <section id="loading" class="hidden flex flex-col items-center justify-center my-10">
75
- <div class="spinner mb-4"></div>
76
- <p class="text-gray-600 text-lg">Génération en cours... Patientez quelques instants.</p>
77
- </section>
78
-
79
- <!-- Flashcards -->
80
- <section id="flashcardsContainer" class="mt-8 hidden">
81
- <div class="mb-6 text-center">
82
- <h2 class="text-3xl font-semibold text-gray-800">Flashcards générées</h2>
83
- <p class="text-gray-500">Cliquez sur une carte pour révéler la réponse</p>
84
- </div>
85
- <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6"></div>
86
- </section>
87
-
88
- <!-- Quiz -->
89
- <section id="quizContainer" class="mt-8 max-w-3xl mx-auto hidden">
90
- <div class="mb-6 text-center">
91
- <h2 class="text-3xl font-semibold text-gray-800">Quiz généré</h2>
92
- <p class="text-gray-500">Sélectionnez une réponse pour chaque question</p>
93
- </div>
94
- </section>
95
- </main>
96
-
97
- <footer class="bg-gray-100 py-4">
98
- <p class="text-center text-gray-500 text-sm">© 2025 Générateur de Flashcards & Quiz. Tous droits réservés.</p>
99
- </footer>
100
-
101
- <script>
102
- const generateBtn = document.getElementById('generateBtn');
103
- const loadingIndicator = document.getElementById('loading');
104
- const flashcardsContainer = document.getElementById('flashcardsContainer');
105
- const quizContainer = document.getElementById('quizContainer');
106
- const topicInput = document.getElementById('topic');
107
-
108
- generateBtn.addEventListener('click', () => {
109
- const topic = topicInput.value.trim();
110
- if (!topic) {
111
- alert('Veuillez entrer un sujet.');
112
- return;
113
- }
114
-
115
- const contentType = document.querySelector('input[name="contentType"]:checked').value;
116
 
117
- // Afficher le chargement et réinitialiser les sections
118
- loadingIndicator.classList.remove('hidden');
119
- flashcardsContainer.querySelector('.grid') && (flashcardsContainer.querySelector('.grid').innerHTML = '');
120
- quizContainer.innerHTML = '';
121
- flashcardsContainer.classList.add('hidden');
122
- quizContainer.classList.add('hidden');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
 
124
- // Simulation d'appel API (remplacez par votre fetch)
125
- setTimeout(() => {
126
- loadingIndicator.classList.add('hidden');
127
- // Exemple de données fictives pour le quiz
128
- if (contentType === 'quiz') {
129
- const data = {
130
- quiz: [
131
- {
132
- question: "When did World War II begin?",
133
- options: ["September 1, 1938", "September 2, 1945", "September 1, 1939", "December 7, 1941"],
134
- correctAnswer: "September 1, 1939",
135
- explanation: "World War II began on September 1, 1939, with the German invasion of Poland."
136
- },
137
- {
138
- question: "Which event led the United States to enter World War II?",
139
- options: ["The invasion of Poland", "The fall of France", "The attack on Pearl Harbor", "The Battle of Britain"],
140
- correctAnswer: "The attack on Pearl Harbor",
141
- explanation: "The Japanese attack on Pearl Harbor on December 7, 1941, prompted the United States to declare war."
142
- }
143
- ]
144
- };
145
- quizContainer.classList.remove('hidden');
146
- displayQuiz(data.quiz);
147
- } else {
148
- // Exemple fictif pour les flashcards
149
- const data = {
150
- flashcards: [
151
- { question: "Capital of France?", answer: "Paris" },
152
- { question: "Capital of Spain?", answer: "Madrid" },
153
- { question: "Capital of Italy?", answer: "Rome" }
154
- ]
155
- };
156
- flashcardsContainer.classList.remove('hidden');
157
- displayFlashcards(data.flashcards);
158
- }
159
- }, 1500);
160
- });
 
 
 
 
 
 
 
 
 
 
161
 
162
- function displayFlashcards(flashcards) {
163
- const gridContainer = flashcardsContainer.querySelector('.grid') || document.createElement('div');
164
- if (!gridContainer.classList.contains('grid')) {
165
- gridContainer.className = 'grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6';
166
- flashcardsContainer.appendChild(gridContainer);
167
- }
168
- gridContainer.innerHTML = '';
169
- flashcards.forEach((card, index) => {
170
- const cardElement = document.createElement('div');
171
- cardElement.className = 'bg-white rounded-xl shadow-lg p-6 cursor-pointer hover-transform';
172
- cardElement.setAttribute('onclick', `toggleAnswer(${index})`);
173
- cardElement.innerHTML = `
174
- <h3 class="text-xl font-semibold text-gray-800 mb-4">${card.question}</h3>
175
- <div id="answer-${index}" class="hidden text-gray-700 border-t border-gray-200 pt-4">
176
- <span class="font-bold">Réponse:</span> ${card.answer}
177
- </div>
178
- `;
179
- gridContainer.appendChild(cardElement);
180
- });
181
- }
182
 
183
- function toggleAnswer(index) {
184
- const answerElement = document.getElementById(`answer-${index}`);
185
- answerElement.classList.toggle('hidden');
186
- }
 
 
187
 
188
- function displayQuiz(quizQuestions) {
189
- quizQuestions.forEach((question, qIndex) => {
190
- const questionCard = document.createElement('div');
191
- questionCard.className = 'bg-white rounded-xl shadow-lg p-6 mb-6';
192
- let optionsHtml = '';
193
- // Sécuriser la réponse correcte
194
- const safeCorrectAnswer = question.correctAnswer.replace(/"/g, '&quot;');
195
- question.options.forEach((option, oIndex) => {
196
- optionsHtml += `
197
- <div class="option block p-3 my-2 border border-gray-200 rounded-md cursor-pointer hover-transform hover:bg-gray-50 text-gray-800"
198
- id="q${qIndex}-o${oIndex}"
199
- data-correct="${safeCorrectAnswer}"
200
- onclick="selectOption(this, ${qIndex}, ${oIndex})">
201
- ${option}
 
 
 
 
 
202
  </div>
203
- `;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  });
205
- questionCard.innerHTML = `
206
- <h4 class="text-lg font-semibold text-gray-800 mb-4">${qIndex + 1}. ${question.question}</h4>
207
- <div class="options">
208
- ${optionsHtml}
209
- </div>
210
- <div id="explanation-${qIndex}" class="hidden mt-4 p-4 rounded-md bg-blue-50 border border-blue-200 text-blue-700 text-sm">
211
- <strong>Explication:</strong> ${question.explanation}
212
- </div>
213
- `;
214
- quizContainer.appendChild(questionCard);
215
- });
216
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
217
 
218
- function selectOption(element, questionIndex, optionIndex) {
219
- const correctAnswer = element.dataset.correct;
220
- const questionOptions = quizContainer.querySelectorAll(`#q${questionIndex}-o0`)[0].parentElement.querySelectorAll('.option');
221
- const explanationElement = document.getElementById(`explanation-${questionIndex}`);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
 
223
- // Vérifier si une option a déjà été sélectionnée pour éviter le re-clic
224
- let alreadyAnswered = false;
225
- questionOptions.forEach(opt => {
226
- if (opt.classList.contains('bg-green-100') || opt.classList.contains('bg-red-100')) {
227
- alreadyAnswered = true;
228
- }
229
- });
230
- if (alreadyAnswered) return;
231
 
232
- // Réinitialiser les styles pour toutes les options
233
- questionOptions.forEach(option => {
234
- option.classList.remove('bg-indigo-100', 'border-indigo-300', 'bg-green-100', 'border-green-300', 'text-green-800', 'bg-red-100', 'border-red-300', 'text-red-800');
235
- option.classList.add('hover:bg-gray-50');
236
- });
 
 
 
 
237
 
238
- // Appliquer le style à l'option sélectionnée
239
- element.classList.add('bg-indigo-100', 'border-indigo-300');
240
- element.classList.remove('hover:bg-gray-50');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
241
 
242
- const selectedText = element.textContent.trim();
243
- if (selectedText === correctAnswer) {
244
- element.classList.remove('bg-indigo-100', 'border-indigo-300');
245
- element.classList.add('bg-green-100', 'border-green-300', 'text-green-800');
246
- } else {
247
- element.classList.remove('bg-indigo-100', 'border-indigo-300');
248
- element.classList.add('bg-red-100', 'border-red-300', 'text-red-800');
249
- // Mettre en évidence la bonne réponse
250
- questionOptions.forEach(option => {
251
- if (option.textContent.trim() === correctAnswer) {
252
- option.classList.add('bg-green-100', 'border-green-300', 'text-green-800');
253
- option.classList.remove('hover:bg-gray-50');
254
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
  });
256
- }
257
 
258
- // Désactiver les clics sur toutes les options de cette question
259
- questionOptions.forEach(option => {
260
- option.onclick = null;
261
- option.classList.remove('cursor-pointer');
262
- option.style.cursor = 'default';
263
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
 
265
- // Afficher l'explication
266
- explanationElement.classList.remove('hidden');
267
- }
268
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
  </body>
270
- </html>
 
1
  <!DOCTYPE html>
2
  <html lang="fr">
3
  <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Générateur de Flashcards et Quiz</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
9
+ <script>
10
+ tailwind.config = {
11
+ theme: {
12
+ extend: {
13
+ colors: {
14
+ primary: {
15
+ 50: '#f0f9ff',
16
+ 100: '#e0f2fe',
17
+ 200: '#bae6fd',
18
+ 300: '#7dd3fc',
19
+ 400: '#38bdf8',
20
+ 500: '#0ea5e9',
21
+ 600: '#0284c7',
22
+ 700: '#0369a1',
23
+ 800: '#075985',
24
+ 900: '#0c4a6e',
25
+ }
26
+ },
27
+ animation: {
28
+ 'bounce-slow': 'bounce 3s linear infinite',
29
+ }
30
+ }
31
+ }
32
+ }
33
+ </script>
34
+ <style>
35
+ @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
36
+
37
+ body {
38
+ font-family: 'Poppins', sans-serif;
39
+ background-color: #f8fafc;
40
+ }
41
+
42
+ .flashcard {
43
+ perspective: 1000px;
44
+ height: 220px;
45
+ }
46
+
47
+ .flashcard-inner {
48
+ position: relative;
49
+ width: 100%;
50
+ height: 100%;
51
+ transition: transform 0.8s;
52
+ transform-style: preserve-3d;
53
+ }
54
+
55
+ .flashcard.flipped .flashcard-inner {
56
+ transform: rotateY(180deg);
57
+ }
58
+
59
+ .flashcard-front, .flashcard-back {
60
+ position: absolute;
61
+ width: 100%;
62
+ height: 100%;
63
+ -webkit-backface-visibility: hidden;
64
+ backface-visibility: hidden;
65
+ display: flex;
66
+ align-items: center;
67
+ justify-content: center;
68
+ border-radius: 0.5rem;
69
+ padding: 1.5rem;
70
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
71
+ }
72
+
73
+ .flashcard-front {
74
+ background-color: #ffffff;
75
+ color: #1e293b;
76
+ border-left: 5px solid #0ea5e9;
77
+ }
78
+
79
+ .flashcard-back {
80
+ background-color: #0ea5e9;
81
+ color: white;
82
+ transform: rotateY(180deg);
83
+ }
84
+
85
+ .quiz-option {
86
+ position: relative;
87
+ padding-left: 2.5rem;
88
+ }
89
+
90
+ .quiz-option input[type="radio"] {
91
+ position: absolute;
92
+ opacity: 0;
93
+ }
94
+
95
+ .quiz-option label {
96
+ display: block;
97
+ position: relative;
98
+ padding: 1rem 1.5rem 1rem 2.5rem;
99
+ cursor: pointer;
100
+ border: 1px solid #e2e8f0;
101
+ border-radius: 0.5rem;
102
+ transition: all 0.3s ease;
103
+ }
104
+
105
+ .quiz-option label:before {
106
+ content: '';
107
+ position: absolute;
108
+ left: 1rem;
109
+ top: 50%;
110
+ transform: translateY(-50%);
111
+ width: 1.25rem;
112
+ height: 1.25rem;
113
+ border-radius: 50%;
114
+ border: 2px solid #cbd5e1;
115
+ transition: all 0.3s ease;
116
+ }
117
+
118
+ .quiz-option input[type="radio"]:checked + label {
119
+ background-color: #e0f2fe;
120
+ border-color: #0ea5e9;
121
+ }
122
+
123
+ .quiz-option input[type="radio"]:checked + label:before {
124
+ border-color: #0ea5e9;
125
+ background-color: #0ea5e9;
126
+ box-shadow: inset 0 0 0 4px #e0f2fe;
127
+ }
128
+
129
+ .quiz-option.correct input[type="radio"]:checked + label {
130
+ background-color: #d1fae5;
131
+ border-color: #10b981;
132
+ }
133
+
134
+ .quiz-option.correct input[type="radio"]:checked + label:before {
135
+ border-color: #10b981;
136
+ background-color: #10b981;
137
+ box-shadow: inset 0 0 0 4px #d1fae5;
138
+ }
139
+
140
+ .quiz-option.incorrect input[type="radio"]:checked + label {
141
+ background-color: #fee2e2;
142
+ border-color: #ef4444;
143
+ }
144
+
145
+ .quiz-option.incorrect input[type="radio"]:checked + label:before {
146
+ border-color: #ef4444;
147
+ background-color: #ef4444;
148
+ box-shadow: inset 0 0 0 4px #fee2e2;
149
+ }
150
+
151
+ .progress-bar-container {
152
+ width: 100%;
153
+ height: 8px;
154
+ background-color: #e2e8f0;
155
+ border-radius: 4px;
156
+ overflow: hidden;
157
+ }
158
+
159
+ .progress-bar {
160
+ height: 100%;
161
+ background-color: #0ea5e9;
162
+ transition: width 0.5s ease;
163
+ }
164
+
165
+ .floating-label {
166
+ position: absolute;
167
+ top: -10px;
168
+ left: 10px;
169
+ padding: 0 5px;
170
+ background-color: white;
171
+ transition: all 0.3s ease;
172
+ pointer-events: none;
173
+ }
174
+
175
+ .pulse-animation {
176
+ animation: pulse 2s infinite;
177
+ }
178
+
179
+ @keyframes pulse {
180
+ 0% {
181
+ box-shadow: 0 0 0 0 rgba(14, 165, 233, 0.4);
182
+ }
183
+ 70% {
184
+ box-shadow: 0 0 0 10px rgba(14, 165, 233, 0);
185
+ }
186
+ 100% {
187
+ box-shadow: 0 0 0 0 rgba(14, 165, 233, 0);
188
+ }
189
+ }
190
+
191
+ .confetti {
192
+ position: fixed;
193
+ width: 10px;
194
+ height: 10px;
195
+ background-color: #f00;
196
+ opacity: 0;
197
+ animation: confetti-fall 3s linear forwards;
198
+ }
199
+
200
+ @keyframes confetti-fall {
201
+ 0% {
202
+ transform: translateY(0) rotate(0deg);
203
+ opacity: 1;
204
+ }
205
+ 100% {
206
+ transform: translateY(100vh) rotate(360deg);
207
+ opacity: 0;
208
+ }
209
+ }
210
+
211
+ .btn-primary {
212
+ @apply bg-primary-600 text-white px-6 py-3 rounded-lg shadow-md hover:bg-primary-700 transition duration-300 ease-in-out transform hover:-translate-y-1 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-opacity-50;
213
+ }
214
+
215
+ .btn-secondary {
216
+ @apply bg-white text-primary-600 border border-primary-600 px-6 py-3 rounded-lg shadow-md hover:bg-primary-50 transition duration-300 ease-in-out transform hover:-translate-y-1 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-opacity-50;
217
+ }
218
+ </style>
219
  </head>
220
+ <body>
221
+ <div class="min-h-screen bg-gradient-to-b from-primary-50 to-white">
222
+ <header class="bg-white shadow-sm py-6">
223
+ <div class="container mx-auto px-4">
224
+ <div class="flex items-center justify-between">
225
+ <h1 class="text-3xl font-bold text-primary-700 flex items-center">
226
+ <i class="fas fa-brain mr-3 text-primary-500"></i>
227
+ Mémorisation Facile
228
+ </h1>
229
+ <div class="flex space-x-2">
230
+ <button id="themeToggle" class="p-2 rounded-full hover:bg-gray-100">
231
+ <i class="fas fa-moon text-gray-600"></i>
232
+ </button>
233
+ <button class="p-2 rounded-full hover:bg-gray-100">
234
+ <i class="fas fa-question-circle text-gray-600"></i>
235
+ </button>
236
+ </div>
237
+ </div>
238
+ </div>
239
+ </header>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
240
 
241
+ <main class="container mx-auto px-4 py-8">
242
+ <div class="max-w-3xl mx-auto">
243
+ <!-- Introduction -->
244
+ <div class="text-center mb-8">
245
+ <h2 class="text-4xl font-bold text-gray-800 mb-4">Apprenez plus efficacement</h2>
246
+ <p class="text-lg text-gray-600 mb-6">Créez des flashcards ou des quiz pour mémoriser n'importe quel sujet</p>
247
+ </div>
248
+
249
+ <!-- Section de configuration -->
250
+ <div class="bg-white rounded-xl shadow-lg p-8 mb-10 relative overflow-hidden">
251
+ <div class="absolute top-0 right-0 w-40 h-40 bg-primary-100 rounded-full -mr-20 -mt-20 z-0"></div>
252
+ <div class="absolute bottom-0 left-0 w-24 h-24 bg-primary-100 rounded-full -ml-12 -mb-12 z-0"></div>
253
+
254
+ <div class="relative z-10">
255
+ <h3 class="text-2xl font-semibold text-gray-800 mb-6">Que souhaitez-vous apprendre aujourd'hui ?</h3>
256
+
257
+ <div class="space-y-6">
258
+ <div class="relative">
259
+ <input type="text" id="topic" class="w-full px-4 py-3 border-2 border-gray-300 rounded-lg focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50 transition-all duration-300 pl-10" placeholder="Entrez un sujet...">
260
+ <i class="fas fa-search absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400"></i>
261
+ <div class="text-xs text-gray-500 mt-1 ml-2">Exemples: "Capitales du monde", "Photosynthèse", "Verbes irréguliers en anglais"</div>
262
+ </div>
263
+
264
+ <div>
265
+ <p class="text-gray-700 font-medium mb-3">Choisissez votre méthode d'apprentissage :</p>
266
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
267
+ <div class="relative">
268
+ <input type="radio" id="typeFlashcards" name="contentType" value="flashcards" checked class="peer absolute opacity-0">
269
+ <label for="typeFlashcards" class="flex flex-col items-center justify-center p-4 border-2 border-gray-200 rounded-lg cursor-pointer transition-all duration-300 hover:bg-gray-50 peer-checked:border-primary-500 peer-checked:bg-primary-50">
270
+ <div class="w-12 h-12 rounded-full bg-primary-100 flex items-center justify-center mb-3">
271
+ <i class="fas fa-clone text-xl text-primary-600"></i>
272
+ </div>
273
+ <h4 class="font-semibold text-gray-800">Flashcards</h4>
274
+ <p class="text-sm text-gray-600 text-center mt-2">Pour mémoriser des informations par répétition</p>
275
+ </label>
276
+ </div>
277
+
278
+ <div class="relative">
279
+ <input type="radio" id="typeQuiz" name="contentType" value="quiz" class="peer absolute opacity-0">
280
+ <label for="typeQuiz" class="flex flex-col items-center justify-center p-4 border-2 border-gray-200 rounded-lg cursor-pointer transition-all duration-300 hover:bg-gray-50 peer-checked:border-primary-500 peer-checked:bg-primary-50">
281
+ <div class="w-12 h-12 rounded-full bg-primary-100 flex items-center justify-center mb-3">
282
+ <i class="fas fa-question text-xl text-primary-600"></i>
283
+ </div>
284
+ <h4 class="font-semibold text-gray-800">Quiz</h4>
285
+ <p class="text-sm text-gray-600 text-center mt-2">Pour tester vos connaissances avec des QCM</p>
286
+ </label>
287
+ </div>
288
+ </div>
289
+ </div>
290
+
291
+ <div class="flex items-center justify-between pt-2">
292
+ <div class="text-sm text-gray-500 italic">
293
+ <i class="fas fa-info-circle mr-1"></i> La génération peut prendre jusqu'à 1 minute
294
+ </div>
295
+ <button id="generateBtn" class="btn-primary flex items-center">
296
+ <span class="mr-2">Générer</span>
297
+ <i class="fas fa-chevron-right"></i>
298
+ </button>
299
+ </div>
300
+ </div>
301
+ </div>
302
+ </div>
303
 
304
+ <!-- Indicateur de chargement -->
305
+ <div id="loading" class="hidden">
306
+ <div class="bg-white rounded-xl shadow-lg p-8 text-center">
307
+ <div class="flex flex-col items-center justify-center space-y-4">
308
+ <div class="relative w-24 h-24">
309
+ <div class="absolute inset-0 border-4 border-primary-100 border-t-primary-500 rounded-full animate-spin"></div>
310
+ <div class="absolute inset-0 flex items-center justify-center">
311
+ <i class="fas fa-lightbulb text-2xl text-primary-500 animate-pulse"></i>
312
+ </div>
313
+ </div>
314
+ <h3 class="text-xl font-semibold text-gray-800">Création en cours...</h3>
315
+ <p class="text-gray-600">Nous élaborons votre contenu d'apprentissage personnalisé</p>
316
+
317
+ <div class="w-full max-w-md mt-4">
318
+ <div class="progress-bar-container">
319
+ <div id="progressBar" class="progress-bar" style="width: 0%"></div>
320
+ </div>
321
+ <div id="loadingSteps" class="mt-8 text-left">
322
+ <div class="flex items-center mb-3">
323
+ <div class="w-6 h-6 rounded-full bg-primary-500 flex items-center justify-center mr-3">
324
+ <i class="fas fa-check text-white text-xs"></i>
325
+ </div>
326
+ <span class="text-sm text-gray-700">Analyse du sujet</span>
327
+ </div>
328
+ <div class="flex items-center mb-3">
329
+ <div id="step2" class="w-6 h-6 rounded-full bg-gray-200 flex items-center justify-center mr-3">
330
+ <i class="fas fa-spinner text-white text-xs animate-spin"></i>
331
+ </div>
332
+ <span class="text-sm text-gray-500">Recherche d'informations</span>
333
+ </div>
334
+ <div class="flex items-center mb-3">
335
+ <div id="step3" class="w-6 h-6 rounded-full bg-gray-200 flex items-center justify-center mr-3">
336
+ <i class="fas fa-hourglass text-white text-xs"></i>
337
+ </div>
338
+ <span class="text-sm text-gray-500">Création du contenu</span>
339
+ </div>
340
+ <div class="flex items-center">
341
+ <div id="step4" class="w-6 h-6 rounded-full bg-gray-200 flex items-center justify-center mr-3">
342
+ <i class="fas fa-hourglass text-white text-xs"></i>
343
+ </div>
344
+ <span class="text-sm text-gray-500">Finalisation</span>
345
+ </div>
346
+ </div>
347
+ </div>
348
+ </div>
349
+ </div>
350
+ </div>
351
 
352
+ <!-- Conteneur pour les Flashcards -->
353
+ <div id="flashcardsContainer" class="mt-8 hidden">
354
+ <!-- Les flashcards seront injectées ici -->
355
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
356
 
357
+ <!-- Conteneur pour le Quiz -->
358
+ <div id="quizContainer" class="mt-8 hidden">
359
+ <!-- Les questions du quiz seront injectées ici -->
360
+ </div>
361
+ </div>
362
+ </main>
363
 
364
+ <footer class="bg-gray-900 text-white py-8 mt-20">
365
+ <div class="container mx-auto px-4">
366
+ <div class="flex flex-col md:flex-row justify-between items-center">
367
+ <div class="mb-4 md:mb-0">
368
+ <h2 class="text-xl font-bold flex items-center">
369
+ <i class="fas fa-brain mr-2"></i> Mémorisation Facile
370
+ </h2>
371
+ <p class="text-gray-400 text-sm mt-2">Votre outil d'apprentissage intelligent</p>
372
+ </div>
373
+ <div class="flex space-x-4">
374
+ <a href="#" class="text-gray-400 hover:text-white transition-colors"><i class="fab fa-twitter"></i></a>
375
+ <a href="#" class="text-gray-400 hover:text-white transition-colors"><i class="fab fa-facebook"></i></a>
376
+ <a href="#" class="text-gray-400 hover:text-white transition-colors"><i class="fab fa-instagram"></i></a>
377
+ <a href="#" class="text-gray-400 hover:text-white transition-colors"><i class="fab fa-youtube"></i></a>
378
+ </div>
379
+ </div>
380
+ <div class="mt-8 border-t border-gray-800 pt-6 text-sm text-gray-400 text-center">
381
+ &copy; 2025 Mémorisation Facile. Tous droits réservés.
382
+ </div>
383
  </div>
384
+ </footer>
385
+ </div>
386
+
387
+ <script>
388
+ const generateBtn = document.getElementById('generateBtn');
389
+ const loadingIndicator = document.getElementById('loading');
390
+ const flashcardsContainer = document.getElementById('flashcardsContainer');
391
+ const quizContainer = document.getElementById('quizContainer');
392
+ const topicInput = document.getElementById('topic');
393
+ const progressBar = document.getElementById('progressBar');
394
+ const themeToggle = document.getElementById('themeToggle');
395
+ const step2 = document.getElementById('step2');
396
+ const step3 = document.getElementById('step3');
397
+ const step4 = document.getElementById('step4');
398
+
399
+ // Gestion du thème clair/sombre
400
+ themeToggle.addEventListener('click', function() {
401
+ document.body.classList.toggle('dark-mode');
402
+ const icon = this.querySelector('i');
403
+ if (icon.classList.contains('fa-moon')) {
404
+ icon.classList.remove('fa-moon');
405
+ icon.classList.add('fa-sun');
406
+ } else {
407
+ icon.classList.remove('fa-sun');
408
+ icon.classList.add('fa-moon');
409
+ }
410
  });
411
+
412
+ // Animation de chargement
413
+ function simulateLoading() {
414
+ let progress = 0;
415
+ const interval = setInterval(() => {
416
+ progress += 1;
417
+ progressBar.style.width = `${progress}%`;
418
+
419
+ if (progress === 25) {
420
+ step2.classList.remove('bg-gray-200');
421
+ step2.classList.add('bg-primary-500');
422
+ step2.innerHTML = '<i class="fas fa-check text-white text-xs"></i>';
423
+ } else if (progress === 60) {
424
+ step3.classList.remove('bg-gray-200');
425
+ step3.classList.add('bg-primary-500');
426
+ step3.innerHTML = '<i class="fas fa-check text-white text-xs"></i>';
427
+ step4.innerHTML = '<i class="fas fa-spinner text-white text-xs animate-spin"></i>';
428
+ } else if (progress === 95) {
429
+ step4.classList.remove('bg-gray-200');
430
+ step4.classList.add('bg-primary-500');
431
+ step4.innerHTML = '<i class="fas fa-check text-white text-xs"></i>';
432
+ }
433
+
434
+ if (progress >= 100) {
435
+ clearInterval(interval);
436
+ }
437
+ }, 50);
438
+
439
+ return interval;
440
+ }
441
+
442
+ // Fonction pour créer des confettis
443
+ function createConfetti() {
444
+ const confettiCount = 100;
445
+ const colors = ['#0ea5e9', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6'];
446
+
447
+ for (let i = 0; i < confettiCount; i++) {
448
+ const confetti = document.createElement('div');
449
+ confetti.className = 'confetti';
450
+ confetti.style.left = `${Math.random() * 100}vw`;
451
+ confetti.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
452
+ confetti.style.width = `${Math.random() * 10 + 5}px`;
453
+ confetti.style.height = `${Math.random() * 10 + 5}px`;
454
+ confetti.style.animationDuration = `${Math.random() * 3 + 2}s`;
455
+ document.body.appendChild(confetti);
456
+
457
+ setTimeout(() => {
458
+ confetti.remove();
459
+ }, 5000);
460
+ }
461
+ }
462
 
463
+ // Gestion des flashcards
464
+ function flipCard(card) {
465
+ card.classList.toggle('flipped');
466
+ }
467
+
468
+ generateBtn.addEventListener('click', function() {
469
+ const topic = topicInput.value.trim();
470
+ if (!topic) {
471
+ // Animation de secouement sur l'input
472
+ topicInput.classList.add('border-red-500');
473
+ topicInput.classList.add('animate-bounce');
474
+ setTimeout(() => {
475
+ topicInput.classList.remove('animate-bounce');
476
+ topicInput.classList.remove('border-red-500');
477
+ }, 1000);
478
+
479
+ // Afficher un message d'erreur
480
+ const errorMsg = document.createElement('div');
481
+ errorMsg.className = 'text-red-500 text-sm mt-1 ml-2';
482
+ errorMsg.textContent = 'Veuillez entrer un sujet';
483
+ topicInput.parentElement.appendChild(errorMsg);
484
+ setTimeout(() => {
485
+ errorMsg.remove();
486
+ }, 3000);
487
+
488
+ return;
489
+ }
490
 
491
+ const contentType = document.querySelector('input[name="contentType"]:checked').value;
 
 
 
 
 
 
 
492
 
493
+ // Afficher le chargement et cacher les anciens résultats
494
+ loadingIndicator.classList.remove('hidden');
495
+ flashcardsContainer.classList.add('hidden');
496
+ quizContainer.classList.add('hidden');
497
+ flashcardsContainer.innerHTML = '';
498
+ quizContainer.innerHTML = '';
499
+
500
+ // Simuler l'animation de chargement
501
+ const loadingInterval = simulateLoading();
502
 
503
+ // Envoi de la requête
504
+ fetch('/generate', {
505
+ method: 'POST',
506
+ headers: {
507
+ 'Content-Type': 'application/json',
508
+ },
509
+ body: JSON.stringify({ topic, type: contentType }),
510
+ })
511
+ .then(response => {
512
+ if (!response.ok) {
513
+ throw new Error(`Erreur HTTP: ${response.status}`);
514
+ }
515
+ return response.json();
516
+ })
517
+ .then(data => {
518
+ // Assurons-nous que l'animation montre au moins 2 secondes
519
+ setTimeout(() => {
520
+ clearInterval(loadingInterval);
521
+ progressBar.style.width = '100%';
522
+
523
+ setTimeout(() => {
524
+ loadingIndicator.classList.add('hidden');
525
+
526
+ if (data.error) {
527
+ // Afficher une erreur élégante
528
+ const errorContainer = document.createElement('div');
529
+ errorContainer.className = 'bg-red-50 border-l-4 border-red-500 p-4 rounded-md mt-4';
530
+ errorContainer.innerHTML = `
531
+ <div class="flex">
532
+ <div class="flex-shrink-0">
533
+ <i class="fas fa-exclamation-circle text-red-500"></i>
534
+ </div>
535
+ <div class="ml-3">
536
+ <p class="text-sm text-red-700">
537
+ ${data.error}
538
+ </p>
539
+ </div>
540
+ </div>
541
+ `;
542
+ document.querySelector('.max-w-3xl').appendChild(errorContainer);
543
+ return;
544
+ }
545
 
546
+ if (contentType === 'flashcards' && data.flashcards) {
547
+ flashcardsContainer.classList.remove('hidden');
548
+ displayFlashcards(data.flashcards);
549
+ // Créer un effet de confettis
550
+ createConfetti();
551
+ } else if (contentType === 'quiz' && data.quiz) {
552
+ quizContainer.classList.remove('hidden');
553
+ displayQuiz(data.quiz);
554
+ // Créer un effet de confettis
555
+ createConfetti();
556
+ } else {
557
+ // Afficher une erreur élégante
558
+ const errorContainer = document.createElement('div');
559
+ errorContainer.className = 'bg-red-50 border-l-4 border-red-500 p-4 rounded-md mt-4';
560
+ errorContainer.innerHTML = `
561
+ <div class="flex">
562
+ <div class="flex-shrink-0">
563
+ <i class="fas fa-exclamation-circle text-red-500"></i>
564
+ </div>
565
+ <div class="ml-3">
566
+ <p class="text-sm text-red-700">
567
+ Aucune donnée reçue ou format incorrect.
568
+ </p>
569
+ </div>
570
+ </div>
571
+ `;
572
+ document.querySelector('.max-w-3xl').appendChild(errorContainer);
573
+ }
574
+ }, 500);
575
+ }, 2000);
576
+ })
577
+ .catch(error => {
578
+ clearInterval(loadingInterval);
579
+ loadingIndicator.classList.add('hidden');
580
+ console.error('Erreur lors de la génération:', error);
581
+
582
+ // Afficher une erreur élégante
583
+ const errorContainer = document.createElement('div');
584
+ errorContainer.className = 'bg-red-50 border-l-4 border-red-500 p-4 rounded-md mt-4';
585
+ errorContainer.innerHTML = `
586
+ <div class="flex">
587
+ <div class="flex-shrink-0">
588
+ <i class="fas fa-exclamation-circle text-red-500"></i>
589
+ </div>
590
+ <div class="ml-3">
591
+ <p class="text-sm text-red-700">
592
+ Erreur lors de la génération: ${error.message}.
593
+ </p>
594
+ </div>
595
+ </div>
596
+ `;
597
+ document.querySelector('.max-w-3xl').appendChild(errorContainer);
598
+ });
599
  });
 
600
 
601
+ function displayFlashcards(flashcards) {
602
+ const header = document.createElement('div');
603
+ header.className = 'mb-8 text-center';
604
+ header.innerHTML = `
605
+ <h2 class="text-3xl font-bold text-gray-800 mb-2">Vos Flashcards (${flashcards.length})</h2>
606
+ <p class="text-gray-600">Cliquez sur une carte pour la retourner et voir la réponse</p>
607
+ <div class="flex items-center justify-center space-x-4 mt-6">
608
+ <button id="printBtn" class="btn-secondary text-sm">
609
+ <i class="fas fa-print mr-2"></i> Imprimer
610
+ </button>
611
+ <button id="saveBtn" class="btn-secondary text-sm">
612
+ <i class="fas fa-save mr-2"></i> Enregistrer
613
+ </button>
614
+ <button id="shareBtn" class="btn-secondary text-sm">
615
+ <i class="fas fa-share-alt mr-2"></i> Partager
616
+ </button>
617
+ </div>
618
+ `;
619
+ flashcardsContainer.appendChild(header);
620
+
621
+ const flashcardsGrid = document.createElement('div');
622
+ flashcardsGrid.className = 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6';
623
+ flashcardsContainer.appendChild(flashcardsGrid);
624
+
625
+ flashcards.forEach((card, index) => {
626
+ const cardElement = document.createElement('div');
627
+ cardElement.className = 'flashcard cursor-pointer';
628
+ cardElement.onclick = function() { flipCard(this); };
629
+ cardElement.innerHTML = `
630
+ <div class="flashcard-inner">
631
+ <div class="flashcard-front">
632
+ <div class="w-full">
633
+ <div class="absolute top-2 left-2 text-xs text-gray-400">#${index + 1}</div>
634
+ <h3 class="text-lg font-semibold mb-2 text-center">${card.question}</h3>
635
+ <div class="text-center mt-4">
636
+ <span class="text-xs text-gray-500">Cliquez pour voir la réponse</span>
637
+ </div>
638
+ </div>
639
+ </div>
640
+
641
+ <div class="flashcard-back">
642
+ <div class="w-full">
643
+ <div class="absolute top-2 right-2 text-xs text-white opacity-70">#${index + 1}</div>
644
+ <div class="text-center">
645
+ <p class="font-medium">${card.answer}</p>
646
+ </div>
647
+ <div class="absolute bottom-2 right-2">
648
+ <span class="text-xs text-white opacity-70">Cliquez pour retourner</span>
649
+ </div>
650
+ </div>
651
+ </div>
652
+ </div>
653
+ `;
654
+ flashcardsGrid.appendChild(cardElement);
655
+ });
656
+
657
+ // Ajouter des boutons de navigation et de contrôle
658
+ const controls = document.createElement('div');
659
+ controls.className = 'mt-10 flex flex-col items-center justify-center';
660
+ controls.innerHTML = `
661
+ <div class="flex items-center space-x-4 mb-6">
662
+ <button class="px-4 py-2 bg-primary-100 hover:bg-primary-200 text-primary-700 rounded-md transition duration-300 flex items-center">
663
+ <i class="fas fa-redo-alt mr-2"></i> Recommencer
664
+ </button>
665
+ <button id="newTopicBtn" class="px-4 py-2 bg-primary-600 hover:bg-primary-700 text-white rounded-md transition duration-300 flex items-center">
666
+ <i class="fas fa-plus mr-2"></i> Nouveau sujet
667
+ </button>
668
+ </div>
669
+ <div class="text-center mt-2">
670
+ <p class="text-gray-500 text-sm">
671
+ <i class="far fa-lightbulb mr-1"></i> Astuce : Essayez de répondre mentalement avant de retourner la carte
672
+ </p>
673
+ </div>
674
+ `;
675
+ flashcardsContainer.appendChild(controls);
676
+
677
+ // Ajouter des interactions aux boutons
678
+ document.getElementById('printBtn').addEventListener('click', function() {
679
+ window.print();
680
+ });
681
+
682
+ document.getElementById('saveBtn').addEventListener('click', function() {
683
+ alert('Flashcards sauvegardées !');
684
+ });
685
+
686
+ document.getElementById('shareBtn').addEventListener('click', function() {
687
+ alert('Lien de partage copié dans le presse-papiers !');
688
+ });
689
+
690
+ document.getElementById('newTopicBtn').addEventListener('click', function() {
691
+ window.scrollTo({
692
+ top: 0,
693
+ behavior: 'smooth'
694
+ });
695
+ topicInput.focus();
696
+ });
697
+ }
698
 
699
+ function displayQuiz(quizQuestions) {
700
+ const header = document.createElement('div');
701
+ header.className = 'mb-8 text-center';
702
+ header.innerHTML = `
703
+ <h2 class="text-3xl font-bold text-gray-800 mb-2">Votre Quiz (${quizQuestions.length} questions)</h2>
704
+ <p class="text-gray-600">Testez vos connaissances en répondant aux questions</p>
705
+ <div class="flex items-center justify-center mt-6">
706
+ <div class="bg-white px-4 py-2 rounded-full shadow-sm flex items-center">
707
+ <span class="text-primary-700 font-medium">Score: </span>
708
+ <span id="score" class="ml-1 text-primary-700 font-bold">0</span>
709
+ <span class="mx-1 text-gray-400">/</span>
710
+ <span class="text-gray-600">${quizQuestions.length}</span>
711
+ </div>
712
+ </div>
713
+ `;
714
+ quizContainer.appendChild(header);
715
+
716
+ // Créer un conteneur pour les questions
717
+ const questionsContainer = document.createElement('div');
718
+ questionsContainer.className = 'space-y-8';
719
+ quizContainer.appendChild(questionsContainer);
720
+
721
+ // Variable pour suivre le score
722
+ let currentScore = 0;
723
+
724
+ quizQuestions.forEach((question, qIndex) => {
725
+ const questionElement = document.createElement('div');
726
+ questionElement.className = 'bg-white rounded-xl shadow-md p-6 transition-all duration-300';
727
+ questionElement.setAttribute('id', `question-${qIndex}`);
728
+
729
+ let optionsHtml = '';
730
+ const safeCorrectAnswer = question.correctAnswer.replace(/"/g, '&quot;');
731
+
732
+ question.options.forEach((option, oIndex) => {
733
+ optionsHtml += `
734
+ <div class="quiz-option mb-3" id="option-${qIndex}-${oIndex}">
735
+ <input type="radio" id="q${qIndex}-o${oIndex}" name="question-${qIndex}" value="${option}" data-correct="${safeCorrectAnswer}">
736
+ <label for="q${qIndex}-o${oIndex}" class="group">
737
+ ${option}
738
+ <span class="hidden success-icon absolute right-4 text-green-500">
739
+ <i class="fas fa-check-circle"></i>
740
+ </span>
741
+ <span class="hidden error-icon absolute right-4 text-red-500">
742
+ <i class="fas fa-times-circle"></i>
743
+ </span>
744
+ </label>
745
+ </div>
746
+ `;
747
+ });
748
+
749
+ questionElement.innerHTML = `
750
+ <div class="flex items-center justify-between mb-4">
751
+ <span class="bg-primary-100 text-primary-800 text-xs font-medium px-2.5 py-0.5 rounded">Question ${qIndex + 1}/${quizQuestions.length}</span>
752
+ <span class="text-gray-400 text-sm">
753
+ <i class="far fa-lightbulb"></i>
754
+ </span>
755
+ </div>
756
+ <h3 class="text-xl font-medium text-gray-800 mb-4">${question.question}</h3>
757
+ <div class="options mt-5">
758
+ ${optionsHtml}
759
+ </div>
760
+ <div class="explanation hidden mt-6 p-4 bg-blue-50 border border-blue-100 rounded-lg" id="explanation-${qIndex}">
761
+ <div class="flex items-start">
762
+ <div class="flex-shrink-0 mt-0.5">
763
+ <i class="fas fa-info-circle text-blue-500"></i>
764
+ </div>
765
+ <div class="ml-3">
766
+ <h4 class="text-sm font-medium text-blue-800">Explication</h4>
767
+ <div class="mt-1 text-sm text-blue-700">${question.explanation}</div>
768
+ </div>
769
+ </div>
770
+ </div>
771
+ `;
772
+ questionsContainer.appendChild(questionElement);
773
+
774
+ // Ajouter des gestionnaires d'événements pour les options
775
+ const options = questionElement.querySelectorAll('input[type="radio"]');
776
+ options.forEach((option) => {
777
+ option.addEventListener('change', function() {
778
+ const optionId = this.id;
779
+ const [_, qIdx, oIdx] = optionId.match(/q(\d+)-o(\d+)/);
780
+ const selected = this.value;
781
+ const correct = this.getAttribute('data-correct');
782
+ const explanationElement = document.getElementById(`explanation-${qIdx}`);
783
+
784
+ // Vérifier la réponse
785
+ if (selected === correct) {
786
+ // Réponse correcte
787
+ document.getElementById(`option-${qIdx}-${oIdx}`).classList.add('correct');
788
+ currentScore++;
789
+ document.getElementById('score').textContent = currentScore;
790
+
791
+ // Afficher une animation de succès
792
+ const successIcon = this.nextElementSibling.querySelector('.success-icon');
793
+ successIcon.classList.remove('hidden');
794
+ } else {
795
+ // Réponse incorrecte
796
+ document.getElementById(`option-${qIdx}-${oIdx}`).classList.add('incorrect');
797
+
798
+ // Afficher une animation d'erreur
799
+ const errorIcon = this.nextElementSibling.querySelector('.error-icon');
800
+ errorIcon.classList.remove('hidden');
801
+
802
+ // Mettre en évidence la bonne réponse
803
+ options.forEach((opt, idx) => {
804
+ if (opt.value === correct) {
805
+ document.getElementById(`option-${qIdx}-${idx}`).classList.add('correct');
806
+ const successIcon = opt.nextElementSibling.querySelector('.success-icon');
807
+ successIcon.classList.remove('hidden');
808
+ }
809
+ });
810
+ }
811
+
812
+ // Désactiver toutes les autres options
813
+ options.forEach((opt) => {
814
+ if (opt !== this) {
815
+ opt.disabled = true;
816
+ }
817
+ });
818
+
819
+ // Afficher l'explication
820
+ explanationElement.classList.remove('hidden');
821
+
822
+ // Animer le passage à la question suivante
823
+ setTimeout(() => {
824
+ const nextQuestion = document.getElementById(`question-${parseInt(qIdx) + 1}`);
825
+ if (nextQuestion) {
826
+ window.scrollTo({
827
+ top: nextQuestion.offsetTop - 20,
828
+ behavior: 'smooth'
829
+ });
830
+ } else {
831
+ // C'était la dernière question, afficher un récapitulatif
832
+ if (parseInt(qIdx) === quizQuestions.length - 1) {
833
+ displayQuizResults(currentScore, quizQuestions.length);
834
+ }
835
+ }
836
+ }, 1500);
837
+ });
838
+ });
839
+ });
840
+ }
841
+
842
+ function displayQuizResults(score, total) {
843
+ const percentage = (score / total) * 100;
844
+ let resultClass, resultIcon, resultMessage;
845
+
846
+ if (percentage >= 80) {
847
+ resultClass = 'bg-green-50 border-green-500 text-green-800';
848
+ resultIcon = '<i class="fas fa-trophy text-3xl text-yellow-500 mb-3"></i>';
849
+ resultMessage = 'Excellent ! Vous maîtrisez ce sujet.';
850
+ } else if (percentage >= 60) {
851
+ resultClass = 'bg-blue-50 border-blue-500 text-blue-800';
852
+ resultIcon = '<i class="fas fa-medal text-3xl text-blue-500 mb-3"></i>';
853
+ resultMessage = 'Bon travail ! Continuez vos efforts.';
854
+ } else {
855
+ resultClass = 'bg-red-50 border-red-500 text-red-800';
856
+ resultIcon = '<i class="fas fa-book-open text-3xl text-red-500 mb-3"></i>';
857
+ resultMessage = 'Continuez à étudier pour améliorer vos connaissances.';
858
+ }
859
+
860
+ const resultsElement = document.createElement('div');
861
+ resultsElement.className = `mt-10 p-6 rounded-xl shadow-lg border-l-4 ${resultClass} text-center`;
862
+ resultsElement.innerHTML = `
863
+ <div class="flex flex-col items-center">
864
+ ${resultIcon}
865
+ <h3 class="text-2xl font-bold mb-2">Résultat final: ${score}/${total}</h3>
866
+ <p class="mb-4">${resultMessage}</p>
867
+ <div class="w-full max-w-xs bg-gray-200 rounded-full h-4 mb-4">
868
+ <div class="h-4 rounded-full ${percentage >= 80 ? 'bg-green-500' : percentage >= 60 ? 'bg-blue-500' : 'bg-red-500'}" style="width: ${percentage}%"></div>
869
+ </div>
870
+ <div class="flex space-x-4 mt-6">
871
+ <button id="retryQuizBtn" class="btn-secondary text-sm">
872
+ <i class="fas fa-redo mr-2"></i> Réessayer
873
+ </button>
874
+ <button id="newQuizBtn" class="btn-primary text-sm">
875
+ <i class="fas fa-plus mr-2"></i> Nouveau quiz
876
+ </button>
877
+ </div>
878
+ </div>
879
+ `;
880
+ quizContainer.appendChild(resultsElement);
881
+
882
+ // Animation de confettis si le score est bon
883
+ if (percentage >= 70) {
884
+ createConfetti();
885
+ }
886
+
887
+ // Ajouter des interactions aux boutons
888
+ document.getElementById('retryQuizBtn').addEventListener('click', function() {
889
+ const radios = document.querySelectorAll('input[type="radio"]');
890
+ radios.forEach(radio => {
891
+ radio.checked = false;
892
+ radio.disabled = false;
893
+ });
894
+
895
+ const options = document.querySelectorAll('.quiz-option');
896
+ options.forEach(option => {
897
+ option.classList.remove('correct', 'incorrect');
898
+ });
899
+
900
+ const explanations = document.querySelectorAll('.explanation');
901
+ explanations.forEach(exp => {
902
+ exp.classList.add('hidden');
903
+ });
904
+
905
+ const icons = document.querySelectorAll('.success-icon, .error-icon');
906
+ icons.forEach(icon => {
907
+ icon.classList.add('hidden');
908
+ });
909
+
910
+ resultsElement.remove();
911
+ document.getElementById('score').textContent = '0';
912
+
913
+ window.scrollTo({
914
+ top: quizContainer.offsetTop,
915
+ behavior: 'smooth'
916
+ });
917
+ });
918
+
919
+ document.getElementById('newQuizBtn').addEventListener('click', function() {
920
+ window.scrollTo({
921
+ top: 0,
922
+ behavior: 'smooth'
923
+ });
924
+ topicInput.focus();
925
+ });
926
+ }
927
+
928
+ // Focus sur le champ de saisie au chargement
929
+ window.addEventListener('load', () => {
930
+ topicInput.focus();
931
+ });
932
+ </script>
933
  </body>
934
+ </html>