body {
font-family: ‘Segoe UI’, Tahoma, Geneva, Verdana, sans-serif;
max-width: 100%;
margin: 0 auto;
padding: 20px;
background-color: #f9f9f9;
}
h1, h2, h3 {
color: #2c3e50;
}
.container {
background-color: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
max-width: 100%;
margin: 0 auto;
}
.subscription-form {
background-color: #e8f4f8;
padding: 20px;
border-radius: 8px;
margin-bottom: 30px;
}
.exercise-container {
display: none;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
input, select {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
}
button {
background-color: #3498db;
color: white;
border: none;
padding: 12px 20px;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
transition: background-color 0.3s;
}
button:hover {
background-color: #2980b9;
}
.question {
margin-bottom: 25px;
padding: 20px;
background-color: #f8f9fa;
border-radius: 8px;
border-left: 4px solid #3498db;
}
.question-number {
font-weight: bold;
color: #2c3e50;
margin-bottom: 10px;
}
.question-text {
font-size: 16px;
margin-bottom: 15px;
line-height: 1.5;
}
.options {
display: grid;
gap: 10px;
}
.option {
display: flex;
align-items: center;
padding: 10px;
background-color: white;
border: 2px solid #e9ecef;
border-radius: 6px;
cursor: pointer;
transition: all 0.3s;
}
.option:hover {
border-color: #3498db;
background-color: #f0f8ff;
}
.option input[type=”radio”] {
margin-right: 10px;
width: auto;
}
.option.correct {
background-color: #d4edda;
border-color: #28a745;
}
.option.incorrect {
background-color: #f8d7da;
border-color: #dc3545;
}
.option.correct-answer {
background-color: #d1ecf1;
border-color: #17a2b8;
}
.result {
margin-top: 30px;
padding: 20px;
background-color: #eafaf1;
border-radius: 8px;
display: none;
}
.certificate {
text-align: center;
margin-top: 30px;
padding: 20px;
border: 2px solid #2c3e50;
border-radius: 8px;
display: none;
}
.error {
color: red;
font-size: 14px;
}
.progress-bar {
width: 100%;
height: 20px;
background-color: #e9ecef;
border-radius: 10px;
margin-bottom: 20px;
}
.progress-fill {
height: 100%;
background-color: #28a745;
border-radius: 10px;
transition: width 0.3s;
width: 0%;
}
#certificatePreview {
position: relative;
width: 100%;
height: 450px;
background-color: #fff;
border: 10px solid transparent;
border-image: linear-gradient(45deg, #3498db, #2980b9, #1abc9c, #16a085, #27ae60) 1;
box-sizing: border-box;
overflow: hidden;
margin-bottom: 20px;
}
.certificate-background {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0.07;
z-index: 0;
background-position: center;
background-repeat: no-repeat;
background-size: 70%;
}
.certificate-content {
position: relative;
z-index: 1;
padding: 20px;
width: 100%;
height: 100%;
box-sizing: border-box;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.certificate-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.certificate-title {
flex-grow: 1;
text-align: center;
}
.certificate-logo {
width: 120px;
height: 60px;
background-color: #3498db;
border-radius: 5px;
}
.certificate-footer {
display: flex;
justify-content: space-between;
align-items: flex-end;
}
.certificate-qr {
width: 120px;
height: 120px;
display: flex;
justify-content: center;
align-items: center;
background-color: #f9f9f9;
border: 1px solid #ddd;
}
.certificate-qr img {
max-width: 100%;
max-height: 100%;
}
.certificate-signature {
flex-grow: 1;
text-align: center;
}
.triangle-pattern {
position: absolute;
width: 150px;
height: 120px;
}
.triangle-pattern.top-right {
top: 0;
right: 0;
}
.triangle-pattern.bottom-left {
bottom: 0;
left: 0;
}
.loading {
display: none;
margin-top: 15px;
font-style: italic;
color: #666;
}
.instruction-box {
background-color: #fff3cd;
border: 1px solid #ffeaa7;
border-radius: 8px;
padding: 15px;
margin-bottom: 25px;
}
.theme-section {
margin-bottom: 30px;
padding: 20px;
background-color: #f1f3f4;
border-radius: 8px;
border-left: 5px solid #e74c3c;
}
.theme-title {
color: #e74c3c;
font-size: 18px;
font-weight: bold;
margin-bottom: 15px;
}
Inscrivez-vous pour commencer l’exercice
Veuillez vous abonner et remplir vos informations pour accéder à l’exercice sur le futur, les conditions avec “si” et les structures “quand + futur”.
Quiz sur le Futur et les Structures Conditionnelles
Instructions: Choisissez la bonne réponse pour chaque question. Cet exercice porte sur :
- Le futur simple et le futur antérieur
- Les conditions avec “si” (présent/futur, imparfait/conditionnel)
- Les structures “quand + futur”
- La conjugaison des verbes au futur
Résultats
Certificat de réussite
Certificat d’Excellence
Maîtrise du Futur et Structures Conditionnelles
Ce certificat est décerné à
pour avoir complété avec succès l’exercice sur
le futur et les structures conditionnelles en français
avec un score de
Date:
document.addEventListener(‘DOMContentLoaded’, function() {
// S’assurer que jsPDF est disponible
if (typeof window.jspdf === ‘undefined’) {
window.jspdf = window.jsPDF;
}
// Références aux éléments DOM
const subscriptionForm = document.getElementById(‘subscriptionForm’);
const exerciseContainer = document.getElementById(‘exerciseContainer’);
const startButton = document.getElementById(‘startButton’);
const verifyButton = document.getElementById(‘verifyButton’);
const resultContainer = document.getElementById(‘resultContainer’);
const resultText = document.getElementById(‘resultText’);
const mistakesContainer = document.getElementById(‘mistakesContainer’);
const showCertificateButton = document.getElementById(‘showCertificateButton’);
const certificateContainer = document.getElementById(‘certificateContainer’);
const downloadCertificateButton = document.getElementById(‘downloadCertificateButton’);
const pdfLoading = document.getElementById(‘pdfLoading’);
const progressFill = document.getElementById(‘progressFill’);
// Informations de l’utilisateur
let userData = {
prenom: ”,
nom: ”,
email: ”,
score: 0
};
// Démarrer l’exercice
startButton.addEventListener(‘click’, function() {
// Valider le formulaire
const prenom = document.getElementById(‘prenom’).value.trim();
const nom = document.getElementById(‘nom’).value.trim();
const email = document.getElementById(‘email’).value.trim();
const subscribe = document.getElementById(‘subscribe’).checked;
// Réinitialiser les erreurs
document.getElementById(‘prenomError’).textContent = ”;
document.getElementById(‘nomError’).textContent = ”;
document.getElementById(‘emailError’).textContent = ”;
document.getElementById(‘subscribeError’).textContent = ”;
let isValid = true;
// Vérification des champs
if (!prenom) {
document.getElementById(‘prenomError’).textContent = ‘Veuillez entrer votre prénom’;
isValid = false;
}
if (!nom) {
document.getElementById(‘nomError’).textContent = ‘Veuillez entrer votre nom’;
isValid = false;
}
if (!email) {
document.getElementById(‘emailError’).textContent = ‘Veuillez entrer votre email’;
isValid = false;
} else if (!/^[^s@]+@[^s@]+.[^s@]+$/.test(email)) {
document.getElementById(‘emailError’).textContent = ‘Veuillez entrer un email valide’;
isValid = false;
}
if (!subscribe) {
document.getElementById(‘subscribeError’).textContent = ‘Veuillez accepter de vous abonner’;
isValid = false;
}
if (isValid) {
// Enregistrer les informations de l’utilisateur
userData.prenom = prenom;
userData.nom = nom;
userData.email = email;
// Masquer le formulaire et afficher l’exercice
subscriptionForm.style.display = ‘none’;
exerciseContainer.style.display = ‘block’;
}
});
// Mettre à jour la barre de progression
function updateProgress() {
const totalQuestions = 40;
const answeredQuestions = document.querySelectorAll(‘input[type=”radio”]:checked’).length;
const progress = (answeredQuestions / totalQuestions) * 100;
progressFill.style.width = progress + ‘%’;
}
// Écouter les changements de réponse
document.addEventListener(‘change’, function(e) {
if (e.target.type === ‘radio’) {
updateProgress();
}
});
// Vérifier les réponses
verifyButton.addEventListener(‘click’, function() {
let correctAnswers = 0;
const totalQuestions = 40;
const mistakes = [];
// Vérifier chaque question
for (let i = 1; i {
option.classList.remove(‘correct’, ‘incorrect’, ‘correct-answer’);
});
if (userAnswer === correctAnswer) {
correctAnswers++;
selectedRadio.closest(‘.option’).classList.add(‘correct’);
} else {
selectedRadio.closest(‘.option’).classList.add(‘incorrect’);
// Marquer la bonne réponse
const correctOption = questionElement.querySelector(`input[value=”${correctAnswer}”]`);
if (correctOption) {
correctOption.closest(‘.option’).classList.add(‘correct-answer’);
}
// Ajouter à la liste des erreurs
const questionText = questionElement.querySelector(‘.question-text’).textContent;
mistakes.push({
number: i,
question: questionText,
userAnswer: selectedRadio.closest(‘.option’).textContent.trim(),
correctAnswer: correctOption ? correctOption.closest(‘.option’).textContent.trim() : ‘N/A’
});
}
}
}
// Calculer le score
const score = Math.round((correctAnswers / totalQuestions) * 100);
userData.score = score;
// Afficher les résultats
resultContainer.style.display = ‘block’;
resultText.innerHTML = `Vous avez obtenu un score de ${score}% (${correctAnswers} réponses correctes sur ${totalQuestions}).`;
// Afficher les erreurs
mistakesContainer.innerHTML = ”;
if (mistakes.length > 0) {
const mistakesTitle = document.createElement(‘h4’);
mistakesTitle.textContent = ‘Questions à revoir:’;
mistakesContainer.appendChild(mistakesTitle);
const mistakesList = document.createElement(‘div’);
mistakes.forEach(mistake => {
const mistakeItem = document.createElement(‘div’);
mistakeItem.style.marginBottom = ’15px’;
mistakeItem.style.padding = ’10px’;
mistakeItem.style.backgroundColor = ‘#fff3cd’;
mistakeItem.style.border = ‘1px solid #ffeaa7’;
mistakeItem.style.borderRadius = ‘5px’;
mistakeItem.innerHTML = `
Question ${mistake.number}:
${mistake.question}
Votre réponse: ${mistake.userAnswer}
Réponse correcte: ${mistake.correctAnswer}
`;
mistakesList.appendChild(mistakeItem);
});
mistakesContainer.appendChild(mistakesList);
}
// Afficher le bouton du certificat si le score est supérieur à 70%
if (score >= 70) {
showCertificateButton.style.display = ‘block’;
} else {
showCertificateButton.style.display = ‘none’;
}
// Faire défiler vers les résultats
resultContainer.scrollIntoView({ behavior: ‘smooth’ });
});
// Afficher le certificat
showCertificateButton.addEventListener(‘click’, function() {
certificateContainer.style.display = ‘block’;
resultContainer.style.display = ‘none’;
// Remplir les informations du certificat
document.getElementById(‘certificateName’).textContent = `${userData.prenom} ${userData.nom}`;
document.getElementById(‘certificateScore’).textContent = `${userData.score}%`;
const today = new Date();
const options = { year: ‘numeric’, month: ‘long’, day: ‘numeric’ };
document.getElementById(‘certificateDate’).textContent = today.toLocaleDateString(‘fr-FR’, options);
// Générer un QR code
const qrValue = `Certificat: ${userData.nom} ${userData.prenom} – Score: ${userData.score}% – Exercice Futur et Conditionnels – ${today.toLocaleDateString(‘fr-FR’)}`;
try {
const qr = qrcode(0, ‘M’);
qr.addData(qrValue);
qr.make();
const qrContainer = document.querySelector(‘.certificate-qr’);
qrContainer.innerHTML = qr.createImgTag(4);
} catch (error) {
console.log(‘Erreur génération QR code:’, error);
document.querySelector(‘.certificate-qr’).innerHTML = ‘
QR Code
‘;
}
certificateContainer.scrollIntoView({ behavior: ‘smooth’ });
});
// Télécharger le certificat en PDF
downloadCertificateButton.addEventListener(‘click’, function() {
pdfLoading.style.display = ‘block’;
downloadCertificateButton.disabled = true;
setTimeout(() => {
try {
const { jsPDF } = window.jspdf;
const pdf = new jsPDF(‘landscape’, ‘mm’, ‘a4’);
// Configuration du PDF
const pageWidth = pdf.internal.pageSize.getWidth();
const pageHeight = pdf.internal.pageSize.getHeight();
// Couleurs
const primaryColor = [52, 152, 219]; // #3498db
const secondaryColor = [44, 62, 80]; // #2c3e50
const accentColor = [39, 174, 96]; // #27ae60
// Bordure décorative
pdf.setDrawColor(…primaryColor);
pdf.setLineWidth(3);
pdf.rect(10, 10, pageWidth – 20, pageHeight – 20);
pdf.setDrawColor(…accentColor);
pdf.setLineWidth(1);
pdf.rect(15, 15, pageWidth – 30, pageHeight – 30);
// Éléments décoratifs dans les coins
pdf.setFillColor(…primaryColor);
// Triangle supérieur droit
pdf.triangle(pageWidth – 50, 20, pageWidth – 20, 20, pageWidth – 20, 50);
// Triangle inférieur gauche
pdf.triangle(20, pageHeight – 50, 50, pageHeight – 20, 20, pageHeight – 20);
// Logo (rectangle simple)
pdf.setFillColor(…primaryColor);
pdf.rect(25, 25, 40, 20, ‘F’);
pdf.setTextColor(255, 255, 255);
pdf.setFontSize(12);
pdf.setFont(‘helvetica’, ‘bold’);
pdf.text(‘AFL’, 45, 37, { align: ‘center’ });
// Titre principal
pdf.setTextColor(…secondaryColor);
pdf.setFontSize(28);
pdf.setFont(‘helvetica’, ‘bold’);
pdf.text(‘CERTIFICAT D’EXCELLENCE’, pageWidth / 2, 50, { align: ‘center’ });
// Sous-titre
pdf.setFontSize(18);
pdf.setFont(‘helvetica’, ‘normal’);
pdf.text(‘Maîtrise du Futur et Structures Conditionnelles’, pageWidth / 2, 65, { align: ‘center’ });
// Ligne décorative
pdf.setDrawColor(…accentColor);
pdf.setLineWidth(2);
pdf.line(pageWidth / 2 – 80, 75, pageWidth / 2 + 80, 75);
// Texte “Ce certificat est décerné à”
pdf.setFontSize(14);
pdf.setTextColor(…secondaryColor);
pdf.text(‘Ce certificat est décerné à’, pageWidth / 2, 95, { align: ‘center’ });
// Nom de l’utilisateur
pdf.setFontSize(24);
pdf.setFont(‘helvetica’, ‘bold’);
pdf.setTextColor(…primaryColor);
pdf.text(`${userData.prenom} ${userData.nom}`, pageWidth / 2, 115, { align: ‘center’ });
// Ligne sous le nom
pdf.setDrawColor(…primaryColor);
pdf.setLineWidth(1);
const nameWidth = pdf.getTextWidth(`${userData.prenom} ${userData.nom}`);
pdf.line((pageWidth – nameWidth) / 2, 120, (pageWidth + nameWidth) / 2, 120);
// Description du certificat
pdf.setFontSize(14);
pdf.setTextColor(…secondaryColor);
pdf.setFont(‘helvetica’, ‘normal’);
pdf.text(‘pour avoir complété avec succès l’exercice sur’, pageWidth / 2, 140, { align: ‘center’ });
pdf.text(‘le futur et les structures conditionnelles en français’, pageWidth / 2, 155, { align: ‘center’ });
// Score
pdf.setFontSize(16);
pdf.setFont(‘helvetica’, ‘bold’);
pdf.setTextColor(…accentColor);
pdf.text(`avec un score de ${userData.score}%`, pageWidth / 2, 175, { align: ‘center’ });
// Date
pdf.setFontSize(12);
pdf.setTextColor(…secondaryColor);
pdf.setFont(‘helvetica’, ‘normal’);
const today = new Date();
const options = { year: ‘numeric’, month: ‘long’, day: ‘numeric’ };
pdf.text(`Date: ${today.toLocaleDateString(‘fr-FR’, options)}`, pageWidth / 2, 195, { align: ‘center’ });
// Signature
pdf.setFontSize(12);
pdf.text(‘Académie Française de Langue’, pageWidth / 2, pageHeight – 40, { align: ‘center’ });
// Ligne de signature
pdf.setDrawColor(…secondaryColor);
pdf.setLineWidth(0.5);
pdf.line(pageWidth / 2 – 40, pageHeight – 50, pageWidth / 2 + 40, pageHeight – 50);
// QR Code (texte simple car difficile à générer dans PDF)
pdf.setFontSize(8);
pdf.text(‘QR Code de vérification’, 25, pageHeight – 25);
pdf.rect(25, pageHeight – 45, 20, 20);
// Numéro de certificat
const certNumber = `CERT-${Date.now().toString().slice(-6)}`;
pdf.text(`N° ${certNumber}`, pageWidth – 70, pageHeight – 25);
// Enregistrer le PDF
const fileName = `Certificat_${userData.nom}_${userData.prenom}_Futur_Conditionnels.pdf`;
pdf.save(fileName);
} catch (error) {
console.error(‘Erreur génération PDF:’, error);
alert(‘Erreur lors de la génération du PDF. Veuillez réessayer.’);
} finally {
pdfLoading.style.display = ‘none’;
downloadCertificateButton.disabled = false;
}
}, 1000);
});
// Fonction pour créer un triangle dans le PDF
if (typeof window.jspdf !== ‘undefined’) {
window.jspdf.jsPDF.API.triangle = function(x1, y1, x2, y2, x3, y3, style) {
this.lines([[x2 – x1, y2 – y1], [x3 – x2, y3 – y2], [x1 – x3, y1 – y3]], x1, y1, [1, 1], style || null, true);
return this;
};
}
// Animation au chargement
document.body.style.opacity = ‘0’;
setTimeout(() => {
document.body.style.transition = ‘opacity 0.5s ease-in’;
document.body.style.opacity = ‘1’;
}, 100);
});