// ========== LANGUAGE TOGGLE (legacy buttons - now overridden by Odoo i18n URL routing) ========== // Read lang from that Odoo set server-side. Don't override it. const savedLang = document.documentElement.lang.toLowerCase().startsWith('en') ? 'en' : 'fr'; const langButtons = document.querySelectorAll('.lang-toggle button'); langButtons.forEach(b => b.classList.toggle('active', b.dataset.lang === savedLang)); // ========== ROI CALCULATOR ========== const employees = document.getElementById('employees'); const hours = document.getElementById('hours'); const rate = document.getElementById('rate'); const invoices = document.getElementById('invoices'); function fmt(n, lang) { if (lang === 'en') return n.toLocaleString('en-US'); return n.toLocaleString('fr-CA').replace(/,/g, ' '); } function updateROI() { const lang = document.documentElement.lang; const isUSD = lang === 'en'; const usdRate = 0.74; const emp = +employees.value; const hrs = +hours.value; const rCAD = +rate.value; const inv = +invoices.value; const displayRate = isUSD ? Math.round(rCAD * usdRate) : rCAD; document.getElementById('empValue').textContent = emp; document.getElementById('hoursValue').textContent = hrs + 'h'; document.getElementById('rateValue').textContent = isUSD ? '$' + displayRate : displayRate + ' $'; document.getElementById('invoicesValue').textContent = inv; const weeksPerYear = 50; const hoursSaved = Math.round(hrs * 0.73 * weeksPerYear); const laborSavingsCAD = hoursSaved * rCAD; const invoiceSavingsCAD = inv * 12 * 4.5; const totalSavingsCAD = Math.round((laborSavingsCAD + invoiceSavingsCAD) / 100) * 100; const totalSavings = isUSD ? Math.round(totalSavingsCAD * usdRate / 100) * 100 : totalSavingsCAD; const annualCostCAD = Math.max(8000, emp * 250); const roi = (totalSavingsCAD / annualCostCAD).toFixed(1); const paybackMonths = Math.max(1, Math.round(12 / roi)); document.getElementById('savings').textContent = isUSD ? '$' + fmt(totalSavings, lang) : fmt(totalSavings, lang) + ' $'; document.getElementById('hoursSaved').textContent = fmt(hoursSaved, lang) + 'h'; document.getElementById('errorReduction').textContent = '87%'; document.getElementById('roiX').textContent = roi + 'x'; document.getElementById('payback').textContent = isUSD ? `~${paybackMonths} months` : `~${paybackMonths} mois`; } [employees, hours, rate, invoices].forEach(el => { if (el) el.addEventListener('input', updateROI); }); if (employees && hours && rate && invoices) updateROI(); // ========== SMART FORM ========== let currentStep = 1; const totalSteps = 4; document.querySelectorAll('.option-card').forEach(card => { card.addEventListener('click', () => { const grid = card.parentElement; if (grid.id === 'painPointsGrid') { card.classList.toggle('selected'); } else { grid.querySelectorAll('.option-card').forEach(c => c.classList.remove('selected')); card.classList.add('selected'); } }); }); function showStep(n) { document.querySelectorAll('.form-step').forEach(s => { s.classList.toggle('active', +s.dataset.step === n); }); document.querySelectorAll('.progress-step').forEach((s, i) => { s.classList.remove('active', 'complete'); if (i + 1 < n) s.classList.add('complete'); if (i + 1 === n) s.classList.add('active'); }); } function nextStep() { if (currentStep < totalSteps) { currentStep++; showStep(currentStep); } } function prevStep() { if (currentStep > 1) { currentStep--; showStep(currentStep); } } async function submitForm() { // Récupérer toutes les données du formulaire const data = { situation: window.formData?.situation || 'Non spécifié', pain: Array.from(window.formData?.pain || []).join(', '), company: document.getElementById('field-company')?.value || '', employees: document.getElementById('field-employees')?.value || '', name: document.getElementById('field-name')?.value || '', email: document.getElementById('field-email')?.value || '', phone: document.getElementById('field-phone')?.value || '', message: document.getElementById('field-message')?.value || '', _subject: '🦅 Nouvelle demande BHI', _replyto: document.getElementById('field-email')?.value || '' }; // Validation minimale if (!data.email || !data.name) { alert(document.documentElement.lang === 'fr' ? 'Veuillez remplir au moins votre nom et courriel.' : 'Please fill in at least your name and email.'); return; } // Indicateur de chargement const submitBtn = document.querySelector('[onclick="submitForm()"]'); if (submitBtn) { submitBtn.disabled = true; submitBtn.innerHTML = document.documentElement.lang === 'fr' ? 'Envoi en cours...' : 'Sending...'; } try { // ⚠️ REMPLACE 'TON_FORMSPREE_ID' PAR TON VRAI FORMSPREE ID // Inscris-toi gratuitement sur https://formspree.io et obtiens un endpoint // Format final: https://formspree.io/f/abcdefgh const FORMSPREE_ENDPOINT = 'https://formspree.io/f/TON_FORMSPREE_ID'; const response = await fetch(FORMSPREE_ENDPOINT, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: JSON.stringify(data) }); if (response.ok) { // Succès currentStep = 5; showStep(5); document.querySelectorAll('.progress-step').forEach(s => { s.classList.remove('active'); s.classList.add('complete'); }); } else { throw new Error('Form submission failed'); } } catch (error) { // En cas d'erreur, on affiche quand même le succès en mode démo // (jusqu'à ce que tu configures Formspree) console.warn('Formspree non configuré - mode démo activé'); currentStep = 5; showStep(5); document.querySelectorAll('.progress-step').forEach(s => { s.classList.remove('active'); s.classList.add('complete'); }); } finally { if (submitBtn) { submitBtn.disabled = false; } } } // ========== STICKY CTA ON SCROLL ========== const stickyCta = document.getElementById('stickyCta'); const heroSection = document.querySelector('.hero'); const contactSection = document.getElementById('contact'); if (stickyCta && heroSection && contactSection) { window.addEventListener('scroll', () => { const heroBottom = heroSection.offsetTop + heroSection.offsetHeight; const contactTop = contactSection.offsetTop; const scrollY = window.scrollY + window.innerHeight; if (window.scrollY > heroBottom && scrollY < contactTop + 100) { stickyCta.classList.add('visible'); } else { stickyCta.classList.remove('visible'); } }); } // ========== SMOOTH SCROLL avec offset pour nav fixe ========== document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function(e) { const targetId = this.getAttribute('href'); if (targetId === '#') return; const target = document.querySelector(targetId); if (target) { e.preventDefault(); const navHeight = 130; // hauteur de la nav fixe (logo 126px + padding) const targetPosition = target.getBoundingClientRect().top + window.pageYOffset - navHeight; window.scrollTo({ top: targetPosition, behavior: 'smooth' }); } }); }); // ========== ANIMATIONS DE SCROLL (Intersection Observer) ========== const fadeInElements = document.querySelectorAll( '.benefit-card, .pain-card, .we-card, .reassure-card, .stat-card, .module-card, ' + '.process-step, .pricing-custom, .summary-impact, .roi-result-card, .smart-form, .faq-item' ); const fadeObserver = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('fade-in-visible'); fadeObserver.unobserve(entry.target); } }); }, { threshold: 0.1, rootMargin: '0px 0px -50px 0px' }); fadeInElements.forEach(el => { el.classList.add('fade-in-init'); fadeObserver.observe(el); }); // ========== ANIMATION TIMELINE PROCESS ========== const processSection = document.querySelector('.process-section'); if (processSection) { const processObserver = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('process-active'); processObserver.unobserve(entry.target); } }); }, { threshold: 0.3 }); processObserver.observe(processSection); } // ========== VALIDATION TEMPS RÉEL EMAIL ========== const emailField = document.getElementById('field-email'); if (emailField) { emailField.addEventListener('blur', () => { const isValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(emailField.value); if (emailField.value && !isValid) { emailField.style.borderColor = '#c92a3c'; } else { emailField.style.borderColor = ''; } }); } // Contact form — submit to Formspree function submitContact(e){ e.preventDefault(); const form = document.getElementById('contactForm'); const submitBtn = form.querySelector('.cf-submit'); const confirm = document.getElementById('cfConfirm'); if (submitBtn) submitBtn.disabled = true; fetch(form.action, { method: 'POST', body: new FormData(form), headers: { 'Accept': 'application/json' } }).then(res => { if (res.ok) { form.reset(); if (confirm) confirm.hidden = false; if (submitBtn) submitBtn.style.opacity = '0.5'; } else { alert(document.documentElement.lang === 'fr' ? 'Une erreur est survenue. Réessaie ou écris à contact@b-h-i.net.' : 'Something went wrong. Try again or email contact@b-h-i.net.'); if (submitBtn) submitBtn.disabled = false; } }).catch(() => { alert(document.documentElement.lang === 'fr' ? 'Erreur réseau. Réessaie ou écris à contact@b-h-i.net.' : 'Network error. Try again or email contact@b-h-i.net.'); if (submitBtn) submitBtn.disabled = false; }); return false; } window.submitContact = submitContact;