|
|
|
<!DOCTYPE html> |
|
|
|
<html lang="fr"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>Générateur de Flashcards et Quiz</title> |
|
<script src="https://cdn.tailwindcss.com"></script> |
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"> |
|
<script> |
|
tailwind.config = { |
|
theme: { |
|
extend: { |
|
colors: { |
|
primary: { |
|
50: '#f0f9ff', |
|
100: '#e0f2fe', |
|
200: '#bae6fd', |
|
300: '#7dd3fc', |
|
400: '#38bdf8', |
|
500: '#0ea5e9', |
|
600: '#0284c7', |
|
700: '#0369a1', |
|
800: '#075985', |
|
900: '#0c4a6e', |
|
} |
|
}, |
|
animation: { |
|
'bounce-slow': 'bounce 3s linear infinite', |
|
} |
|
} |
|
} |
|
} |
|
</script> |
|
<style> |
|
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap'); |
|
|
|
body { |
|
font-family: 'Poppins', sans-serif; |
|
background-color: #f8fafc; |
|
} |
|
|
|
.flashcard { |
|
perspective: 1000px; |
|
height: 220px; |
|
} |
|
|
|
.flashcard-inner { |
|
position: relative; |
|
width: 100%; |
|
height: 100%; |
|
transition: transform 0.8s; |
|
transform-style: preserve-3d; |
|
} |
|
|
|
.flashcard.flipped .flashcard-inner { |
|
transform: rotateY(180deg); |
|
} |
|
|
|
.flashcard-front, .flashcard-back { |
|
position: absolute; |
|
width: 100%; |
|
height: 100%; |
|
-webkit-backface-visibility: hidden; |
|
backface-visibility: hidden; |
|
display: flex; |
|
align-items: center; |
|
justify-content: center; |
|
border-radius: 0.5rem; |
|
padding: 1.5rem; |
|
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); |
|
} |
|
|
|
.flashcard-front { |
|
background-color: #ffffff; |
|
color: #1e293b; |
|
border-left: 5px solid #0ea5e9; |
|
} |
|
|
|
.flashcard-back { |
|
background-color: #0ea5e9; |
|
color: white; |
|
transform: rotateY(180deg); |
|
} |
|
|
|
.quiz-option { |
|
position: relative; |
|
padding-left: 2.5rem; |
|
} |
|
|
|
.quiz-option input[type="radio"] { |
|
position: absolute; |
|
opacity: 0; |
|
} |
|
|
|
.quiz-option label { |
|
display: block; |
|
position: relative; |
|
padding: 1rem 1.5rem 1rem 2.5rem; |
|
cursor: pointer; |
|
border: 1px solid #e2e8f0; |
|
border-radius: 0.5rem; |
|
transition: all 0.3s ease; |
|
} |
|
|
|
.quiz-option label:before { |
|
content: ''; |
|
position: absolute; |
|
left: 1rem; |
|
top: 50%; |
|
transform: translateY(-50%); |
|
width: 1.25rem; |
|
height: 1.25rem; |
|
border-radius: 50%; |
|
border: 2px solid #cbd5e1; |
|
transition: all 0.3s ease; |
|
} |
|
|
|
.quiz-option input[type="radio"]:checked + label { |
|
background-color: #e0f2fe; |
|
border-color: #0ea5e9; |
|
} |
|
|
|
.quiz-option input[type="radio"]:checked + label:before { |
|
border-color: #0ea5e9; |
|
background-color: #0ea5e9; |
|
box-shadow: inset 0 0 0 4px #e0f2fe; |
|
} |
|
|
|
.quiz-option.correct input[type="radio"]:checked + label { |
|
background-color: #d1fae5; |
|
border-color: #10b981; |
|
} |
|
|
|
.quiz-option.correct input[type="radio"]:checked + label:before { |
|
border-color: #10b981; |
|
background-color: #10b981; |
|
box-shadow: inset 0 0 0 4px #d1fae5; |
|
} |
|
|
|
.quiz-option.incorrect input[type="radio"]:checked + label { |
|
background-color: #fee2e2; |
|
border-color: #ef4444; |
|
} |
|
|
|
.quiz-option.incorrect input[type="radio"]:checked + label:before { |
|
border-color: #ef4444; |
|
background-color: #ef4444; |
|
box-shadow: inset 0 0 0 4px #fee2e2; |
|
} |
|
|
|
.progress-bar-container { |
|
width: 100%; |
|
height: 8px; |
|
background-color: #e2e8f0; |
|
border-radius: 4px; |
|
overflow: hidden; |
|
} |
|
|
|
.progress-bar { |
|
height: 100%; |
|
background-color: #0ea5e9; |
|
transition: width 0.5s ease; |
|
} |
|
|
|
.floating-label { |
|
position: absolute; |
|
top: -10px; |
|
left: 10px; |
|
padding: 0 5px; |
|
background-color: white; |
|
transition: all 0.3s ease; |
|
pointer-events: none; |
|
} |
|
|
|
.pulse-animation { |
|
animation: pulse 2s infinite; |
|
} |
|
|
|
@keyframes pulse { |
|
0% { |
|
box-shadow: 0 0 0 0 rgba(14, 165, 233, 0.4); |
|
} |
|
70% { |
|
box-shadow: 0 0 0 10px rgba(14, 165, 233, 0); |
|
} |
|
100% { |
|
box-shadow: 0 0 0 0 rgba(14, 165, 233, 0); |
|
} |
|
} |
|
|
|
.confetti { |
|
position: fixed; |
|
width: 10px; |
|
height: 10px; |
|
background-color: #f00; |
|
opacity: 0; |
|
animation: confetti-fall 3s linear forwards; |
|
} |
|
|
|
@keyframes confetti-fall { |
|
0% { |
|
transform: translateY(0) rotate(0deg); |
|
opacity: 1; |
|
} |
|
100% { |
|
transform: translateY(100vh) rotate(360deg); |
|
opacity: 0; |
|
} |
|
} |
|
|
|
.btn-primary { |
|
@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; |
|
} |
|
|
|
.btn-secondary { |
|
@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; |
|
} |
|
</style> |
|
|
|
</head> |
|
<body> |
|
<div class="min-h-screen bg-gradient-to-b from-primary-50 to-white"> |
|
<header class="bg-white shadow-sm py-6"> |
|
<div class="container mx-auto px-4"> |
|
<div class="flex items-center justify-between"> |
|
<a href="#" class="text-3xl font-bold text-primary-700 flex items-center"> |
|
<i class="fas fa-home mr-3 text-primary-500"></i> |
|
Mariam Quizz |
|
</a> |
|
<div class="flex space-x-2"> |
|
<button id="themeToggle" class="p-2 rounded-full hover:bg-gray-100"> |
|
<i class="fas fa-moon text-gray-600"></i> |
|
</button> |
|
<button class="p-2 rounded-full hover:bg-gray-100"> |
|
<i class="fas fa-question-circle text-gray-600"></i> |
|
</button> |
|
</div> |
|
</div> |
|
</div> |
|
</header> |
|
|
|
<main class="container mx-auto px-4 py-8"> |
|
<div class="max-w-3xl mx-auto"> |
|
|
|
<div class="text-center mb-8"> |
|
<h2 class="text-4xl font-bold text-gray-800 mb-4">Apprenez plus efficacement</h2> |
|
<p class="text-lg text-gray-600 mb-6">Créez des flashcards ou des quiz pour mémoriser n'importe quel sujet</p> |
|
</div> |
|
|
|
|
|
<div class="bg-white rounded-xl shadow-lg p-8 mb-10 relative overflow-hidden"> |
|
<div class="absolute top-0 right-0 w-40 h-40 bg-primary-100 rounded-full -mr-20 -mt-20 z-0"></div> |
|
<div class="absolute bottom-0 left-0 w-24 h-24 bg-primary-100 rounded-full -ml-12 -mb-12 z-0"></div> |
|
|
|
<div class="relative z-10"> |
|
<h3 class="text-2xl font-semibold text-gray-800 mb-6">Que souhaitez-vous apprendre aujourd'hui ?</h3> |
|
|
|
<div class="space-y-6"> |
|
<div class="relative"> |
|
<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..."> |
|
<i class="fas fa-search absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400"></i> |
|
<div class="text-xs text-gray-500 mt-1 ml-2">Exemples: "Capitales du monde", "Photosynthèse", "Verbes irréguliers en anglais"</div> |
|
</div> |
|
|
|
<div> |
|
<p class="text-gray-700 font-medium mb-3">Choisissez votre méthode d'apprentissage :</p> |
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4"> |
|
<div class="relative"> |
|
<input type="radio" id="typeFlashcards" name="contentType" value="flashcards" checked class="peer absolute opacity-0"> |
|
<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"> |
|
<div class="w-12 h-12 rounded-full bg-primary-100 flex items-center justify-center mb-3"> |
|
<i class="fas fa-clone text-xl text-primary-600"></i> |
|
</div> |
|
<h4 class="font-semibold text-gray-800">Flashcards</h4> |
|
<p class="text-sm text-gray-600 text-center mt-2">Pour mémoriser des informations par répétition</p> |
|
</label> |
|
</div> |
|
|
|
<div class="relative"> |
|
<input type="radio" id="typeQuiz" name="contentType" value="quiz" class="peer absolute opacity-0"> |
|
<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"> |
|
<div class="w-12 h-12 rounded-full bg-primary-100 flex items-center justify-center mb-3"> |
|
<i class="fas fa-question text-xl text-primary-600"></i> |
|
</div> |
|
<h4 class="font-semibold text-gray-800">Quiz</h4> |
|
<p class="text-sm text-gray-600 text-center mt-2">Pour tester vos connaissances avec des QCM</p> |
|
</label> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<div class="flex items-center justify-between pt-2"> |
|
<div class="text-sm text-gray-500 italic"> |
|
<i class="fas fa-info-circle mr-1"></i> La génération peut prendre jusqu'à 1 minute |
|
</div> |
|
<button id="generateBtn" class="btn-primary flex items-center"> |
|
<span class="mr-2">Générer</span> |
|
<i class="fas fa-chevron-right"></i> |
|
</button> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
|
|
<div id="loading" class="hidden"> |
|
<div class="bg-white rounded-xl shadow-lg p-8 text-center"> |
|
<div class="flex flex-col items-center justify-center space-y-4"> |
|
<div class="relative w-24 h-24"> |
|
<div class="absolute inset-0 border-4 border-primary-100 border-t-primary-500 rounded-full animate-spin"></div> |
|
<div class="absolute inset-0 flex items-center justify-center"> |
|
<i class="fas fa-lightbulb text-2xl text-primary-500 animate-pulse"></i> |
|
</div> |
|
</div> |
|
<h3 class="text-xl font-semibold text-gray-800">Création en cours...</h3> |
|
<p class="text-gray-600">Nous élaborons votre contenu d'apprentissage personnalisé</p> |
|
|
|
<div class="w-full max-w-md mt-4"> |
|
<div class="progress-bar-container"> |
|
<div id="progressBar" class="progress-bar" style="width: 0%"></div> |
|
</div> |
|
<div id="loadingSteps" class="mt-8 text-left"> |
|
<div class="flex items-center mb-3"> |
|
<div class="w-6 h-6 rounded-full bg-primary-500 flex items-center justify-center mr-3"> |
|
<i class="fas fa-check text-white text-xs"></i> |
|
</div> |
|
<span class="text-sm text-gray-700">Analyse du sujet</span> |
|
</div> |
|
<div class="flex items-center mb-3"> |
|
<div id="step2" class="w-6 h-6 rounded-full bg-gray-200 flex items-center justify-center mr-3"> |
|
<i class="fas fa-spinner text-white text-xs animate-spin"></i> |
|
</div> |
|
<span class="text-sm text-gray-500">Recherche d'informations</span> |
|
</div> |
|
<div class="flex items-center mb-3"> |
|
<div id="step3" class="w-6 h-6 rounded-full bg-gray-200 flex items-center justify-center mr-3"> |
|
<i class="fas fa-hourglass text-white text-xs"></i> |
|
</div> |
|
<span class="text-sm text-gray-500">Création du contenu</span> |
|
</div> |
|
<div class="flex items-center"> |
|
<div id="step4" class="w-6 h-6 rounded-full bg-gray-200 flex items-center justify-center mr-3"> |
|
<i class="fas fa-hourglass text-white text-xs"></i> |
|
</div> |
|
<span class="text-sm text-gray-500">Finalisation</span> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
|
|
<div id="flashcardsContainer" class="mt-8 hidden"> |
|
|
|
</div> |
|
|
|
|
|
<div id="quizContainer" class="mt-8 hidden"> |
|
|
|
</div> |
|
</div> |
|
</main> |
|
|
|
<footer class="bg-gray-900 text-white py-8 mt-20 hidden md:block"> |
|
<div class="container mx-auto px-4"> |
|
<div class="flex flex-col md:flex-row justify-between items-center"> |
|
<div class="mb-4 md:mb-0"> |
|
<h2 class="text-xl font-bold flex items-center"> |
|
<i class="fas fa-brain mr-2"></i> Mémorisation Facile |
|
</h2> |
|
<p class="text-gray-400 text-sm mt-2">Votre outil d'apprentissage intelligent</p> |
|
</div> |
|
<div class="flex space-x-4"> |
|
<a href="#" class="text-gray-400 hover:text-white transition-colors"><i class="fab fa-twitter"></i></a> |
|
<a href="#" class="text-gray-400 hover:text-white transition-colors"><i class="fab fa-facebook"></i></a> |
|
<a href="#" class="text-gray-400 hover:text-white transition-colors"><i class="fab fa-instagram"></i></a> |
|
<a href="#" class="text-gray-400 hover:text-white transition-colors"><i class="fab fa-youtube"></i></a> |
|
</div> |
|
</div> |
|
<div class="mt-8 border-t border-gray-800 pt-6 text-sm text-gray-400 text-center"> |
|
© 2025 Mémorisation Facile. Tous droits réservés. |
|
</div> |
|
</div> |
|
</footer> |
|
|
|
|
|
</div> |
|
|
|
<script> |
|
const generateBtn = document.getElementById('generateBtn'); |
|
const loadingIndicator = document.getElementById('loading'); |
|
const flashcardsContainer = document.getElementById('flashcardsContainer'); |
|
const quizContainer = document.getElementById('quizContainer'); |
|
const topicInput = document.getElementById('topic'); |
|
const progressBar = document.getElementById('progressBar'); |
|
const themeToggle = document.getElementById('themeToggle'); |
|
const step2 = document.getElementById('step2'); |
|
const step3 = document.getElementById('step3'); |
|
const step4 = document.getElementById('step4'); |
|
|
|
|
|
themeToggle.addEventListener('click', function() { |
|
document.body.classList.toggle('dark-mode'); |
|
const icon = this.querySelector('i'); |
|
if (icon.classList.contains('fa-moon')) { |
|
icon.classList.remove('fa-moon'); |
|
icon.classList.add('fa-sun'); |
|
} else { |
|
icon.classList.remove('fa-sun'); |
|
icon.classList.add('fa-moon'); |
|
} |
|
}); |
|
|
|
|
|
function simulateLoading() { |
|
let progress = 0; |
|
const interval = setInterval(() => { |
|
progress += 1; |
|
progressBar.style.width = `${progress}%`; |
|
|
|
if (progress === 25) { |
|
step2.classList.remove('bg-gray-200'); |
|
step2.classList.add('bg-primary-500'); |
|
step2.innerHTML = '<i class="fas fa-check text-white text-xs"></i>'; |
|
} else if (progress === 60) { |
|
step3.classList.remove('bg-gray-200'); |
|
step3.classList.add('bg-primary-500'); |
|
step3.innerHTML = '<i class="fas fa-check text-white text-xs"></i>'; |
|
step4.innerHTML = '<i class="fas fa-spinner text-white text-xs animate-spin"></i>'; |
|
} else if (progress === 95) { |
|
step4.classList.remove('bg-gray-200'); |
|
step4.classList.add('bg-primary-500'); |
|
step4.innerHTML = '<i class="fas fa-check text-white text-xs"></i>'; |
|
} |
|
|
|
if (progress >= 100) { |
|
clearInterval(interval); |
|
} |
|
}, 50); |
|
|
|
return interval; |
|
} |
|
|
|
|
|
function createConfetti() { |
|
const confettiCount = 100; |
|
const colors = ['#0ea5e9', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6']; |
|
|
|
for (let i = 0; i < confettiCount; i++) { |
|
const confetti = document.createElement('div'); |
|
confetti.className = 'confetti'; |
|
confetti.style.left = `${Math.random() * 100}vw`; |
|
confetti.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)]; |
|
confetti.style.width = `${Math.random() * 10 + 5}px`; |
|
confetti.style.height = `${Math.random() * 10 + 5}px`; |
|
confetti.style.animationDuration = `${Math.random() * 3 + 2}s`; |
|
document.body.appendChild(confetti); |
|
|
|
setTimeout(() => { |
|
confetti.remove(); |
|
}, 5000); |
|
} |
|
} |
|
|
|
|
|
function flipCard(card) { |
|
card.classList.toggle('flipped'); |
|
} |
|
|
|
generateBtn.addEventListener('click', function() { |
|
const topic = topicInput.value.trim(); |
|
if (!topic) { |
|
|
|
topicInput.classList.add('border-red-500'); |
|
topicInput.classList.add('animate-bounce'); |
|
setTimeout(() => { |
|
topicInput.classList.remove('animate-bounce'); |
|
topicInput.classList.remove('border-red-500'); |
|
}, 1000); |
|
|
|
|
|
const errorMsg = document.createElement('div'); |
|
errorMsg.className = 'text-red-500 text-sm mt-1 ml-2'; |
|
errorMsg.textContent = 'Veuillez entrer un sujet'; |
|
topicInput.parentElement.appendChild(errorMsg); |
|
setTimeout(() => { |
|
errorMsg.remove(); |
|
}, 3000); |
|
|
|
return; |
|
} |
|
|
|
const contentType = document.querySelector('input[name="contentType"]:checked').value; |
|
|
|
|
|
loadingIndicator.classList.remove('hidden'); |
|
flashcardsContainer.classList.add('hidden'); |
|
quizContainer.classList.add('hidden'); |
|
flashcardsContainer.innerHTML = ''; |
|
quizContainer.innerHTML = ''; |
|
|
|
|
|
const loadingInterval = simulateLoading(); |
|
|
|
|
|
fetch('/generate', { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json', |
|
}, |
|
body: JSON.stringify({ topic, type: contentType }), |
|
}) |
|
.then(response => { |
|
if (!response.ok) { |
|
throw new Error(`Erreur HTTP: ${response.status}`); |
|
} |
|
return response.json(); |
|
}) |
|
.then(data => { |
|
|
|
setTimeout(() => { |
|
clearInterval(loadingInterval); |
|
progressBar.style.width = '100%'; |
|
|
|
setTimeout(() => { |
|
loadingIndicator.classList.add('hidden'); |
|
|
|
if (data.error) { |
|
|
|
const errorContainer = document.createElement('div'); |
|
errorContainer.className = 'bg-red-50 border-l-4 border-red-500 p-4 rounded-md mt-4'; |
|
errorContainer.innerHTML = ` |
|
<div class="flex"> |
|
<div class="flex-shrink-0"> |
|
<i class="fas fa-exclamation-circle text-red-500"></i> |
|
</div> |
|
<div class="ml-3"> |
|
<p class="text-sm text-red-700"> |
|
${data.error} |
|
</p> |
|
</div> |
|
</div> |
|
`; |
|
document.querySelector('.max-w-3xl').appendChild(errorContainer); |
|
return; |
|
} |
|
|
|
if (contentType === 'flashcards' && data.flashcards) { |
|
flashcardsContainer.classList.remove('hidden'); |
|
displayFlashcards(data.flashcards); |
|
|
|
createConfetti(); |
|
} else if (contentType === 'quiz' && data.quiz) { |
|
quizContainer.classList.remove('hidden'); |
|
displayQuiz(data.quiz); |
|
|
|
createConfetti(); |
|
} else { |
|
|
|
const errorContainer = document.createElement('div'); |
|
errorContainer.className = 'bg-red-50 border-l-4 border-red-500 p-4 rounded-md mt-4'; |
|
errorContainer.innerHTML = ` |
|
<div class="flex"> |
|
<div class="flex-shrink-0"> |
|
<i class="fas fa-exclamation-circle text-red-500"></i> |
|
</div> |
|
<div class="ml-3"> |
|
<p class="text-sm text-red-700"> |
|
Aucune donnée reçue ou format incorrect. |
|
</p> |
|
</div> |
|
</div> |
|
`; |
|
document.querySelector('.max-w-3xl').appendChild(errorContainer); |
|
} |
|
}, 500); |
|
}, 2000); |
|
}) |
|
.catch(error => { |
|
clearInterval(loadingInterval); |
|
loadingIndicator.classList.add('hidden'); |
|
console.error('Erreur lors de la génération:', error); |
|
|
|
|
|
const errorContainer = document.createElement('div'); |
|
errorContainer.className = 'bg-red-50 border-l-4 border-red-500 p-4 rounded-md mt-4'; |
|
errorContainer.innerHTML = ` |
|
<div class="flex"> |
|
<div class="flex-shrink-0"> |
|
<i class="fas fa-exclamation-circle text-red-500"></i> |
|
</div> |
|
<div class="ml-3"> |
|
<p class="text-sm text-red-700"> |
|
Erreur lors de la génération: ${error.message}. |
|
</p> |
|
</div> |
|
</div> |
|
`; |
|
document.querySelector('.max-w-3xl').appendChild(errorContainer); |
|
}); |
|
}); |
|
|
|
function displayFlashcards(flashcards) { |
|
const header = document.createElement('div'); |
|
header.className = 'mb-8 text-center'; |
|
header.innerHTML = ` |
|
<h2 class="text-3xl font-bold text-gray-800 mb-2">Vos Flashcards (${flashcards.length})</h2> |
|
<p >Cliquez sur une carte pour la retourner et voir la réponse.</p> |
|
<p class="text-gray-600"> |
|
<i class="far fa-lightbulb mr-1"></i> Astuce : Essayez de répondre mentalement avant de retourner la carte |
|
</p> |
|
<p><div class="flex items-center justify-center space-x-4 mt-6"> |
|
</div></p> |
|
|
|
`; |
|
flashcardsContainer.appendChild(header); |
|
|
|
const flashcardsGrid = document.createElement('div'); |
|
flashcardsGrid.className = 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6'; |
|
flashcardsContainer.appendChild(flashcardsGrid); |
|
|
|
flashcards.forEach((card, index) => { |
|
const cardElement = document.createElement('div'); |
|
cardElement.className = 'flashcard cursor-pointer'; |
|
cardElement.onclick = function() { flipCard(this); }; |
|
cardElement.innerHTML = ` |
|
<div class="flashcard-inner"> |
|
<div class="flashcard-front"> |
|
<div class="w-full"> |
|
<div class="absolute top-2 left-2 text-xs text-gray-400">#${index + 1}</div> |
|
<h3 class="text-lg font-semibold mb-2 text-center">${card.question}</h3> |
|
<div class="text-center mt-4"> |
|
<span class="text-xs text-gray-500">Cliquez pour voir la réponse</span> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<div class="flashcard-back"> |
|
<div class="w-full"> |
|
<div class="absolute top-2 right-2 text-xs text-white opacity-70">#${index + 1}</div> |
|
<div class="text-center"> |
|
<p class="font-medium">${card.answer}</p> |
|
</div> |
|
<div class="absolute bottom-2 right-2"> |
|
<span class="text-xs text-white opacity-70">Cliquez pour retourner</span> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
`; |
|
flashcardsGrid.appendChild(cardElement); |
|
}); |
|
|
|
|
|
const controls = document.createElement('div'); |
|
controls.className = 'mt-10 flex flex-col items-center justify-center'; |
|
controls.innerHTML = ` |
|
<div class="flex items-center space-x-4 mb-6"> |
|
<button class="px-4 py-2 bg-primary-100 hover:bg-primary-200 text-primary-700 rounded-md transition duration-300 flex items-center"> |
|
<i class="fas fa-redo-alt mr-2"></i> Recommencer |
|
</button> |
|
<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"> |
|
<i class="fas fa-plus mr-2"></i> Nouveau sujet |
|
</button> |
|
</div> |
|
|
|
`; |
|
flashcardsContainer.appendChild(controls); |
|
|
|
|
|
document.getElementById('printBtn').addEventListener('click', function() { |
|
window.print(); |
|
}); |
|
|
|
document.getElementById('saveBtn').addEventListener('click', function() { |
|
alert('Flashcards sauvegardées !'); |
|
}); |
|
|
|
document.getElementById('shareBtn').addEventListener('click', function() { |
|
alert('Lien de partage copié dans le presse-papiers !'); |
|
}); |
|
|
|
document.getElementById('newTopicBtn').addEventListener('click', function() { |
|
window.scrollTo({ |
|
top: 0, |
|
behavior: 'smooth' |
|
}); |
|
topicInput.focus(); |
|
}); |
|
} |
|
|
|
function displayQuiz(quizQuestions) { |
|
const header = document.createElement('div'); |
|
header.className = 'mb-8 text-center'; |
|
header.innerHTML = ` |
|
<h2 class="text-3xl font-bold text-gray-800 mb-2">Votre Quiz (${quizQuestions.length} questions)</h2> |
|
<p class="text-gray-600">Testez vos connaissances en répondant aux questions</p> |
|
<div class="flex items-center justify-center mt-6"> |
|
<div class="bg-white px-4 py-2 rounded-full shadow-sm flex items-center"> |
|
<span class="text-primary-700 font-medium">Score: </span> |
|
<span id="score" class="ml-1 text-primary-700 font-bold">0</span> |
|
<span class="mx-1 text-gray-400">/</span> |
|
<span class="text-gray-600">${quizQuestions.length}</span> |
|
</div> |
|
</div> |
|
`; |
|
quizContainer.appendChild(header); |
|
|
|
|
|
const questionsContainer = document.createElement('div'); |
|
questionsContainer.className = 'space-y-8'; |
|
quizContainer.appendChild(questionsContainer); |
|
|
|
|
|
let currentScore = 0; |
|
|
|
quizQuestions.forEach((question, qIndex) => { |
|
const questionElement = document.createElement('div'); |
|
questionElement.className = 'bg-white rounded-xl shadow-md p-6 transition-all duration-300'; |
|
questionElement.setAttribute('id', `question-${qIndex}`); |
|
|
|
let optionsHtml = ''; |
|
const safeCorrectAnswer = question.correctAnswer.replace(/"/g, '"'); |
|
|
|
question.options.forEach((option, oIndex) => { |
|
optionsHtml += ` |
|
<div class="quiz-option mb-3" id="option-${qIndex}-${oIndex}"> |
|
<input type="radio" id="q${qIndex}-o${oIndex}" name="question-${qIndex}" value="${option}" data-correct="${safeCorrectAnswer}"> |
|
<label for="q${qIndex}-o${oIndex}" class="group"> |
|
${option} |
|
<span class="hidden success-icon absolute right-4 text-green-500"> |
|
<i class="fas fa-check-circle"></i> |
|
</span> |
|
<span class="hidden error-icon absolute right-4 text-red-500"> |
|
<i class="fas fa-times-circle"></i> |
|
</span> |
|
</label> |
|
</div> |
|
`; |
|
}); |
|
|
|
questionElement.innerHTML = ` |
|
<div class="flex items-center justify-between mb-4"> |
|
<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> |
|
<span class="text-gray-400 text-sm"> |
|
<i class="far fa-lightbulb"></i> |
|
</span> |
|
</div> |
|
<h3 class="text-xl font-medium text-gray-800 mb-4">${question.question}</h3> |
|
<div class="options mt-5"> |
|
${optionsHtml} |
|
</div> |
|
<div class="explanation hidden mt-6 p-4 bg-blue-50 border border-blue-100 rounded-lg" id="explanation-${qIndex}"> |
|
<div class="flex items-start"> |
|
<div class="flex-shrink-0 mt-0.5"> |
|
<i class="fas fa-info-circle text-blue-500"></i> |
|
</div> |
|
<div class="ml-3"> |
|
<h4 class="text-sm font-medium text-blue-800">Explication</h4> |
|
<div class="mt-1 text-sm text-blue-700">${question.explanation}</div> |
|
</div> |
|
</div> |
|
</div> |
|
`; |
|
questionsContainer.appendChild(questionElement); |
|
|
|
|
|
const options = questionElement.querySelectorAll('input[type="radio"]'); |
|
options.forEach((option) => { |
|
option.addEventListener('change', function() { |
|
const optionId = this.id; |
|
const [_, qIdx, oIdx] = optionId.match(/q(\d+)-o(\d+)/); |
|
const selected = this.value; |
|
const correct = this.getAttribute('data-correct'); |
|
const explanationElement = document.getElementById(`explanation-${qIdx}`); |
|
|
|
|
|
let delay = 0; |
|
if (selected === correct) { |
|
|
|
document.getElementById(`option-${qIdx}-${oIdx}`).classList.add('correct'); |
|
currentScore++; |
|
document.getElementById('score').textContent = currentScore; |
|
|
|
|
|
const successIcon = this.nextElementSibling.querySelector('.success-icon'); |
|
successIcon.classList.remove('hidden'); |
|
delay = 2000; |
|
} else { |
|
|
|
document.getElementById(`option-${qIdx}-${oIdx}`).classList.add('incorrect'); |
|
|
|
|
|
const errorIcon = this.nextElementSibling.querySelector('.error-icon'); |
|
errorIcon.classList.remove('hidden'); |
|
|
|
|
|
options.forEach((opt, idx) => { |
|
if (opt.value === correct) { |
|
document.getElementById(`option-${qIdx}-${idx}`).classList.add('correct'); |
|
const successIcon = opt.nextElementSibling.querySelector('.success-icon'); |
|
successIcon.classList.remove('hidden'); |
|
} |
|
}); |
|
delay = 5000; |
|
} |
|
|
|
|
|
options.forEach((opt) => { |
|
if (opt !== this) { |
|
opt.disabled = true; |
|
} |
|
}); |
|
|
|
|
|
explanationElement.classList.remove('hidden'); |
|
|
|
|
|
setTimeout(() => { |
|
const nextQuestion = document.getElementById(`question-${parseInt(qIdx) + 1}`); |
|
if (nextQuestion) { |
|
window.scrollTo({ |
|
top: nextQuestion.offsetTop - 20, |
|
behavior: 'smooth' |
|
}); |
|
} else { |
|
|
|
if (parseInt(qIdx) === quizQuestions.length - 1) { |
|
displayQuizResults(currentScore, quizQuestions.length); |
|
} |
|
} |
|
}, delay); |
|
}); |
|
}); |
|
}); |
|
} |
|
|
|
function displayQuizResults(score, total) { |
|
const percentage = (score / total) * 100; |
|
let resultClass, resultIcon, resultMessage; |
|
|
|
if (percentage >= 80) { |
|
resultClass = 'bg-green-50 border-green-500 text-green-800'; |
|
resultIcon = '<i class="fas fa-trophy text-3xl text-yellow-500 mb-3"></i>'; |
|
resultMessage = 'Excellent ! Vous maîtrisez ce sujet.'; |
|
} else if (percentage >= 60) { |
|
resultClass = 'bg-blue-50 border-blue-500 text-blue-800'; |
|
resultIcon = '<i class="fas fa-medal text-3xl text-blue-500 mb-3"></i>'; |
|
resultMessage = 'Bon travail ! Continuez vos efforts.'; |
|
} else { |
|
resultClass = 'bg-red-50 border-red-500 text-red-800'; |
|
resultIcon = '<i class="fas fa-book-open text-3xl text-red-500 mb-3"></i>'; |
|
resultMessage = 'Continuez à étudier pour améliorer vos connaissances.'; |
|
} |
|
|
|
const resultsElement = document.createElement('div'); |
|
resultsElement.className = `mt-10 p-6 rounded-xl shadow-lg border-l-4 ${resultClass} text-center`; |
|
resultsElement.innerHTML = ` |
|
<div class="flex flex-col items-center"> |
|
${resultIcon} |
|
<h3 class="text-2xl font-bold mb-2">Résultat final: ${score}/${total}</h3> |
|
<p class="mb-4">${resultMessage}</p> |
|
<div class="w-full max-w-xs bg-gray-200 rounded-full h-4 mb-4"> |
|
<div class="h-4 rounded-full ${percentage >= 80 ? 'bg-green-500' : percentage >= 60 ? 'bg-blue-500' : 'bg-red-500'}" style="width: ${percentage}%"></div> |
|
</div> |
|
<div class="flex space-x-4 mt-6"> |
|
<button id="retryQuizBtn" class="btn-secondary text-sm"> |
|
<i class="fas fa-redo mr-2"></i> Réessayer |
|
</button> |
|
<button id="newQuizBtn" class="btn-primary text-sm"> |
|
<i class="fas fa-plus mr-2"></i> Nouveau quiz |
|
</button> |
|
</div> |
|
</div> |
|
`; |
|
quizContainer.appendChild(resultsElement); |
|
|
|
|
|
if (percentage >= 70) { |
|
createConfetti(); |
|
} |
|
|
|
|
|
document.getElementById('retryQuizBtn').addEventListener('click', function() { |
|
const radios = document.querySelectorAll('input[type="radio"]'); |
|
radios.forEach(radio => { |
|
radio.checked = false; |
|
radio.disabled = false; |
|
}); |
|
|
|
const options = document.querySelectorAll('.quiz-option'); |
|
options.forEach(option => { |
|
option.classList.remove('correct', 'incorrect'); |
|
}); |
|
|
|
const explanations = document.querySelectorAll('.explanation'); |
|
explanations.forEach(exp => { |
|
exp.classList.add('hidden'); |
|
}); |
|
|
|
const icons = document.querySelectorAll('.success-icon, .error-icon'); |
|
icons.forEach(icon => { |
|
icon.classList.add('hidden'); |
|
}); |
|
|
|
resultsElement.remove(); |
|
document.getElementById('score').textContent = '0'; |
|
|
|
window.scrollTo({ |
|
top: quizContainer.offsetTop, |
|
behavior: 'smooth' |
|
}); |
|
}); |
|
|
|
document.getElementById('newQuizBtn').addEventListener('click', function() { |
|
window.scrollTo({ |
|
top: 0, |
|
behavior: 'smooth' |
|
}); |
|
topicInput.focus(); |
|
}); |
|
} |
|
|
|
|
|
window.addEventListener('load', () => { |
|
topicInput.focus(); |
|
}); |
|
</script> |
|
|
|
</body> |
|
</html> |
|
|