```
✨ feat(templates): [FR] Améliore l'UI et ajoute des traductions pour plus de contenu dynamique.
```
This commit is contained in:
@@ -4,18 +4,18 @@ import '@grafikart/drop-files-element'
|
||||
import {PaymentForm} from './PaymentForm'
|
||||
import * as Sentry from "@sentry/browser";
|
||||
|
||||
// --- CLÉS DE STOCKAGE ET VAPID ---
|
||||
// --- 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
|
||||
|
||||
// --- MESSAGES ET TRADUCTIONS ---
|
||||
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 <strong>fonctionnement</strong> et de <strong>sécurité</strong> essentiels. Aucune donnée personnelle n\'est collectée.',
|
||||
cookieText: 'Ce site utilise uniquement des cookies de <strong>fonctionnement</strong> et de <strong>sécurité</strong> essentiels.',
|
||||
cookieLink: "Politique de cookies",
|
||||
cookieButton: "Accepter",
|
||||
},
|
||||
@@ -24,7 +24,7 @@ const MESSAGES = {
|
||||
notificationText: "Receive news, promotions, and association events.",
|
||||
notificationButton: "Enable",
|
||||
notificationClose: "Close notification",
|
||||
cookieText: 'This website only uses <strong>functional</strong> and <strong>security</strong> cookies. No personal data is collected.',
|
||||
cookieText: 'This website only uses <strong>functional</strong> and <strong>security</strong> cookies.',
|
||||
cookieLink: "Cookie Policy",
|
||||
cookieButton: "Accept",
|
||||
}
|
||||
@@ -62,12 +62,10 @@ function toggleMenu(button, menu) {
|
||||
* Initialisation de l'UI
|
||||
*/
|
||||
function initializeUI() {
|
||||
// Reset des menus au chargement
|
||||
document.querySelectorAll('#mobile-menu, #userMenuDesktop, #userMenuMobile').forEach(menu => {
|
||||
menu.classList.add('hidden');
|
||||
});
|
||||
|
||||
// Panier Latéral
|
||||
const cartSidebar = document.getElementById('cartSidebar');
|
||||
const cartBackdrop = document.getElementById('cartBackdrop');
|
||||
|
||||
@@ -78,7 +76,6 @@ function initializeUI() {
|
||||
cartSidebar.classList.remove('translate-x-full');
|
||||
cartSidebar.classList.add('translate-x-0');
|
||||
};
|
||||
|
||||
window.closeCart = () => {
|
||||
document.body.style.overflow = '';
|
||||
cartSidebar.classList.remove('translate-x-0');
|
||||
@@ -89,7 +86,6 @@ function initializeUI() {
|
||||
};
|
||||
}
|
||||
|
||||
// Update counters
|
||||
const updateCartDisplay = (count) => {
|
||||
const desktopCounter = document.getElementById('cartCountDesktop');
|
||||
const mobileCounter = document.getElementById('cartCountMobile');
|
||||
@@ -98,20 +94,47 @@ function initializeUI() {
|
||||
};
|
||||
updateCartDisplay(0);
|
||||
|
||||
// Initialisation spécifique au menu utilisateur (Desktop)
|
||||
setupUserMenuHover();
|
||||
|
||||
if ('Notification' in window && Notification.permission === 'granted') {
|
||||
subscribeAndSave();
|
||||
}
|
||||
}
|
||||
|
||||
// --- LOGIQUE PUSH NOTIFICATIONS ---
|
||||
/**
|
||||
* 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({
|
||||
@@ -119,15 +142,12 @@ async function subscribeAndSave() {
|
||||
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);
|
||||
}
|
||||
} catch (error) { console.error("Push Error:", error); }
|
||||
}
|
||||
|
||||
async function promptForPermissionAndSubscribe() {
|
||||
@@ -135,18 +155,14 @@ async function promptForPermissionAndSubscribe() {
|
||||
try {
|
||||
const permission = await Notification.requestPermission();
|
||||
if (permission === 'granted') await subscribeAndSave();
|
||||
} catch (error) {
|
||||
console.error("Permission Error:", error);
|
||||
}
|
||||
} catch (error) { console.error("Permission Error:", error); }
|
||||
}
|
||||
|
||||
// --- OPTIMISATION PERFORMANCE ---
|
||||
function isPerformanceTestAgent() {
|
||||
const ua = navigator.userAgent;
|
||||
return ua.includes('Lighthouse') || ua.includes('PageSpeed');
|
||||
}
|
||||
|
||||
// --- BANNIÈRES ---
|
||||
function handleNotificationBanner() {
|
||||
if (isPerformanceTestAgent()) return;
|
||||
const BANNER_ID = 'notification-prompt-banner';
|
||||
@@ -157,7 +173,6 @@ function handleNotificationBanner() {
|
||||
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 = `
|
||||
<div class="flex items-start justify-between italic">
|
||||
<p class="font-black uppercase text-xs tracking-widest">${M.notificationTitle}</p>
|
||||
@@ -170,13 +185,11 @@ function handleNotificationBanner() {
|
||||
${M.notificationButton}
|
||||
</button>
|
||||
`;
|
||||
|
||||
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();
|
||||
@@ -189,12 +202,10 @@ function handleCookieBanner() {
|
||||
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 = `
|
||||
<p class="text-xs font-bold uppercase italic leading-relaxed text-gray-600">${M.cookieText}</p>
|
||||
<div class="mt-4 flex justify-end items-center gap-4">
|
||||
@@ -204,78 +215,58 @@ function handleCookieBanner() {
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
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();
|
||||
});
|
||||
}
|
||||
|
||||
// --- DOM READY & TURBO ---
|
||||
// --- BOOTSTRAP ---
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
if (!customElements.get('payment-don')) {
|
||||
customElements.define('payment-don', PaymentForm, {extends: 'form'});
|
||||
}
|
||||
initializeUI();
|
||||
|
||||
if (!isPerformanceTestAgent()) {
|
||||
handleNotificationBanner();
|
||||
handleCookieBanner();
|
||||
|
||||
// Chatwoot
|
||||
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
|
||||
});
|
||||
window.chatwootSDK.run({ websiteToken: '6uFX3g3qybyvSt3PAQUMgkm4', baseUrl: BASE_URL_WOOT });
|
||||
};
|
||||
}
|
||||
|
||||
const env = document.querySelector('meta[name="env"]');
|
||||
if (env && env.getAttribute('content') === "prod") {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.register('/sw.js');
|
||||
}
|
||||
if (env && env.getAttribute('content') === "prod" && 'serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.register('/sw.js');
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('turbo:load', () => {
|
||||
initializeUI();
|
||||
handleNotificationBanner();
|
||||
handleCookieBanner();
|
||||
});
|
||||
|
||||
// --- DÉLÉGATION D'ÉVÉNEMENTS ---
|
||||
document.addEventListener('click', (event) => {
|
||||
const target = event.target;
|
||||
|
||||
// Menu Mobile
|
||||
const mobileMenuButton = target.closest('#mobileMenuButton');
|
||||
if (mobileMenuButton) {
|
||||
const menu = document.getElementById('mobile-menu');
|
||||
toggleMenu(mobileMenuButton, menu);
|
||||
toggleMenu(mobileMenuButton, document.getElementById('mobile-menu'));
|
||||
return;
|
||||
}
|
||||
|
||||
// Panier
|
||||
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();
|
||||
|
||||
@@ -9,3 +9,8 @@
|
||||
.epage{
|
||||
color: orangered;
|
||||
}
|
||||
|
||||
#userMenuDesktop {
|
||||
margin-top: -4px; /* Remonte légèrement le menu pour toucher le bouton */
|
||||
padding-top: 10px; /* Ajoute du padding interne pour garder la zone réactive */
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user