feat(UtmEvent): Ajoute le tracking Umami des utilisateurs connectés.

Ajoute l'identification des utilisateurs Umami et enregistre la session.
Implémente une bannière de consentement pour les cookies et gère l'état.
```
This commit is contained in:
Serreau Jovann
2026-01-27 20:24:02 +01:00
parent 52e92b4230
commit 454b748973
13 changed files with 485 additions and 114 deletions

View File

@@ -1,5 +1,6 @@
import './reserve.scss';
import { UtmEvent, UtmAccount } from "./tools/UtmEvent.js";
import { CookieBanner } from "./tools/CookieBanner.js";
import * as Turbo from "@hotwired/turbo";
// --- DÉTECTION BOT / PERFORMANCE ---
@@ -10,38 +11,54 @@ const isLighthouse = () => {
return patterns.some(pattern => userAgent.includes(pattern));
};
// --- INITIALISATION SENTRY ---
const initSentry = async () => {
if (!isLighthouse() && !window.SentryInitialized) {
try {
const Sentry = await import("@sentry/browser");
Sentry.init({
dsn: "https://803814be6540031b1c37bf92ba9c0f79@sentry.esy-web.dev/24",
tunnel: "/sentry-tunnel",
integrations: [Sentry.browserTracingIntegration()],
tracesSampleRate: 1.0,
});
window.SentryInitialized = true; // Empêche la ré-initialisation
} catch (e) {
console.warn("Sentry load failed", e);
// --- GESTION DYNAMIQUE DE 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: "https://803814be6540031b1c37bf92ba9c0f79@sentry.esy-web.dev/24",
tunnel: "/sentry-tunnel",
integrations: [Sentry.browserTracingIntegration()],
tracesSampleRate: 1.0,
});
window.SentryInitialized = true;
console.log("✔️ Sentry initialisé et activé");
} else {
// Réactivation si déjà chargé
if (window.sentryClient) window.sentryClient.getOptions().enabled = true;
console.log("✔️ Sentry ré-activé");
}
}
if (status === 'refused' && window.SentryInitialized) {
// Désactivation sans décharger le script
if (window.sentryClient) window.sentryClient.getOptions().enabled = false;
console.log("🛑 Sentry désactivé (Client muet)");
}
} catch (e) {
console.warn("Sentry toggle failed", e);
}
};
// --- LOGIQUE DU LOADER TURBO (Unique à travers les pages) ---
// --- LOGIQUE DU LOADER TURBO ---
const initLoader = () => {
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 transition-opacity duration-300 opacity-100 pointer-events-none';
loaderEl.innerHTML = `
<div class="relative flex items-center justify-center">
<div class="absolute w-24 h-24 border-4 border-[#f39e36] border-t-transparent rounded-full animate-spin"></div>
<img src="/provider/images/favicon.webp" class="w-12 h-12 relative z-10 animate-pulse" alt="Logo">
</div>
`;
document.body.appendChild(loaderEl);
const loaderEl = document.createElement('div');
loaderEl.id = 'turbo-loader';
loaderEl.className = 'fixed inset-0 z-[9999] flex items-center justify-center bg-white transition-opacity duration-300 opacity-0 pointer-events-none';
loaderEl.innerHTML = `
<div class="relative flex items-center justify-center">
<div class="absolute w-24 h-24 border-4 border-[#f39e36] border-t-transparent rounded-full animate-spin"></div>
<img src="/provider/images/favicon.webp" class="w-12 h-12 relative z-10 animate-pulse" alt="Logo">
</div>
`;
document.body.appendChild(loaderEl);
document.addEventListener("turbo:click", () => {
loaderEl.classList.replace('opacity-0', 'opacity-100');
@@ -59,13 +76,11 @@ const initLoader = () => {
document.addEventListener("turbo:render", hideLoader);
};
// --- LOGIQUE DU MENU MOBILE (Compatible Turbo) ---
// --- LOGIQUE INTERFACE (Menu, Filtres, Redirect, Register) ---
const initMobileMenu = () => {
const btn = document.getElementById('menu-button');
const menu = document.getElementById('mobile-menu');
if (btn && menu) {
// On enlève l'ancien listener pour éviter les doublons au retour arrière
btn.onclick = null;
btn.addEventListener('click', () => {
const isExpanded = btn.getAttribute('aria-expanded') === 'true';
@@ -75,57 +90,46 @@ const initMobileMenu = () => {
}
};
// --- LOGIQUE FILTRE CATALOGUE ---
const initCatalogueSearch = () => {
const filters = document.querySelectorAll('.filter-btn');
const products = document.querySelectorAll('.product-item');
const emptyMsg = document.getElementById('empty-msg');
if (filters.length === 0) return;
filters.forEach(btn => {
btn.onclick = () => {
const category = btn.getAttribute('data-filter').toLowerCase();
let count = 0;
// Update UI des filtres
filters.forEach(f => f.classList.replace('bg-slate-900', 'bg-white'));
filters.forEach(f => f.classList.replace('text-white', 'text-slate-500'));
filters.forEach(f => {
f.classList.replace('bg-slate-900', 'bg-white');
f.classList.replace('text-white', 'text-slate-500');
});
btn.classList.replace('bg-white', 'bg-slate-900');
btn.classList.replace('text-slate-500', 'text-white');
// Filtrage des produits
products.forEach(item => {
const itemCat = item.getAttribute('data-category').toLowerCase();
const itemCat = (item.getAttribute('data-category') || '').toLowerCase();
const isVisible = category === 'all' || itemCat.includes(category);
item.style.display = isVisible ? 'block' : 'none';
if (isVisible) count++;
});
if (emptyMsg) count === 0 ? emptyMsg.classList.remove('hidden') : emptyMsg.classList.add('hidden');
};
});
};
// --- LOGIQUE DU REDIRECT ---
const initAutoRedirect = () => {
const container = document.getElementById('payment-check-container');
if (container && container.dataset.autoRedirect) {
const url = container.dataset.autoRedirect;
setTimeout(() => {
// On vérifie que l'utilisateur est toujours sur la page de paiement
if (document.getElementById('payment-check-container')) {
Turbo.visit(url);
}
if (document.getElementById('payment-check-container')) Turbo.visit(url);
}, 10000);
}
}
};
const initRegisterLogic = () => {
const siretContainer = document.getElementById('siret-container');
const typeRadios = document.querySelectorAll('input[name="type"]');
if (!siretContainer || typeRadios.length === 0) return;
const updateSiretVisibility = () => {
const selectedType = document.querySelector('input[name="type"]:checked')?.value;
if (selectedType === 'buisness') {
@@ -136,25 +140,28 @@ const initRegisterLogic = () => {
siretContainer.querySelector('input')?.removeAttribute('required');
}
};
typeRadios.forEach(radio => {
radio.addEventListener('change', updateSiretVisibility);
});
// Initialisation au chargement (si redirection avec erreur par exemple)
typeRadios.forEach(radio => radio.addEventListener('change', updateSiretVisibility));
updateSiretVisibility();
};
// --- INITIALISATION GLOBALE ---
document.addEventListener('DOMContentLoaded', () => {
initSentry();
initLoader();
// Custom Elements (une seule fois suffit)
// Enregistrement Custom Elements
if (!customElements.get('utm-event')) customElements.define('utm-event', UtmEvent);
if (!customElements.get('utm-account')) customElements.define('utm-account', UtmAccount);
if (!customElements.get('cookie-banner')) customElements.define('cookie-banner', CookieBanner);
// Initialisation Sentry basée sur le choix existant
const currentConsent = sessionStorage.getItem('ldk_cookie');
if (currentConsent) toggleSentry(currentConsent);
// Écouteurs pour changements de choix cookies
window.addEventListener('cookieAccepted', () => toggleSentry('accepted'));
window.addEventListener('cookieRefused', () => toggleSentry('refused'));
});
// À chaque changement de page Turbo
document.addEventListener('turbo:load', () => {
initMobileMenu();
initCatalogueSearch();
@@ -162,7 +169,6 @@ document.addEventListener('turbo:load', () => {
initRegisterLogic();
});
// Nettoyage avant la mise en cache de Turbo (évite les bugs visuels au retour arrière)
document.addEventListener("turbo:before-cache", () => {
document.querySelectorAll('.product-item').forEach(i => i.style.display = 'block');
const emptyMsg = document.getElementById('empty-msg');