|
<!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 & Quiz</title> |
|
|
|
<script src="https://cdn.tailwindcss.com"></script> |
|
|
|
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet" /> |
|
<style> |
|
body { |
|
font-family: 'Roboto', sans-serif; |
|
} |
|
|
|
.hover-transform { |
|
transition: transform 0.3s ease, box-shadow 0.3s ease; |
|
} |
|
.hover-transform:hover { |
|
transform: translateY(-4px); |
|
box-shadow: 0 8px 16px rgba(0,0,0,0.1); |
|
} |
|
|
|
.spinner { |
|
border: 4px solid rgba(0, 0, 0, 0.1); |
|
width: 3rem; |
|
height: 3rem; |
|
border-radius: 50%; |
|
border-left-color: #4f46e5; |
|
animation: spin 1s linear infinite; |
|
} |
|
@keyframes spin { |
|
to { transform: rotate(360deg); } |
|
} |
|
</style> |
|
</head> |
|
<body class="bg-gray-50"> |
|
|
|
<header class="bg-gradient-to-r from-indigo-600 to-blue-500 py-6 shadow-lg"> |
|
<h1 class="text-center text-white text-4xl font-bold">Générateur de Flashcards & Quiz</h1> |
|
</header> |
|
|
|
<main class="container mx-auto px-4 py-8"> |
|
|
|
<section class="max-w-2xl mx-auto mb-10"> |
|
<div class="bg-white rounded-xl shadow-lg p-8"> |
|
<div class="mb-6"> |
|
<label for="topic" class="block text-gray-700 text-lg font-medium mb-2">Sujet</label> |
|
<input type="text" id="topic" placeholder="Entrez un sujet..." |
|
class="w-full border border-gray-300 rounded-md p-3 focus:outline-none focus:ring-2 focus:ring-indigo-500" /> |
|
</div> |
|
<div class="mb-6"> |
|
<span class="block text-gray-700 text-lg font-medium mb-2">Type de contenu</span> |
|
<div class="flex space-x-6"> |
|
<label class="flex items-center space-x-2"> |
|
<input type="radio" name="contentType" value="flashcards" checked |
|
class="form-radio h-5 w-5 text-indigo-600" /> |
|
<span class="text-gray-800">Flashcards</span> |
|
</label> |
|
<label class="flex items-center space-x-2"> |
|
<input type="radio" name="contentType" value="quiz" |
|
class="form-radio h-5 w-5 text-indigo-600" /> |
|
<span class="text-gray-800">Quiz</span> |
|
</label> |
|
</div> |
|
</div> |
|
<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"> |
|
Générer |
|
</button> |
|
</div> |
|
</section> |
|
|
|
|
|
<section id="loading" class="hidden flex flex-col items-center justify-center my-10"> |
|
<div class="spinner mb-4"></div> |
|
<p class="text-gray-600 text-lg">Génération en cours... Patientez quelques instants.</p> |
|
</section> |
|
|
|
|
|
<section id="flashcardsContainer" class="mt-8 hidden"> |
|
<div class="mb-6 text-center"> |
|
<h2 class="text-3xl font-semibold text-gray-800">Flashcards générées</h2> |
|
<p class="text-gray-500">Cliquez sur une carte pour révéler la réponse</p> |
|
</div> |
|
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6"></div> |
|
</section> |
|
|
|
|
|
<section id="quizContainer" class="mt-8 max-w-3xl mx-auto hidden"> |
|
<div class="mb-6 text-center"> |
|
<h2 class="text-3xl font-semibold text-gray-800">Quiz généré</h2> |
|
<p class="text-gray-500">Sélectionnez une réponse pour chaque question</p> |
|
</div> |
|
</section> |
|
</main> |
|
|
|
<footer class="bg-gray-100 py-4"> |
|
<p class="text-center text-gray-500 text-sm">© 2025 Générateur de Flashcards & Quiz. Tous droits réservés.</p> |
|
</footer> |
|
|
|
<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'); |
|
|
|
generateBtn.addEventListener('click', () => { |
|
const topic = topicInput.value.trim(); |
|
if (!topic) { |
|
alert('Veuillez entrer un sujet.'); |
|
return; |
|
} |
|
|
|
const contentType = document.querySelector('input[name="contentType"]:checked').value; |
|
|
|
|
|
loadingIndicator.classList.remove('hidden'); |
|
flashcardsContainer.querySelector('.grid') && (flashcardsContainer.querySelector('.grid').innerHTML = ''); |
|
quizContainer.innerHTML = ''; |
|
flashcardsContainer.classList.add('hidden'); |
|
quizContainer.classList.add('hidden'); |
|
|
|
|
|
setTimeout(() => { |
|
loadingIndicator.classList.add('hidden'); |
|
|
|
if (contentType === 'quiz') { |
|
const data = { |
|
quiz: [ |
|
{ |
|
question: "When did World War II begin?", |
|
options: ["September 1, 1938", "September 2, 1945", "September 1, 1939", "December 7, 1941"], |
|
correctAnswer: "September 1, 1939", |
|
explanation: "World War II began on September 1, 1939, with the German invasion of Poland." |
|
}, |
|
{ |
|
question: "Which event led the United States to enter World War II?", |
|
options: ["The invasion of Poland", "The fall of France", "The attack on Pearl Harbor", "The Battle of Britain"], |
|
correctAnswer: "The attack on Pearl Harbor", |
|
explanation: "The Japanese attack on Pearl Harbor on December 7, 1941, prompted the United States to declare war." |
|
} |
|
] |
|
}; |
|
quizContainer.classList.remove('hidden'); |
|
displayQuiz(data.quiz); |
|
} else { |
|
|
|
const data = { |
|
flashcards: [ |
|
{ question: "Capital of France?", answer: "Paris" }, |
|
{ question: "Capital of Spain?", answer: "Madrid" }, |
|
{ question: "Capital of Italy?", answer: "Rome" } |
|
] |
|
}; |
|
flashcardsContainer.classList.remove('hidden'); |
|
displayFlashcards(data.flashcards); |
|
} |
|
}, 1500); |
|
}); |
|
|
|
function displayFlashcards(flashcards) { |
|
const gridContainer = flashcardsContainer.querySelector('.grid') || document.createElement('div'); |
|
if (!gridContainer.classList.contains('grid')) { |
|
gridContainer.className = 'grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6'; |
|
flashcardsContainer.appendChild(gridContainer); |
|
} |
|
gridContainer.innerHTML = ''; |
|
flashcards.forEach((card, index) => { |
|
const cardElement = document.createElement('div'); |
|
cardElement.className = 'bg-white rounded-xl shadow-lg p-6 cursor-pointer hover-transform'; |
|
cardElement.setAttribute('onclick', `toggleAnswer(${index})`); |
|
cardElement.innerHTML = ` |
|
<h3 class="text-xl font-semibold text-gray-800 mb-4">${card.question}</h3> |
|
<div id="answer-${index}" class="hidden text-gray-700 border-t border-gray-200 pt-4"> |
|
<span class="font-bold">Réponse:</span> ${card.answer} |
|
</div> |
|
`; |
|
gridContainer.appendChild(cardElement); |
|
}); |
|
} |
|
|
|
function toggleAnswer(index) { |
|
const answerElement = document.getElementById(`answer-${index}`); |
|
answerElement.classList.toggle('hidden'); |
|
} |
|
|
|
function displayQuiz(quizQuestions) { |
|
quizQuestions.forEach((question, qIndex) => { |
|
const questionCard = document.createElement('div'); |
|
questionCard.className = 'bg-white rounded-xl shadow-lg p-6 mb-6'; |
|
let optionsHtml = ''; |
|
|
|
const safeCorrectAnswer = question.correctAnswer.replace(/"/g, '"'); |
|
question.options.forEach((option, oIndex) => { |
|
optionsHtml += ` |
|
<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" |
|
id="q${qIndex}-o${oIndex}" |
|
data-correct="${safeCorrectAnswer}" |
|
onclick="selectOption(this, ${qIndex}, ${oIndex})"> |
|
${option} |
|
</div> |
|
`; |
|
}); |
|
questionCard.innerHTML = ` |
|
<h4 class="text-lg font-semibold text-gray-800 mb-4">${qIndex + 1}. ${question.question}</h4> |
|
<div class="options"> |
|
${optionsHtml} |
|
</div> |
|
<div id="explanation-${qIndex}" class="hidden mt-4 p-4 rounded-md bg-blue-50 border border-blue-200 text-blue-700 text-sm"> |
|
<strong>Explication:</strong> ${question.explanation} |
|
</div> |
|
`; |
|
quizContainer.appendChild(questionCard); |
|
}); |
|
} |
|
|
|
function selectOption(element, questionIndex, optionIndex) { |
|
const correctAnswer = element.dataset.correct; |
|
const questionOptions = quizContainer.querySelectorAll(`#q${questionIndex}-o0`)[0].parentElement.querySelectorAll('.option'); |
|
const explanationElement = document.getElementById(`explanation-${questionIndex}`); |
|
|
|
|
|
let alreadyAnswered = false; |
|
questionOptions.forEach(opt => { |
|
if (opt.classList.contains('bg-green-100') || opt.classList.contains('bg-red-100')) { |
|
alreadyAnswered = true; |
|
} |
|
}); |
|
if (alreadyAnswered) return; |
|
|
|
|
|
questionOptions.forEach(option => { |
|
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'); |
|
option.classList.add('hover:bg-gray-50'); |
|
}); |
|
|
|
|
|
element.classList.add('bg-indigo-100', 'border-indigo-300'); |
|
element.classList.remove('hover:bg-gray-50'); |
|
|
|
const selectedText = element.textContent.trim(); |
|
if (selectedText === correctAnswer) { |
|
element.classList.remove('bg-indigo-100', 'border-indigo-300'); |
|
element.classList.add('bg-green-100', 'border-green-300', 'text-green-800'); |
|
} else { |
|
element.classList.remove('bg-indigo-100', 'border-indigo-300'); |
|
element.classList.add('bg-red-100', 'border-red-300', 'text-red-800'); |
|
|
|
questionOptions.forEach(option => { |
|
if (option.textContent.trim() === correctAnswer) { |
|
option.classList.add('bg-green-100', 'border-green-300', 'text-green-800'); |
|
option.classList.remove('hover:bg-gray-50'); |
|
} |
|
}); |
|
} |
|
|
|
|
|
questionOptions.forEach(option => { |
|
option.onclick = null; |
|
option.classList.remove('cursor-pointer'); |
|
option.style.cursor = 'default'; |
|
}); |
|
|
|
|
|
explanationElement.classList.remove('hidden'); |
|
} |
|
</script> |
|
</body> |
|
</html> |
|
|