import './app.scss' import * as Turbo from "@hotwired/turbo" import '@grafikart/drop-files-element' import {PaymentForm} from './PaymentForm.js' import * as Sentry from "@sentry/browser"; // --- CONFIGURATION ET ETAT --- const VAPID_PUBLIC_KEY = "BKz0kdcsG6kk9KxciPpkfP8kEDAd408inZecij5kBDbQ1ZGZSNwS4KZ8FerC28LFXvgSqpDXtor3ePo0zBCdNqo"; const COOKIE_STORAGE_KEY = 'cookies_accepted'; let userMenuTimeout; // Pour gérer le délai de fermeture du menu const MESSAGES = { fr: { notificationTitle: "🔔 Activer les notifications", notificationText: "Recevez les nouvelles, les promotions et les événements de l'association.", notificationButton: "Activer", notificationClose: "Fermer la notification", cookieText: 'Ce site utilise uniquement des cookies de fonctionnement et de sécurité essentiels.', cookieLink: "Politique de cookies", cookieButton: "Accepter", }, en: { notificationTitle: "🔔 Enable Notifications", notificationText: "Receive news, promotions, and association events.", notificationButton: "Enable", notificationClose: "Close notification", cookieText: 'This website only uses functional and security cookies.', cookieLink: "Cookie Policy", cookieButton: "Accept", } }; function getLanguageMessages() { let langCode = 'fr'; const htmlLang = document.documentElement.lang; if (htmlLang) { const normalizedHtmlLang = htmlLang.toLowerCase().substring(0, 2); if (normalizedHtmlLang === 'en') langCode = 'en'; } return MESSAGES[langCode]; } function urlBase64ToUint8Array(base64String) { const padding = '='.repeat((4 - base64String.length % 4) % 4); const base64 = (base64String + padding).replace(/\-/g, '+').replace(/_/g, '/'); const rawData = window.atob(base64); const outputArray = new Uint8Array(rawData.length); for (let i = 0; i < rawData.length; ++i) { outputArray[i] = rawData.charCodeAt(i); } return outputArray; } function toggleMenu(button, menu) { if (!button || !menu) return; const isExpanded = button.getAttribute('aria-expanded') === 'true' || false; button.setAttribute('aria-expanded', !isExpanded); menu.classList.toggle('hidden'); } /** * Initialisation de l'UI */ function initializeUI() { document.querySelectorAll('#mobile-menu, #userMenuDesktop, #userMenuMobile').forEach(menu => { menu.classList.add('hidden'); }); const cartSidebar = document.getElementById('cartSidebar'); const cartBackdrop = document.getElementById('cartBackdrop'); if (cartSidebar) { window.openCart = () => { document.body.style.overflow = 'hidden'; if (cartBackdrop) cartBackdrop.classList.remove('hidden'); cartSidebar.classList.remove('translate-x-full'); cartSidebar.classList.add('translate-x-0'); }; window.closeCart = () => { document.body.style.overflow = ''; cartSidebar.classList.remove('translate-x-0'); cartSidebar.classList.add('translate-x-full'); if (cartBackdrop) { setTimeout(() => cartBackdrop.classList.add('hidden'), 300); } }; } const updateCartDisplay = (count) => { const desktopCounter = document.getElementById('cartCountDesktop'); const mobileCounter = document.getElementById('cartCountMobile'); if (desktopCounter) desktopCounter.textContent = count; if (mobileCounter) mobileCounter.textContent = count; }; updateCartDisplay(0); // Initialisation spécifique au menu utilisateur (Desktop) setupUserMenuHover(); if ('Notification' in window && Notification.permission === 'granted') { subscribeAndSave(); } } /** * Gestion du survol du menu utilisateur pour éviter la fermeture brutale */ function setupUserMenuHover() { const btn = document.getElementById('userMenuButtonDesktop'); const menu = document.getElementById('userMenuDesktop'); if (!btn || !menu) return; const open = () => { clearTimeout(userMenuTimeout); menu.classList.remove('hidden'); }; const close = () => { userMenuTimeout = setTimeout(() => { menu.classList.add('hidden'); }, 200); // Délai de 200ms pour laisser le temps de passer du bouton au menu }; btn.addEventListener('mouseenter', open); btn.addEventListener('mouseleave', close); menu.addEventListener('mouseenter', open); menu.addEventListener('mouseleave', close); } // --- LOGIQUE PUSH & BANNIÈRES (Inchangé) --- async function subscribeAndSave() { if (!('Notification' in window) || Notification.permission !== 'granted') return; if (!('serviceWorker' in navigator)) return; try { const registration = await navigator.serviceWorker.ready; let subscription = await registration.pushManager.getSubscription(); if (!subscription) { const applicationServerKey = urlBase64ToUint8Array(VAPID_PUBLIC_KEY); subscription = await registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: applicationServerKey }); } await fetch('/notificationSub', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ subscription: subscription.toJSON() }) }); } catch (error) { console.error("Push Error:", error); } } async function promptForPermissionAndSubscribe() { if (!('Notification' in window)) return; try { const permission = await Notification.requestPermission(); if (permission === 'granted') await subscribeAndSave(); } catch (error) { console.error("Permission Error:", error); } } function isPerformanceTestAgent() { const ua = navigator.userAgent; return ua.includes('Lighthouse') || ua.includes('PageSpeed'); } function handleNotificationBanner() { if (isPerformanceTestAgent()) return; const BANNER_ID = 'notification-prompt-banner'; if ('Notification' in window && Notification.permission === 'granted') return; if (document.getElementById(BANNER_ID)) return; const M = getLanguageMessages(); const banner = document.createElement('div'); banner.id = BANNER_ID; banner.className = `fixed bottom-4 left-4 z-50 p-4 max-w-xs bg-indigo-600 text-white rounded-xl shadow-2xl transition-all duration-500 transform opacity-0 translate-y-full md:left-8 md:bottom-8 border-2 border-black`; banner.innerHTML = `
${M.notificationTitle}
${M.notificationText}
`; document.body.appendChild(banner); setTimeout(() => { banner.classList.remove('opacity-0', 'translate-y-full'); banner.classList.add('opacity-100', 'translate-y-0'); }, 100); document.getElementById('closeNotificationBanner').addEventListener('click', () => banner.remove()); document.getElementById('activateNotifications').addEventListener('click', async () => { await promptForPermissionAndSubscribe(); banner.remove(); }); } function handleCookieBanner() { if (isPerformanceTestAgent()) return; if (localStorage.getItem(COOKIE_STORAGE_KEY) === 'true') return; const BANNER_ID = 'cookie-banner'; if (document.getElementById(BANNER_ID)) return; const M = getLanguageMessages(); const banner = document.createElement('div'); banner.id = BANNER_ID; banner.className = `fixed bottom-4 right-4 z-50 p-6 max-w-sm bg-white border-4 border-black shadow-[10px_10px_0px_rgba(0,0,0,1)] transition-all duration-500 transform opacity-0 translate-y-full`; banner.innerHTML = `${M.cookieText}
`; document.body.appendChild(banner); setTimeout(() => { banner.classList.remove('opacity-0', 'translate-y-full'); banner.classList.add('opacity-100', 'translate-y-0'); }, 200); document.getElementById('acceptCookies').addEventListener('click', () => { localStorage.setItem(COOKIE_STORAGE_KEY, 'true'); banner.remove(); }); } // --- BOOTSTRAP --- document.addEventListener('DOMContentLoaded', () => { if (!customElements.get('payment-don')) { customElements.define('payment-don', PaymentForm, {extends: 'form'}); } initializeUI(); if (!isPerformanceTestAgent()) { handleNotificationBanner(); handleCookieBanner(); var BASE_URL_WOOT = "https://chat.esy-web.dev"; let script = document.createElement('script'); script.setAttribute('src', BASE_URL_WOOT + "/packs/js/sdk.js"); script.defer = true; document.head.append(script); script.onload = () => { window.chatwootSDK.run({ websiteToken: '6uFX3g3qybyvSt3PAQUMgkm4', baseUrl: BASE_URL_WOOT }); }; } }); document.addEventListener('turbo:load', () => { initializeUI(); }); document.addEventListener('click', (event) => { const target = event.target; const mobileMenuButton = target.closest('#mobileMenuButton'); if (mobileMenuButton) { toggleMenu(mobileMenuButton, document.getElementById('mobile-menu')); return; } const openCartBtn = target.closest('#openCartDesktop, #openCartMobile'); if (openCartBtn && window.openCart) { event.preventDefault(); window.openCart(); return; } const closeCartBtn = target.closest('#closeCartButton') || target === document.getElementById('cartBackdrop'); if (closeCartBtn && window.closeCart) { window.closeCart(); return; } }); document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && window.closeCart) window.closeCart(); });