// ============================================ // MVA Global Fret — Form Handler // HubSpot Portal ID : 148163754 // HubSpot Form GUID : 1d9b75c9-8b60-4966-aa18-4bf503452e9a // ============================================ const HUBSPOT_PORTAL_ID = '148163754'; const HUBSPOT_FORM_GUID = '1d9b75c9-8b60-4966-aa18-4bf503452e9a'; // Create a free account at formspree.io and replace this ID to enable email backup const FORMSPREE_ID = 'mojrvokp'; document.addEventListener('DOMContentLoaded', () => { const form = document.getElementById('contactForm'); if (form) setupContactForm(form); }); function generateRefNumber() { const year = new Date().getFullYear(); const rand = Math.floor(1000 + Math.random() * 9000); // 4 digits return `MVA-${year}-${rand}`; } function setupContactForm(form) { form.addEventListener('submit', async (e) => { e.preventDefault(); if (!validateForm(form)) return; setLoading(true); const refNumber = generateRefNumber(); const data = { firstname: form.firstname.value.trim(), lastname: form.lastname.value.trim(), phone: form.phone.value.trim(), email: form.email.value.trim(), address: form.address.value.trim(), reference_client: refNumber, }; const results = await Promise.allSettled([ submitToHubSpot(data), submitToFormspree(data), ]); const hubspotOk = results[0].status === 'fulfilled'; const formspreeOk = results[1].status === 'fulfilled'; setLoading(false); if (hubspotOk || formspreeOk) { showSuccess(refNumber); } else { showError(); } }); } async function submitToHubSpot(data) { const payload = { fields: [ { name: 'firstname', value: data.firstname }, { name: 'lastname', value: data.lastname }, { name: 'phone', value: data.phone }, { name: 'email', value: data.email }, { name: 'address', value: data.address }, { name: 'reference_client', value: data.reference_client }, ], context: { pageUri: window.location.href, pageName: document.title, }, }; const res = await fetch( `https://api.hsforms.com/submissions/v3/integration/submit/${HUBSPOT_PORTAL_ID}/${HUBSPOT_FORM_GUID}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), } ); if (!res.ok) throw new Error(`HubSpot error: ${res.status}`); return res.json(); } async function submitToFormspree(data) { if (FORMSPREE_ID === 'YOUR_FORMSPREE_ID') return; const res = await fetch(`https://formspree.io/f/${FORMSPREE_ID}`, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json' }, body: JSON.stringify({ nom: data.lastname, prenom: data.firstname, telephone: data.phone, email: data.email, adresse_livraison: data.address, reference_client: data.reference_client, }), }); if (!res.ok) throw new Error(`Formspree error: ${res.status}`); return res.json(); } function validateForm(form) { let valid = true; const lang = localStorage.getItem('mva-lang') || 'fr'; const t = translations?.[lang]?.contact || {}; const requiredMsg = t.required || 'Ce champ est obligatoire'; const invalidEmail = t.invalidEmail || 'Adresse email invalide'; const invalidPhone = t.invalidPhone || 'Numéro de téléphone invalide'; const fields = ['firstname', 'lastname', 'phone', 'email', 'address']; fields.forEach(name => clearError(name)); clearError('cgv'); fields.forEach(name => { const el = form[name]; if (!el.value.trim()) { showFieldError(name, requiredMsg); valid = false; } }); const cgvBox = form['cgv']; if (cgvBox && !cgvBox.checked) { showFieldError('cgv', t.cgvRequired || 'Vous devez accepter les Conditions Générales de Vente.'); valid = false; } if (form.email.value.trim() && !isValidEmail(form.email.value.trim())) { showFieldError('email', invalidEmail); valid = false; } if (form.phone.value.trim() && !isValidPhone(form.phone.value.trim())) { showFieldError('phone', invalidPhone); valid = false; } return valid; } function isValidEmail(email) { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); } function isValidPhone(phone) { return /^[+\d][\d\s\-().]{6,20}$/.test(phone); } function showFieldError(name, msg) { const el = document.getElementById(`error-${name}`); const input = document.getElementById(name) || document.querySelector(`[name="${name}"]`); if (el) el.textContent = msg; if (input) input.classList.add('error'); } function clearError(name) { const el = document.getElementById(`error-${name}`); const input = document.getElementById(name) || document.querySelector(`[name="${name}"]`); if (el) el.textContent = ''; if (input) input.classList.remove('error'); } function setLoading(isLoading) { const btn = document.getElementById('submitBtn'); const txt = document.getElementById('submitText'); const form = document.getElementById('contactForm'); const lang = localStorage.getItem('mva-lang') || 'fr'; const t = translations?.[lang]?.contact || {}; if (!btn) return; btn.disabled = isLoading; if (txt) { txt.textContent = isLoading ? (t.submitLoading || 'Envoi en cours...') : (t.submitBtn || "S'inscrire"); } form?.classList.toggle('form-loading', isLoading); } function showSuccess(refNumber) { const successEl = document.getElementById('formSuccess'); const form = document.getElementById('contactForm'); const refDisplay = document.getElementById('refNumberDisplay'); if (refDisplay && refNumber) refDisplay.textContent = refNumber; if (successEl) { successEl.classList.add('show'); successEl.scrollIntoView({ behavior: 'smooth', block: 'center' }); } if (form) form.style.display = 'none'; } function showError() { const errEl = document.getElementById('formErrorGlobal'); const lang = localStorage.getItem('mva-lang') || 'fr'; const t = translations?.[lang]?.contact || {}; if (errEl) { errEl.style.display = 'block'; errEl.textContent = t.errorMsg || 'Une erreur est survenue. Veuillez réessayer ou nous contacter directement.'; } }