English
Spanish
French
0
Notifications
0 Non lues
Aucune notification
Voir toutes
Aucune nouvelle notification
Raccourcis
Tableau de bord
Profil
Paramètres
Voir toutes les apps
Utilisateur
Utilisateur
Profil
Messages
25
Paramètres
Solde
$47.12
Support
Se déconnecter
Dashboard
Dashboard
Éditer first/callback_form.php
<div class="callback-form" id="callback-form"> <div class="container"> <div class="row"> <div class="col-md-12"> <div class="section-heading"> <h2>Demander un <em>rappel</em></h2> <span>Laissez-nous vos coordonnées, nous vous contacterons rapidement</span> </div> </div> <div class="col-md-12"> <div class="contact-form"> <?php if (session()->getFlashdata('success')): ?> <div class="alert alert-success"><?= esc(session()->getFlashdata('success')) ?></div> <?php elseif (session()->getFlashdata('error')): ?> <div class="alert alert-danger"><?= esc(session()->getFlashdata('error')) ?></div> <?php endif; ?> <div id="form-alert"></div> <form id="contact-form" action="<?= base_url('callback/envoyer'); ?>" method="post"> <!-- Honeypot (piège à robots) --> <div style="position: absolute; left: -9999px; opacity: 0;"> <input type="text" name="website" placeholder="Ne pas remplir ce champ" tabindex="-1" autocomplete="off"> </div> <div class="row"> <div class="col-lg-4 col-md-12 col-sm-12"> <fieldset> <input name="name" type="text" class="form-control" id="name" placeholder="Nom complet" required minlength="2" maxlength="50"> </fieldset> </div> <div class="col-lg-4 col-md-12 col-sm-12"> <fieldset> <input name="email" type="email" class="form-control" id="email" placeholder="Adresse E-Mail" required> </fieldset> </div> <div class="col-lg-4 col-md-12 col-sm-12"> <fieldset> <input name="subject" type="text" class="form-control" id="subject" placeholder="Sujet" required minlength="5" maxlength="100"> </fieldset> </div> <div class="col-lg-12"> <fieldset> <textarea name="message" rows="6" class="form-control" id="message" placeholder="Votre message" required minlength="10" maxlength="1000"></textarea> </fieldset> </div> <!-- Section Anti-spam Compacte --> <div class="col-lg-12"> <div class="security-verification-compact"> <div class="verification-header"> <i class="fas fa-shield-alt"></i> <span>Vérification de sécurité</span> </div> <!-- Ligne de calcul CAPTCHA --> <div class="captcha-line"> <div class="captcha-question-wrapper"> <span id="captcha-question" class="captcha-display"></span> </div> <input type="number" name="captcha" id="captcha" class="captcha-input" placeholder="Tapez votre réponse" required autocomplete="off"> <button type="button" id="refresh-captcha" class="captcha-refresh-btn" title="Changer la question" aria-label="Générer un nouveau calcul"> <i class="fas fa-redo-alt"></i> </button> </div> <!-- Checkbox de certification --> <div class="human-check-wrapper"> <input type="checkbox" id="human-check" class="human-checkbox" required> <label for="human-check" class="human-label"> <span class="checkbox-icon"> <i class="fas fa-check"></i> </span> <span class="checkbox-text">Je certifie que je ne suis pas un robot</span> </label> </div> </div> </div> <div class="col-lg-12"> <fieldset> <button type="submit" id="form-submit" class="border-button"> <span class="spinner-border spinner-border-sm d-none" id="spinner" role="status" aria-hidden="true"></span> <span id="btn-text">Envoyer le message</span> </button> </fieldset> </div> </div> </form> </div> </div> </div> </div> </div> <style> /* ====== SECTION VERIFICATION SECURITE COMPACTE ====== */ .security-verification-compact { background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); border-radius: 15px; padding: 25px; margin: 20px 0; border: 2px solid #e3f2fd; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08); position: relative; overflow: hidden; } .security-verification-compact::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: linear-gradient(90deg, #4CAF50, #2196F3, #4CAF50); border-radius: 15px 15px 0 0; } .verification-header { text-align: center; margin-bottom: 20px; } .verification-header i { color: #4CAF50; font-size: 20px; margin-right: 8px; } .verification-header span { color: #2c3e50; font-size: 18px; font-weight: 600; } /* ====== LIGNE CAPTCHA COMPACTE ====== */ .captcha-line { display: flex; align-items: center; justify-content: center; gap: 15px; margin-bottom: 20px; flex-wrap: wrap; } .captcha-question-wrapper { flex-shrink: 0; } .captcha-display { background: linear-gradient(135deg, #4CAF50 0%, #2196F3 100%); color: white; padding: 12px 20px; border-radius: 10px; font-size: 18px; font-weight: bold; min-width: 120px; text-align: center; box-shadow: 0 4px 12px rgba(76, 175, 80, 0.3); letter-spacing: 1px; transition: all 0.3s ease; } .captcha-display:hover { transform: translateY(-2px); box-shadow: 0 6px 16px rgba(76, 175, 80, 0.4); } .captcha-input { width: 140px; padding: 12px 15px; font-size: 16px; font-weight: 600; text-align: center; border: 2px solid #dee2e6; border-radius: 8px; background: white; color: #495057; transition: all 0.3s ease; } .captcha-input::placeholder { color: #6c757d; font-weight: 500; font-size: 14px; } .captcha-input:focus { outline: none; border-color: #4CAF50; box-shadow: 0 0 0 3px rgba(76, 175, 80, 0.1); background: #f8fff8; transform: translateY(-1px); } .captcha-input.error { border-color: #dc3545; background: #fff5f5; animation: shake 0.5s ease-in-out; } .captcha-input.success { border-color: #28a745; background: #f8fff8; } .captcha-refresh-btn { background: linear-gradient(135deg, #6c757d 0%, #495057 100%); color: white; border: none; padding: 12px; border-radius: 8px; font-size: 14px; cursor: pointer; transition: all 0.3s ease; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); display: flex; align-items: center; justify-content: center; width: 44px; height: 44px; flex-shrink: 0; } .captcha-refresh-btn:hover { background: linear-gradient(135deg, #4CAF50 0%, #2196F3 100%); transform: translateY(-2px) rotate(180deg); box-shadow: 0 6px 16px rgba(76, 175, 80, 0.3); } .captcha-refresh-btn:active { transform: translateY(0) rotate(360deg); } /* ====== CHECKBOX COMPACTE ====== */ .human-check-wrapper { display: flex; justify-content: center; align-items: center; } .human-checkbox { display: none; } .human-label { display: flex; align-items: center; gap: 12px; cursor: pointer; font-size: 15px; font-weight: 500; color: #495057; transition: all 0.3s ease; padding: 8px 12px; border-radius: 8px; background: white; border: 2px solid #e9ecef; } .human-label:hover { border-color: #4CAF50; background: #f8fff8; } .checkbox-icon { width: 20px; height: 20px; border: 2px solid #dee2e6; border-radius: 4px; display: flex; align-items: center; justify-content: center; transition: all 0.3s ease; background: white; position: relative; flex-shrink: 0; } .checkbox-icon i { color: white; font-size: 12px; opacity: 0; transition: all 0.3s ease; } .human-checkbox:checked + .human-label .checkbox-icon { background: linear-gradient(135deg, #4CAF50 0%, #2196F3 100%); border-color: #4CAF50; transform: scale(1.1); } .human-checkbox:checked + .human-label .checkbox-icon i { opacity: 1; } .human-checkbox:checked + .human-label { border-color: #4CAF50; background: #f8fff8; } .checkbox-text { line-height: 1.4; user-select: none; } /* ====== ANIMATIONS ====== */ @keyframes shake { 0%, 20%, 50%, 80%, 100% { transform: translateX(0); } 10% { transform: translateX(-3px); } 30% { transform: translateX(3px); } 60% { transform: translateX(-2px); } 90% { transform: translateX(2px); } } @keyframes fadeInUp { from { opacity: 0; transform: translateY(15px); } to { opacity: 1; transform: translateY(0); } } .security-verification-compact { animation: fadeInUp 0.5s ease-out; } /* ====== RESPONSIVE ====== */ @media (max-width: 768px) { .security-verification-compact { padding: 20px 15px; margin: 15px 0; } .verification-header span { font-size: 16px; } .captcha-line { flex-direction: column; gap: 15px; } .captcha-display { font-size: 16px; padding: 10px 18px; min-width: 100px; } .captcha-input { width: 160px; font-size: 15px; } .captcha-refresh-btn { width: 40px; height: 40px; padding: 10px; } .human-label { font-size: 14px; padding: 6px 10px; } } @media (max-width: 480px) { .captcha-line { gap: 12px; } .captcha-display { font-size: 15px; padding: 8px 15px; } .captcha-input { width: 140px; padding: 10px 12px; font-size: 14px; } .human-label { font-size: 13px; } } /* ====== COMPATIBILITE ANCIENNES REGLES ====== */ .form-check-input:checked { background-color: #4CAF50; border-color: #4CAF50; } .form-check-input:focus { border-color: #4CAF50; box-shadow: 0 0 0 0.2rem rgba(76, 175, 80, 0.25); } .alert { border-radius: 10px; margin-bottom: 20px; padding: 15px 20px; border: none; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); animation: fadeInUp 0.5s ease-out; } .alert-success { background: linear-gradient(135deg, #d4edda 0%, #c3e6cb 100%); color: #155724; border-left: 4px solid #28a745; } .alert-danger { background: linear-gradient(135deg, #f8d7da 0%, #f5c6cb 100%); color: #721c24; border-left: 4px solid #dc3545; } .alert-warning { background: linear-gradient(135deg, #fff3cd 0%, #ffeaa7 100%); color: #856404; border-left: 4px solid #ffc107; } .border-button { background: linear-gradient(135deg, #4CAF50 0%, #2196F3 100%); color: white; border: none; padding: 15px 35px; border-radius: 25px; font-weight: 600; font-size: 16px; transition: all 0.3s ease; position: relative; overflow: hidden; box-shadow: 0 6px 20px rgba(76, 175, 80, 0.3); } .border-button:hover { transform: translateY(-2px); box-shadow: 0 8px 25px rgba(76, 175, 80, 0.4); } .border-button:active { transform: translateY(-1px); } .border-button:disabled { opacity: 0.7; cursor: not-allowed; transform: none; } /* Protection honeypot */ input[name="website"] { position: absolute !important; left: -9999px !important; top: -9999px !important; opacity: 0 !important; pointer-events: none !important; width: 0 !important; height: 0 !important; border: none !important; } </style> <script> // Variables pour le CAPTCHA let captchaAnswer = 0; let lastSubmissionTime = 0; const MIN_INTERVAL = 5000; // 5 secondes entre les soumissions // Fonction pour générer un nouveau CAPTCHA function generateCaptcha() { const num1 = Math.floor(Math.random() * 20) + 1; const num2 = Math.floor(Math.random() * 20) + 1; const operators = ['+', '-', '*']; const operator = operators[Math.floor(Math.random() * operators.length)]; let question = ''; switch(operator) { case '+': question = `${num1} + ${num2} = ?`; captchaAnswer = num1 + num2; break; case '-': question = `${num1} - ${num2} = ?`; captchaAnswer = num1 - num2; break; case '*': question = `${num1} × ${num2} = ?`; captchaAnswer = num1 * num2; break; } document.getElementById('captcha-question').textContent = question; document.getElementById('captcha').value = ''; // Debug console console.log('CAPTCHA généré:', question, 'Réponse:', captchaAnswer); } // Générer le CAPTCHA au chargement de la page document.addEventListener('DOMContentLoaded', function() { generateCaptcha(); }); // Actualiser le CAPTCHA document.getElementById('refresh-captcha').addEventListener('click', function() { generateCaptcha(); }); // Gestion du formulaire (UN SEUL EVENT LISTENER) document.getElementById('contact-form').addEventListener('submit', async function (e) { e.preventDefault(); const form = e.target; const formData = new FormData(form); const alertBox = document.getElementById('form-alert'); const submitBtn = document.getElementById('form-submit'); const spinner = document.getElementById('spinner'); const btnText = document.getElementById('btn-text'); // Protection contre les soumissions multiples rapides const now = Date.now(); if (now - lastSubmissionTime < MIN_INTERVAL) { alertBox.className = 'alert alert-warning'; alertBox.innerHTML = '⚠️ Veuillez attendre 5 secondes avant de renvoyer.'; return false; } lastSubmissionTime = now; // Vérifications côté client const captchaInput = parseInt(document.getElementById('captcha').value); const humanCheck = document.getElementById('human-check').checked; const honeypot = form.querySelector('input[name="website"]').value; // Debug console console.log('CAPTCHA saisi:', captchaInput, 'Réponse attendue:', captchaAnswer); // Vérification du piège à robots (honeypot) if (honeypot) { alertBox.className = 'alert alert-danger'; alertBox.innerHTML = '❌ Détection de robot. Accès refusé.'; return; } // Vérification du CAPTCHA if (isNaN(captchaInput) || captchaInput !== captchaAnswer) { alertBox.className = 'alert alert-danger'; alertBox.innerHTML = '❌ Calcul incorrect. Veuillez vérifier votre réponse.'; // Effet visuel d'erreur const captchaField = document.getElementById('captcha'); captchaField.classList.add('error'); setTimeout(() => captchaField.classList.remove('error'), 600); generateCaptcha(); // Nouveau calcul return; } // Effet visuel de succès const captchaField = document.getElementById('captcha'); captchaField.classList.add('success'); setTimeout(() => captchaField.classList.remove('success'), 1000); // Vérification de la case "Je ne suis pas un robot" if (!humanCheck) { alertBox.className = 'alert alert-danger'; alertBox.innerHTML = '❌ Veuillez cocher la case "Je ne suis pas un robot".'; return; } // Ajouter la réponse du CAPTCHA aux données formData.append('captcha_answer', captchaAnswer); // Activation du spinner spinner.classList.remove('d-none'); btnText.textContent = 'Envoi...'; submitBtn.disabled = true; try { const response = await fetch(form.action, { method: 'POST', body: formData }); const result = await response.json(); if (result.status === 'success') { alertBox.className = 'alert alert-success'; alertBox.innerHTML = '✅ ' + result.message; form.reset(); generateCaptcha(); // Nouveau calcul après envoi réussi } else { alertBox.className = 'alert alert-danger'; alertBox.innerHTML = '❌ ' + result.message; generateCaptcha(); // Nouveau calcul après échec } } catch (error) { alertBox.className = 'alert alert-danger'; alertBox.innerHTML = '❌ Une erreur est survenue. Veuillez réessayer.'; generateCaptcha(); // Nouveau calcul après erreur } spinner.classList.add('d-none'); btnText.textContent = 'Envoyer le message'; submitBtn.disabled = false; }); </script>
Annuler
Enregistrer
Switcher
Theme Styles
Theme Colors
Theme Color Mode:
Light
Dark
Menu Colors: