import './reserve.scss'; import { UtmEvent, UtmAccount } from "./tools/UtmEvent.js"; import { CookieBanner } from "./tools/CookieBanner.js"; import { FlowReserve } from "./tools/FlowReserve.js"; import { FlowDatePicker } from "./tools/FlowDatePicker.js"; import { FlowAddToCart } from "./tools/FlowAddToCart.js"; import * as Turbo from "@hotwired/turbo"; import { onLCP, onINP, onCLS } from 'web-vitals'; import AOS from 'aos'; import 'aos/dist/aos.css'; // --- CONFIGURATION & ÉTAT --- const CONFIG = { sentryDsn: "https://803814be6540031b1c37bf92ba9c0f79@sentry.esy-web.dev/24", vitalsUrl: '/web-vitals' }; // --- UTILS --- const isLighthouse = () => { if (typeof navigator === 'undefined' || !navigator.userAgent) return false; return ['lighthouse', 'pagespeed', 'headless', 'webdriver'].some(p => navigator.userAgent.toLowerCase().includes(p) ); }; // --- PERFORMANCE (Web Vitals) --- const sendToAnalytics = (metric) => { if (isLighthouse()) return; const body = JSON.stringify({ ...metric, path: window.location.pathname }); if (navigator.sendBeacon) { navigator.sendBeacon(CONFIG.vitalsUrl, body); } else { fetch(CONFIG.vitalsUrl, { body, method: 'POST', keepalive: true }); } }; const initVitals = () => { onLCP(sendToAnalytics); onINP(sendToAnalytics); onCLS(sendToAnalytics); }; // --- SERVICES (Sentry) --- const toggleSentry = async (status) => { if (isLighthouse()) return; try { const Sentry = await import("@sentry/browser"); if (status === 'accepted') { if (!window.SentryInitialized) { window.sentryClient = Sentry.init({ dsn: CONFIG.sentryDsn, tunnel: "/sentry-tunnel", integrations: [Sentry.browserTracingIntegration()], tracesSampleRate: 1.0, }); window.SentryInitialized = true; } else if (window.sentryClient) { window.sentryClient.getOptions().enabled = true; } } else if (status === 'refused' && window.SentryInitialized) { if (window.sentryClient) window.sentryClient.getOptions().enabled = false; } } catch (e) { console.warn("Sentry error", e); } }; // --- UI : ACCESSIBILITÉ (Text-to-Speech) --- const initAccessibility = () => { if (document.getElementById('accessibility-toggle')) return; const btn = document.createElement('button'); btn.id = 'accessibility-toggle'; // Positionné en bas à gauche, fond gris ardoise par défaut btn.className = ` fixed bottom-24 left-8 z-50 p-4 rounded-2xl shadow-xl border-2 border-white/10 transition-all duration-300 hover:scale-110 active:scale-95 `; const updateBtnStyle = () => { const isActive = localStorage.getItem('ldk_tts_active') === 'true'; btn.innerHTML = isActive ? '🔊' : '🔇'; btn.classList.toggle('bg-[#f39e36]', isActive); // Orange si actif btn.classList.toggle('bg-slate-900', !isActive); // Noir si inactif btn.classList.toggle('text-white', true); }; updateBtnStyle(); document.body.appendChild(btn); btn.onclick = () => { const currentState = localStorage.getItem('ldk_tts_active') === 'true'; localStorage.setItem('ldk_tts_active', !currentState); updateBtnStyle(); if (currentState) window.speechSynthesis.cancel(); }; // Écouteur global sur le document pour la lecture au clic document.addEventListener('click', (e) => { if (localStorage.getItem('ldk_tts_active') !== 'true') return; const target = e.target.closest('p, h1, h2, h3, h4, span, label, li'); if (target && target.innerText.trim().length > 0) { window.speechSynthesis.cancel(); const utterance = new SpeechSynthesisUtterance(target.innerText); utterance.lang = 'fr-FR'; // Feedback visuel Ludik Event target.classList.add('outline', 'outline-2', 'outline-[#f39e36]', 'outline-offset-2'); setTimeout(() => target.classList.remove('outline', 'outline-2', 'outline-[#f39e36]', 'outline-offset-2'), 1200); window.speechSynthesis.speak(utterance); } }); }; // --- UI : LOADERS & IMAGES --- const initImageLoader = () => { const images = document.querySelectorAll('main img:not(.loaded)'); images.forEach(img => { if (img.complete) { img.classList.add('loaded'); return; } const parent = img.parentElement; if (!parent) return; parent.classList.add('relative', 'overflow-hidden', 'bg-slate-50'); const loader = document.createElement('div'); loader.className = 'absolute inset-0 flex items-center justify-center z-10 bg-slate-50 transition-opacity duration-500'; loader.innerHTML = `
`; parent.insertBefore(loader, img); img.classList.add('opacity-0', 'transition-opacity', 'duration-700'); img.onload = () => { img.classList.replace('opacity-0', 'opacity-100'); img.classList.add('loaded'); loader.classList.add('opacity-0'); setTimeout(() => loader.remove(), 500); }; img.onerror = () => { loader.innerHTML = '⚠️'; }; }); }; const initTurboLoader = () => { if (document.getElementById('turbo-loader')) return; const loaderEl = document.createElement('div'); loaderEl.id = 'turbo-loader'; loaderEl.className = 'fixed inset-0 z-[9999] flex items-center justify-center bg-white/80 backdrop-blur-sm transition-opacity duration-300 opacity-0 pointer-events-none'; loaderEl.innerHTML = `