Spaces:
Running
Running
| <html lang="fr"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Auto-École Pro | Connexion</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| /* Custom animations */ | |
| .fade-in { animation: fadeIn 0.5s ease-in forwards; } | |
| @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } | |
| .slide-up { animation: slideUp 0.4s ease-out forwards; } | |
| @keyframes slideUp { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } | |
| .shake { animation: shake 0.5s linear; } | |
| @keyframes shake { | |
| 0%, 100% { transform: translateX(0); } | |
| 20%, 60% { transform: translateX(-5px); } | |
| 40%, 80% { transform: translateX(5px); } | |
| } | |
| /* Custom scrollbar */ | |
| ::-webkit-scrollbar { width: 8px; height: 8px; } | |
| ::-webkit-scrollbar-track { background: #f1f1f1; } | |
| ::-webkit-scrollbar-thumb { background: #888; border-radius: 10px; } | |
| ::-webkit-scrollbar-thumb:hover { background: #555; } | |
| /* Password toggle */ | |
| .password-toggle { right: 10px; top: 50%; transform: translateY(-50%); } | |
| /* Custom transitions */ | |
| .transition-all-300 { transition: all 0.3s ease; } | |
| /* Role specific colors */ | |
| .bg-student { background-color: #3b82f6; } | |
| .bg-monitor { background-color: #8b5cf6; } | |
| .bg-admin { background-color: #10b981; } | |
| .text-student { color: #3b82f6; } | |
| .text-monitor { color: #8b5cf6; } | |
| .text-admin { color: #10b981; } | |
| .border-student { border-color: #3b82f6; } | |
| .border-monitor { border-color: #8b5cf6; } | |
| .border-admin { border-color: #10b981; } | |
| .hover-bg-student:hover { background-color: #2563eb; } | |
| .hover-bg-monitor:hover { background-color: #7c3aed; } | |
| .hover-bg-admin:hover { background-color: #059669; } | |
| /* Pulse animation */ | |
| @keyframes pulse { | |
| 0%, 100% { transform: scale(1); } | |
| 50% { transform: scale(1.05); } | |
| } | |
| .pulse { animation: pulse 2s infinite; } | |
| /* Custom checkbox */ | |
| .custom-checkbox { | |
| appearance: none; | |
| -webkit-appearance: none; | |
| width: 20px; | |
| height: 20px; | |
| border: 2px solid #d1d5db; | |
| border-radius: 4px; | |
| outline: none; | |
| cursor: pointer; | |
| position: relative; | |
| } | |
| .custom-checkbox:checked { | |
| background-color: currentColor; | |
| border-color: currentColor; | |
| } | |
| .custom-checkbox:checked::after { | |
| content: '\f00c'; | |
| font-family: 'Font Awesome 6 Free'; | |
| font-weight: 900; | |
| position: absolute; | |
| color: white; | |
| font-size: 12px; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gradient-to-br from-blue-50 to-indigo-100 min-h-screen font-sans"> | |
| <!-- Login Container --> | |
| <div id="login-container" class="min-h-screen flex items-center justify-center p-4"> | |
| <!-- Main Login Card --> | |
| <div class="bg-white rounded-2xl shadow-2xl overflow-hidden w-full max-w-md fade-in slide-up"> | |
| <!-- Header with logo and tabs --> | |
| <div id="header-bg" class="bg-student py-8 px-8 text-center relative transition-all-300"> | |
| <div class="absolute top-4 left-4"> | |
| <img src="https://via.placeholder.com/40" alt="Logo" class="h-10 w-10 rounded-full shadow-md"> | |
| </div> | |
| <h1 class="text-3xl font-bold text-white">Auto-École Pro</h1> | |
| <p class="text-blue-100 mt-2">Plateforme de gestion des formations</p> | |
| <!-- Role Tabs --> | |
| <div class="flex mt-6 rounded-lg bg-white bg-opacity-20 p-1"> | |
| <button id="student-tab" class="flex-1 py-2 px-4 rounded-lg text-sm font-medium text-white bg-opacity-90 transition-all-300"> | |
| <i class="fas fa-user-graduate mr-2"></i> Élève | |
| </button> | |
| <button id="monitor-tab" class="flex-1 py-2 px-4 rounded-lg text-sm font-medium text-blue-100 hover:text-white transition-all-300"> | |
| <i class="fas fa-chalkboard-teacher mr-2"></i> Moniteur | |
| </button> | |
| <button id="admin-tab" class="flex-1 py-2 px-4 rounded-lg text-sm font-medium text-blue-100 hover:text-white transition-all-300"> | |
| <i class="fas fa-user-shield mr-2"></i> Admin | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Login Form --> | |
| <div class="p-8 pt-6"> | |
| <!-- Role Specific Info --> | |
| <div id="role-info" class="mb-6 p-4 bg-blue-50 rounded-lg border border-blue-100 transition-all-300"> | |
| <div id="student-info" class="flex items-start"> | |
| <i class="fas fa-user-graduate text-blue-500 mt-1 mr-3"></i> | |
| <div> | |
| <h3 class="font-medium text-blue-800">Accès Élève</h3> | |
| <p class="text-sm text-blue-600">Suivez votre progression, prenez rendez-vous et accédez à vos cours.</p> | |
| </div> | |
| </div> | |
| <div id="monitor-info" class="hidden flex items-start"> | |
| <i class="fas fa-chalkboard-teacher text-purple-500 mt-1 mr-3"></i> | |
| <div> | |
| <h3 class="font-medium text-purple-800">Accès Moniteur</h3> | |
| <p class="text-sm text-purple-600">Gérez votre planning, suivez vos élèves et enregistrez les évaluations.</p> | |
| </div> | |
| </div> | |
| <div id="admin-info" class="hidden flex items-start"> | |
| <i class="fas fa-user-shield text-green-500 mt-1 mr-3"></i> | |
| <div> | |
| <h3 class="font-medium text-green-800">Accès Administrateur</h3> | |
| <p class="text-sm text-green-600">Gérez les utilisateurs, le planning et la configuration de l'auto-école.</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Social Login Buttons --> | |
| <div class="mb-6"> | |
| <p class="text-center text-gray-500 text-sm mb-3">Ou connectez-vous avec</p> | |
| <div class="flex space-x-3"> | |
| <button class="flex-1 py-2 px-4 border border-gray-300 rounded-lg text-gray-700 font-medium hover:bg-gray-50 transition flex items-center justify-center"> | |
| <i class="fab fa-google text-red-500 mr-2"></i> Google | |
| </button> | |
| <button class="flex-1 py-2 px-4 border border-gray-300 rounded-lg text-gray-700 font-medium hover:bg-gray-50 transition flex items-center justify-center"> | |
| <i class="fab fa-facebook text-blue-600 mr-2"></i> Facebook | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Divider --> | |
| <div class="relative mb-6"> | |
| <div class="absolute inset-0 flex items-center"> | |
| <div class="w-full border-t border-gray-300"></div> | |
| </div> | |
| <div class="relative flex justify-center text-sm"> | |
| <span class="px-2 bg-white text-gray-500">Ou avec email</span> | |
| </div> | |
| </div> | |
| <!-- Email Input --> | |
| <div class="mb-5 relative"> | |
| <label for="login-email" class="block text-sm font-medium text-gray-700 mb-1">Adresse email</label> | |
| <div class="relative"> | |
| <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"> | |
| <i class="fas fa-envelope text-gray-400"></i> | |
| </div> | |
| <input id="login-email" type="email" class="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-blue-500" placeholder="email@example.com"> | |
| </div> | |
| <p id="email-error" class="mt-1 text-xs text-red-600 hidden">Veuillez entrer une adresse email valide</p> | |
| </div> | |
| <!-- Password Input --> | |
| <div class="mb-5 relative"> | |
| <label for="login-password" class="block text-sm font-medium text-gray-700 mb-1">Mot de passe</label> | |
| <div class="relative"> | |
| <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"> | |
| <i class="fas fa-lock text-gray-400"></i> | |
| </div> | |
| <input id="login-password" type="password" class="block w-full pl-10 pr-10 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-blue-500" placeholder="••••••••"> | |
| <button id="toggle-password" class="password-toggle absolute right-0 pr-3 text-gray-400 hover:text-gray-600"> | |
| <i class="fas fa-eye"></i> | |
| </button> | |
| </div> | |
| <p id="password-error" class="mt-1 text-xs text-red-600 hidden">Le mot de passe doit contenir au moins 8 caractères</p> | |
| </div> | |
| <!-- Remember Me & Forgot Password --> | |
| <div class="flex items-center justify-between mb-6"> | |
| <div class="flex items-center"> | |
| <input id="remember-me" type="checkbox" class="custom-checkbox text-blue-600 focus:ring-blue-500"> | |
| <label for="remember-me" class="ml-2 block text-sm text-gray-700">Se souvenir de moi</label> | |
| </div> | |
| <a href="#" class="text-sm text-blue-600 hover:text-blue-800" id="forgot-password">Mot de passe oublié ?</a> | |
| </div> | |
| <!-- Login Button --> | |
| <button id="login-btn" class="w-full flex justify-center items-center py-3 px-4 border border-transparent rounded-lg shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-all-300 pulse"> | |
| <span id="login-text">Connexion</span> | |
| <i id="login-spinner" class="fas fa-spinner fa-spin ml-2 hidden"></i> | |
| </button> | |
| <!-- Register Link --> | |
| <div class="mt-6 text-center text-sm"> | |
| <p class="text-gray-500">Pas encore de compte ? | |
| <a href="#" class="font-medium text-blue-600 hover:text-blue-800" id="register-link">S'inscrire</a> | |
| </p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Forgot Password Modal --> | |
| <div id="forgot-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 hidden z-50"> | |
| <div class="bg-white rounded-xl shadow-xl max-w-md w-full fade-in slide-up"> | |
| <div class="p-6"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-xl font-bold text-gray-800">Réinitialiser le mot de passe</h3> | |
| <button id="close-forgot-modal" class="text-gray-400 hover:text-gray-600"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <p class="text-gray-600 mb-4">Entrez votre adresse email pour recevoir un lien de réinitialisation.</p> | |
| <div class="mb-4"> | |
| <label for="reset-email" class="block text-sm font-medium text-gray-700 mb-1">Email</label> | |
| <input type="email" id="reset-email" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-blue-500" placeholder="email@example.com"> | |
| </div> | |
| <button id="send-reset-link" class="w-full bg-blue-600 text-white py-2 px-4 rounded-lg hover:bg-blue-700 transition"> | |
| Envoyer le lien | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Register Modal --> | |
| <div id="register-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 hidden z-50"> | |
| <div class="bg-white rounded-xl shadow-xl max-w-md w-full fade-in slide-up overflow-y-auto" style="max-height: 90vh;"> | |
| <div class="p-6"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-xl font-bold text-gray-800">Créer un compte</h3> | |
| <button id="close-register-modal" class="text-gray-400 hover:text-gray-600"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <!-- Register Tabs --> | |
| <div class="flex mb-6 rounded-lg bg-gray-100 p-1"> | |
| <button id="register-student-tab" class="flex-1 py-2 px-4 rounded-lg text-sm font-medium text-white bg-blue-600 transition-all-300"> | |
| <i class="fas fa-user-graduate mr-2"></i> Élève | |
| </button> | |
| <button id="register-monitor-tab" class="flex-1 py-2 px-4 rounded-lg text-sm font-medium text-gray-700 hover:bg-gray-200 transition-all-300"> | |
| <i class="fas fa-chalkboard-teacher mr-2"></i> Moniteur | |
| </button> | |
| <button id="register-admin-tab" class="flex-1 py-2 px-4 rounded-lg text-sm font-medium text-gray-700 hover:bg-gray-200 transition-all-300"> | |
| <i class="fas fa-user-shield mr-2"></i> Admin | |
| </button> | |
| </div> | |
| <!-- Student Registration Form --> | |
| <form id="student-register-form" class="space-y-4"> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> | |
| <div> | |
| <label for="first-name" class="block text-sm font-medium text-gray-700 mb-1">Prénom*</label> | |
| <input type="text" id="first-name" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-blue-500" required> | |
| </div> | |
| <div> | |
| <label for="last-name" class="block text-sm font-medium text-gray-700 mb-1">Nom*</label> | |
| <input type="text" id="last-name" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-blue-500" required> | |
| </div> | |
| </div> | |
| <div> | |
| <label for="register-email" class="block text-sm font-medium text-gray-700 mb-1">Email*</label> | |
| <input type="email" id="register-email" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-blue-500" required> | |
| </div> | |
| <div> | |
| <label for="register-password" class="block text-sm font-medium text-gray-700 mb-1">Mot de passe*</label> | |
| <div class="relative"> | |
| <input type="password" id="register-password" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-blue-500" required> | |
| <div class="absolute inset-y-0 right-0 pr-3 flex items-center"> | |
| <button type="button" class="text-gray-400 hover:text-gray-600 toggle-password"> | |
| <i class="fas fa-eye"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <p class="mt-1 text-xs text-gray-500">8 caractères minimum avec au moins 1 chiffre</p> | |
| </div> | |
| <div> | |
| <label for="confirm-password" class="block text-sm font-medium text-gray-700 mb-1">Confirmer le mot de passe*</label> | |
| <input type="password" id="confirm-password" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-blue-500" required> | |
| </div> | |
| <div> | |
| <label for="phone" class="block text-sm font-medium text-gray-700 mb-1">Téléphone*</label> | |
| <input type="tel" id="phone" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-blue-500" required> | |
| </div> | |
| <div> | |
| <label for="birthdate" class="block text-sm font-medium text-gray-700 mb-1">Date de naissance*</label> | |
| <input type="date" id="birthdate" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-blue-500" required> | |
| </div> | |
| <div> | |
| <label for="license-type" class="block text-sm font-medium text-gray-700 mb-1">Type de permis*</label> | |
| <select id="license-type" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-blue-500" required> | |
| <option value="">Sélectionner</option> | |
| <option value="B">Permis B (Voiture)</option> | |
| <option value="A">Permis A (Moto)</option> | |
| <option value="C">Permis C (Poids lourd)</option> | |
| <option value="D">Permis D (Bus)</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label for="address" class="block text-sm font-medium text-gray-700 mb-1">Adresse</label> | |
| <textarea id="address" rows="2" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-blue-500"></textarea> | |
| </div> | |
| <div class="flex items-center"> | |
| <input id="terms" type="checkbox" class="custom-checkbox text-blue-600 focus:ring-blue-500" required> | |
| <label for="terms" class="ml-2 block text-sm text-gray-700"> | |
| J'accepte les <a href="#" class="text-blue-600 hover:text-blue-800">conditions d'utilisation</a> et la <a href="#" class="text-blue-600 hover:text-blue-800">politique de confidentialité</a> | |
| </label> | |
| </div> | |
| <button type="submit" class="w-full bg-blue-600 text-white py-3 px-4 rounded-lg hover:bg-blue-700 transition flex items-center justify-center"> | |
| <span id="register-text">S'inscrire comme élève</span> | |
| <i id="register-spinner" class="fas fa-spinner fa-spin ml-2 hidden"></i> | |
| </button> | |
| </form> | |
| <!-- Monitor Registration Form --> | |
| <form id="monitor-register-form" class="space-y-4 hidden"> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> | |
| <div> | |
| <label for="monitor-first-name" class="block text-sm font-medium text-gray-700 mb-1">Prénom*</label> | |
| <input type="text" id="monitor-first-name" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-purple-500" required> | |
| </div> | |
| <div> | |
| <label for="monitor-last-name" class="block text-sm font-medium text-gray-700 mb-1">Nom*</label> | |
| <input type="text" id="monitor-last-name" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-purple-500" required> | |
| </div> | |
| </div> | |
| <div> | |
| <label for="monitor-email" class="block text-sm font-medium text-gray-700 mb-1">Email*</label> | |
| <input type="email" id="monitor-email" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-purple-500" required> | |
| </div> | |
| <div> | |
| <label for="monitor-password" class="block text-sm font-medium text-gray-700 mb-1">Mot de passe*</label> | |
| <div class="relative"> | |
| <input type="password" id="monitor-password" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-purple-500" required> | |
| <div class="absolute inset-y-0 right-0 pr-3 flex items-center"> | |
| <button type="button" class="text-gray-400 hover:text-gray-600 toggle-password"> | |
| <i class="fas fa-eye"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <div> | |
| <label for="monitor-confirm-password" class="block text-sm font-medium text-gray-700 mb-1">Confirmer le mot de passe*</label> | |
| <input type="password" id="monitor-confirm-password" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-purple-500" required> | |
| </div> | |
| <div> | |
| <label for="monitor-phone" class="block text-sm font-medium text-gray-700 mb-1">Téléphone*</label> | |
| <input type="tel" id="monitor-phone" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-purple-500" required> | |
| </div> | |
| <div> | |
| <label for="monitor-id" class="block text-sm font-medium text-gray-700 mb-1">Numéro d'agrément*</label> | |
| <input type="text" id="monitor-id" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-purple-500" required> | |
| </div> | |
| <div> | |
| <label for="monitor-license-types" class="block text-sm font-medium text-gray-700 mb-1">Permis enseignés*</label> | |
| <select id="monitor-license-types" multiple class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-purple-500" required> | |
| <option value="B">Permis B (Voiture)</option> | |
| <option value="A">Permis A (Moto)</option> | |
| <option value="C">Permis C (Poids lourd)</option> | |
| <option value="D">Permis D (Bus)</option> | |
| </select> | |
| <p class="mt-1 text-xs text-gray-500">Maintenez Ctrl (Windows) ou Cmd (Mac) pour sélectionner plusieurs options</p> | |
| </div> | |
| <div> | |
| <label for="monitor-experience" class="block text-sm font-medium text-gray-700 mb-1">Années d'expérience</label> | |
| <input type="number" id="monitor-experience" min="0" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-purple-500"> | |
| </div> | |
| <div class="flex items-center"> | |
| <input id="monitor-terms" type="checkbox" class="custom-checkbox text-purple-600 focus:ring-purple-500" required> | |
| <label for="monitor-terms" class="ml-2 block text-sm text-gray-700"> | |
| J'accepte les <a href="#" class="text-purple-600 hover:text-purple-800">conditions d'utilisation</a> | |
| </label> | |
| </div> | |
| <button type="submit" class="w-full bg-purple-600 text-white py-3 px-4 rounded-lg hover:bg-purple-700 transition flex items-center justify-center"> | |
| <span id="monitor-register-text">Demander l'inscription comme moniteur</span> | |
| <i id="monitor-register-spinner" class="fas fa-spinner fa-spin ml-2 hidden"></i> | |
| </button> | |
| </form> | |
| <!-- Admin Registration Form --> | |
| <form id="admin-register-form" class="space-y-4 hidden"> | |
| <div class="bg-yellow-50 border-l-4 border-yellow-400 p-4 mb-4"> | |
| <div class="flex"> | |
| <div class="flex-shrink-0"> | |
| <i class="fas fa-exclamation-triangle text-yellow-400"></i> | |
| </div> | |
| <div class="ml-3"> | |
| <p class="text-sm text-yellow-700"> | |
| Les comptes administrateur ne peuvent être créés que par un administrateur existant. Veuillez contacter le support pour obtenir un accès. | |
| </p> | |
| </div> | |
| </div> | |
| </div> | |
| <div> | |
| <label for="admin-code" class="block text-sm font-medium text-gray-700 mb-1">Code d'accès administrateur*</label> | |
| <input type="password" id="admin-code" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-green-500" required> | |
| </div> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> | |
| <div> | |
| <label for="admin-first-name" class="block text-sm font-medium text-gray-700 mb-1">Prénom*</label> | |
| <input type="text" id="admin-first-name" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-green-500" required> | |
| </div> | |
| <div> | |
| <label for="admin-last-name" class="block text-sm font-medium text-gray-700 mb-1">Nom*</label> | |
| <input type="text" id="admin-last-name" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-green-500" required> | |
| </div> | |
| </div> | |
| <div> | |
| <label for="admin-email" class="block text-sm font-medium text-gray-700 mb-1">Email*</label> | |
| <input type="email" id="admin-email" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-green-500" required> | |
| </div> | |
| <div> | |
| <label for="admin-password" class="block text-sm font-medium text-gray-700 mb-1">Mot de passe*</label> | |
| <div class="relative"> | |
| <input type="password" id="admin-password" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-green-500" required> | |
| <div class="absolute inset-y-0 right-0 pr-3 flex items-center"> | |
| <button type="button" class="text-gray-400 hover:text-gray-600 toggle-password"> | |
| <i class="fas fa-eye"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <div> | |
| <label for="admin-confirm-password" class="block text-sm font-medium text-gray-700 mb-1">Confirmer le mot de passe*</label> | |
| <input type="password" id="admin-confirm-password" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-green-500" required> | |
| </div> | |
| <div> | |
| <label for="admin-phone" class="block text-sm font-medium text-gray-700 mb-1">Téléphone*</label> | |
| <input type="tel" id="admin-phone" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-green-500" required> | |
| </div> | |
| <div> | |
| <label for="admin-role" class="block text-sm font-medium text-gray-700 mb-1">Rôle*</label> | |
| <select id="admin-role" class="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:border-transparent focus:ring-green-500" required> | |
| <option value="">Sélectionner</option> | |
| <option value="superadmin">Super Administrateur</option> | |
| <option value="manager">Gestionnaire</option> | |
| <option value="secretary">Secrétaire</option> | |
| </select> | |
| </div> | |
| <div class="flex items-center"> | |
| <input id="admin-terms" type="checkbox" class="custom-checkbox text-green-600 focus:ring-green-500" required> | |
| <label for="admin-terms" class="ml-2 block text-sm text-gray-700"> | |
| J'accepte les <a href="#" class="text-green-600 hover:text-green-800">conditions d'utilisation</a> | |
| </label> | |
| </div> | |
| <button type="submit" class="w-full bg-green-600 text-white py-3 px-4 rounded-lg hover:bg-green-700 transition flex items-center justify-center"> | |
| <span id="admin-register-text">Créer le compte administrateur</span> | |
| <i id="admin-register-spinner" class="fas fa-spinner fa-spin ml-2 hidden"></i> | |
| </button> | |
| </form> | |
| <div class="mt-4 text-center text-sm"> | |
| <p class="text-gray-500">Déjà inscrit ? | |
| <button id="show-login-from-register" class="font-medium text-blue-600 hover:text-blue-800">Se connecter</button> | |
| </p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Success Message --> | |
| <div id="success-message" class="fixed bottom-4 right-4 bg-green-500 text-white px-6 py-3 rounded-lg shadow-lg hidden z-50 fade-in"> | |
| <div class="flex items-center"> | |
| <i class="fas fa-check-circle mr-2"></i> | |
| <span id="success-text">Connexion réussie !</span> | |
| <button id="close-success" class="ml-4 text-white hover:text-green-100"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Error Message --> | |
| <div id="error-message" class="fixed bottom-4 right-4 bg-red-500 text-white px-6 py-3 rounded-lg shadow-lg hidden z-50 fade-in"> | |
| <div class="flex items-center"> | |
| <i class="fas fa-exclamation-circle mr-2"></i> | |
| <span id="error-text">Email ou mot de passe incorrect</span> | |
| <button id="close-error" class="ml-4 text-white hover:text-red-100"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <script> | |
| // DOM Elements | |
| const loginContainer = document.getElementById('login-container'); | |
| const loginBtn = document.getElementById('login-btn'); | |
| const loginText = document.getElementById('login-text'); | |
| const loginSpinner = document.getElementById('login-spinner'); | |
| const emailInput = document.getElementById('login-email'); | |
| const passwordInput = document.getElementById('login-password'); | |
| const emailError = document.getElementById('email-error'); | |
| const passwordError = document.getElementById('password-error'); | |
| const togglePassword = document.getElementById('toggle-password'); | |
| const forgotPassword = document.getElementById('forgot-password'); | |
| const registerLink = document.getElementById('register-link'); | |
| const forgotModal = document.getElementById('forgot-modal'); | |
| const closeForgotModal = document.getElementById('close-forgot-modal'); | |
| const sendResetLink = document.getElementById('send-reset-link'); | |
| const registerModal = document.getElementById('register-modal'); | |
| const closeRegisterModal = document.getElementById('close-register-modal'); | |
| const showLoginFromRegister = document.getElementById('show-login-from-register'); | |
| const successMessage = document.getElementById('success-message'); | |
| const closeSuccess = document.getElementById('close-success'); | |
| const errorMessage = document.getElementById('error-message'); | |
| const closeError = document.getElementById('close-error'); | |
| const studentTab = document.getElementById('student-tab'); | |
| const monitorTab = document.getElementById('monitor-tab'); | |
| const adminTab = document.getElementById('admin-tab'); | |
| const headerBg = document.getElementById('header-bg'); | |
| const studentInfo = document.getElementById('student-info'); | |
| const monitorInfo = document.getElementById('monitor-info'); | |
| const adminInfo = document.getElementById('admin-info'); | |
| const roleInfo = document.getElementById('role-info'); | |
| // Register form tabs | |
| const registerStudentTab = document.getElementById('register-student-tab'); | |
| const registerMonitorTab = document.getElementById('register-monitor-tab'); | |
| const registerAdminTab = document.getElementById('register-admin-tab'); | |
| const studentRegisterForm = document.getElementById('student-register-form'); | |
| const monitorRegisterForm = document.getElementById('monitor-register-form'); | |
| const adminRegisterForm = document.getElementById('admin-register-form'); | |
| // Role Tabs | |
| let currentRole = 'student'; | |
| studentTab.addEventListener('click', () => { | |
| currentRole = 'student'; | |
| updateRoleTabs(); | |
| }); | |
| monitorTab.addEventListener('click', () => { | |
| currentRole = 'monitor'; | |
| updateRoleTabs(); | |
| }); | |
| adminTab.addEventListener('click', () => { | |
| currentRole = 'admin'; | |
| updateRoleTabs(); | |
| }); | |
| function updateRoleTabs() { | |
| // Update header background | |
| headerBg.className = `py-8 px-8 text-center relative transition-all-300 ${currentRole === 'student' ? 'bg-student' : currentRole === 'monitor' ? 'bg-monitor' : 'bg-admin'}`; | |
| // Update role info section | |
| studentInfo.classList.toggle('hidden', currentRole !== 'student'); | |
| monitorInfo.classList.toggle('hidden', currentRole !== 'monitor'); | |
| adminInfo.classList.toggle('hidden', currentRole !== 'admin'); | |
| // Update role info border color | |
| roleInfo.className = `mb-6 p-4 rounded-lg border transition-all-300 ${currentRole === 'student' ? 'bg-blue-50 border-blue-100' : currentRole === 'monitor' ? 'bg-purple-50 border-purple-100' : 'bg-green-50 border-green-100'}`; | |
| // Update login button color | |
| loginBtn.className = `w-full flex justify-center items-center py-3 px-4 border border-transparent rounded-lg shadow-sm text-sm font-medium text-white focus:outline-none focus:ring-2 focus:ring-offset-2 transition-all-300 pulse ${currentRole === 'student' ? 'bg-blue-600 hover:bg-blue-700 focus:ring-blue-500' : currentRole === 'monitor' ? 'bg-purple-600 hover:bg-purple-700 focus:ring-purple-500' : 'bg-green-600 hover:bg-green-700 focus:ring-green-500'}`; | |
| } | |
| // Register form tabs | |
| registerStudentTab.addEventListener('click', (e) => { | |
| e.preventDefault(); | |
| updateRegisterForm('student'); | |
| }); | |
| registerMonitorTab.addEventListener('click', (e) => { | |
| e.preventDefault(); | |
| updateRegisterForm('monitor'); | |
| }); | |
| registerAdminTab.addEventListener('click', (e) => { | |
| e.preventDefault(); | |
| updateRegisterForm('admin'); | |
| }); | |
| function updateRegisterForm(role) { | |
| // Update tabs | |
| registerStudentTab.className = `flex-1 py-2 px-4 rounded-lg text-sm font-medium transition-all-300 ${role === 'student' ? 'text-white bg-blue-600' : 'text-gray-700 hover:bg-gray-200'}`; | |
| registerMonitorTab.className = `flex-1 py-2 px-4 rounded-lg text-sm font-medium transition-all-300 ${role === 'monitor' ? 'text-white bg-purple-600' : 'text-gray-700 hover:bg-gray-200'}`; | |
| registerAdminTab.className = `flex-1 py-2 px-4 rounded-lg text-sm font-medium transition-all-300 ${role === 'admin' ? 'text-white bg-green-600' : 'text-gray-700 hover:bg-gray-200'}`; | |
| // Update forms | |
| studentRegisterForm.classList.toggle('hidden', role !== 'student'); | |
| monitorRegisterForm.classList.toggle('hidden', role !== 'monitor'); | |
| adminRegisterForm.classList.toggle('hidden', role !== 'admin'); | |
| } | |
| // Toggle Password Visibility | |
| togglePassword.addEventListener('click', () => { | |
| const type = passwordInput.getAttribute('type') === 'password' ? 'text' : 'password'; | |
| passwordInput.setAttribute('type', type); | |
| togglePassword.innerHTML = type === 'password' ? '<i class="fas fa-eye"></i>' : '<i class="fas fa-eye-slash"></i>'; | |
| }); | |
| // Form Validation | |
| emailInput.addEventListener('input', () => { | |
| if (!validateEmail(emailInput.value)) { | |
| emailError.classList.remove('hidden'); | |
| emailInput.classList.add('border-red-500'); | |
| emailInput.classList.remove('border-gray-300'); | |
| } else { | |
| emailError.classList.add('hidden'); | |
| emailInput.classList.remove('border-red-500'); | |
| emailInput.classList.add('border-gray-300'); | |
| } | |
| }); | |
| passwordInput.addEventListener('input', () => { | |
| if (passwordInput.value.length < 8) { | |
| passwordError.classList.remove('hidden'); | |
| passwordInput.classList.add('border-red-500'); | |
| passwordInput.classList.remove('border-gray-300'); | |
| } else { | |
| passwordError.classList.add('hidden'); | |
| passwordInput.classList.remove('border-red-500'); | |
| passwordInput.classList.add('border-gray-300'); | |
| } | |
| }); | |
| function validateEmail(email) { | |
| const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; | |
| return re.test(email); | |
| } | |
| // Forgot Password Modal | |
| forgotPassword.addEventListener('click', (e) => { | |
| e.preventDefault(); | |
| forgotModal.classList.remove('hidden'); | |
| }); | |
| closeForgotModal.addEventListener('click', () => { | |
| forgotModal.classList.add('hidden'); | |
| }); | |
| sendResetLink.addEventListener('click', () => { | |
| const resetEmail = document.getElementById('reset-email').value; | |
| if (validateEmail(resetEmail)) { | |
| showSuccessMessage('Un lien de réinitialisation a été envoyé à votre email'); | |
| forgotModal.classList.add('hidden'); | |
| } else { | |
| showErrorMessage('Veuillez entrer une adresse email valide'); | |
| } | |
| }); | |
| // Register Modal | |
| registerLink.addEventListener('click', (e) => { | |
| e.preventDefault(); | |
| registerModal.classList.remove('hidden'); | |
| updateRegisterForm('student'); | |
| }); | |
| closeRegisterModal.addEventListener('click', () => { | |
| registerModal.classList.add('hidden'); | |
| }); | |
| showLoginFromRegister.addEventListener('click', () => { | |
| registerModal.classList.add('hidden'); | |
| }); | |
| // Register Form Toggle Password | |
| document.querySelectorAll('.toggle-password').forEach(button => { | |
| button.addEventListener('click', function() { | |
| const input = this.parentElement.previousElementSibling; | |
| const type = input.getAttribute('type') === 'password' ? 'text' : 'password'; | |
| input.setAttribute('type', type); | |
| this.innerHTML = type === 'password' ? '<i class="fas fa-eye"></i>' : '<i class="fas fa-eye-slash"></i>'; | |
| }); | |
| }); | |
| // Register Form Submissions | |
| studentRegisterForm.addEventListener('submit', function(e) { | |
| e.preventDefault(); | |
| const registerSpinner = document.getElementById('register-spinner'); | |
| const registerText = document.getElementById('register-text'); | |
| registerText.textContent = 'Inscription en cours...'; | |
| registerSpinner.classList.remove('hidden'); | |
| // Simulate API call | |
| setTimeout(() => { | |
| registerText.textContent = 'Inscription réussie !'; | |
| registerSpinner.classList.add('hidden'); | |
| setTimeout(() => { | |
| registerModal.classList.add('hidden'); | |
| registerText.textContent = 'S\'inscrire comme élève'; | |
| showSuccessMessage('Votre compte élève a été créé avec succès !'); | |
| }, 1000); | |
| }, 2000); | |
| }); | |
| monitorRegisterForm.addEventListener('submit', function(e) { | |
| e.preventDefault(); | |
| const registerSpinner = document.getElementById('monitor-register-spinner'); | |
| const registerText = document.getElementById('monitor-register-text'); | |
| registerText.textContent = 'Demande en cours...'; | |
| registerSpinner.classList.remove('hidden'); | |
| // Simulate API call | |
| setTimeout(() => { | |
| registerText.textContent = 'Demande envoyée !'; | |
| registerSpinner.classList.add('hidden'); | |
| setTimeout(() => { | |
| registerModal.classList.add('hidden'); | |
| registerText.textContent = 'Demander l\'inscription comme moniteur'; | |
| showSuccessMessage('Votre demande d\'inscription comme moniteur a été envoyée ! Un administrateur va la examiner.'); | |
| }, 1000); | |
| }, 2000); | |
| }); | |
| adminRegisterForm.addEventListener('submit', function(e) { | |
| e.preventDefault(); | |
| const registerSpinner = document.getElementById('admin-register-spinner'); | |
| const registerText = document.getElementById('admin-register-text'); | |
| const adminCode = document.getElementById('admin-code').value; | |
| if (adminCode !== 'ADMIN123') { | |
| showErrorMessage('Code administrateur incorrect'); | |
| return; | |
| } | |
| registerText.textContent = 'Création en cours...'; | |
| registerSpinner.classList.remove('hidden'); | |
| // Simulate API call | |
| setTimeout(() => { | |
| registerText.textContent = 'Compte créé !'; | |
| registerSpinner.classList.add('hidden'); | |
| setTimeout(() => { | |
| registerModal.classList.add('hidden'); | |
| registerText.textContent = 'Créer le compte administrateur'; | |
| showSuccessMessage('Votre compte administrateur a été créé avec succès !'); | |
| }, 1000); | |
| }, 2000); | |
| }); | |
| // Login Simulation | |
| loginBtn.addEventListener('click', () => { | |
| // Validate inputs | |
| const emailValid = validateEmail(emailInput.value); | |
| const passwordValid = passwordInput.value.length >= 8; | |
| if (!emailValid || !passwordValid) { | |
| if (!emailValid) { | |
| emailError.classList.remove('hidden'); | |
| emailInput.classList.add('border-red-500'); | |
| emailInput.classList.remove('border-gray-300'); | |
| emailInput.classList.add('shake'); | |
| setTimeout(() => emailInput.classList.remove('shake'), 500); | |
| } | |
| if (!passwordValid) { | |
| passwordError.classList.remove('hidden'); | |
| passwordInput.classList.add('border-red-500'); | |
| passwordInput.classList.remove('border-gray-300'); | |
| passwordInput.classList.add('shake'); | |
| setTimeout(() => passwordInput.classList.remove('shake'), 500); | |
| } | |
| return; | |
| } | |
| // Show loading state | |
| loginText.textContent = 'Connexion en cours...'; | |
| loginSpinner.classList.remove('hidden'); | |
| loginBtn.disabled = true; | |
| // Simulate API call | |
| setTimeout(() => { | |
| // Randomly decide if login succeeds (80% chance) | |
| const success = Math.random() < 0.8; | |
| if (success) { | |
| showSuccessMessage(`Connexion réussie en tant que ${currentRole}`); | |
| // Redirect to dashboard after delay | |
| setTimeout(() => { | |
| // In a real app, you would redirect to the appropriate dashboard | |
| // window.location.href = `${currentRole}-dashboard.html`; | |
| console.log(`Redirecting to ${currentRole} dashboard`); | |
| }, 1500); | |
| } else { | |
| showErrorMessage('Email ou mot de passe incorrect'); | |
| } | |
| // Reset login button | |
| loginText.textContent = 'Connexion'; | |
| loginSpinner.classList.add('hidden'); | |
| loginBtn.disabled = false; | |
| }, 1500); | |
| }); | |
| // Show success message | |
| function showSuccessMessage(message) { | |
| document.getElementById('success-text').textContent = message; | |
| successMessage.classList.remove('hidden'); | |
| // Auto-hide after 5 seconds | |
| setTimeout(() => { | |
| if (!successMessage.classList.contains('hidden')) { | |
| successMessage.classList.add('hidden'); | |
| } | |
| }, 5000); | |
| } | |
| // Show error message | |
| function showErrorMessage(message) { | |
| document.getElementById('error-text').textContent = message; | |
| errorMessage.classList.remove('hidden'); | |
| // Auto-hide after 5 seconds | |
| setTimeout(() => { | |
| if (!errorMessage.classList.contains('hidden')) { | |
| errorMessage.classList.add('hidden'); | |
| } | |
| }, 5000); | |
| } | |
| // Close messages | |
| closeSuccess.addEventListener('click', () => { | |
| successMessage.classList.add('hidden'); | |
| }); | |
| closeError.addEventListener('click', () => { | |
| errorMessage.classList.add('hidden'); | |
| }); | |
| // Initialize | |
| updateRoleTabs(); | |
| </script> | |
| </body> | |
| </html> |