Files
ludikevent_crm/templates/revervation/base.twig
Serreau Jovann ff9ae0e8d4 ```
 feat(SitePerformance): Ajoute la collecte des métriques web vitales.
🐛 fix(caddy): Corrige la redirection du script Trustpilot.
📦 chore: Ajoute web-vitals comme dépendance et adapte package.json.
```
2026-01-27 23:36:11 +01:00

251 lines
14 KiB
Twig
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="fr" class="scroll-smooth">
<head>
<meta charset="UTF-8">
{# Correction : Suppression de maximum-scale=1.0 et user-scalable=no pour l'accessibilité #}
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{# --- SEO Fondamental --- #}
<title>
{% block title %}Location Structure Gonflable & Châteaux pour vos Événements | Ludikevent{% endblock %}
</title>
{% if block('description') is defined %}
<meta name="description" content="{{ block('description')|replace({"\n": '', "\r": '', ' ': ''})|trim }}">
{% endif %}
{# URL Canonique dynamique #}
{% block canonical %}
{# Génère l'URL propre automatiquement pour 99% des pages #}
<link rel="canonical" href="{{ app.request.schemeAndHttpHost }}{{ app.request.pathinfo }}">
{% endblock %}
<meta name="keywords" content="location structure gonflable, location chateau gonflable, location barnum, jeux exterieurs, animation anniversaire, location materiel evenementiel, parcours gonflable, location machine barbe a papa, ludikevent">
{# --- Open Graph (Facebook / WhatsApp) --- #}
<meta property="og:type" content="website">
<meta property="og:url" content="{{ app.request.uri }}">
<meta property="og:title" content="{{ block('title') }}">
{% if block('description') is defined %}
<meta property="og:description" content="{{ block('description') }}">
{% endif %}
<meta property="og:image" content="{{ absolute_url(asset('provider/images/favicon.png')) }}">
<meta property="article:publisher" content="https://www.facebook.com/profile.php?id=61574652399326">
{# --- Twitter Card --- #}
<meta name="twitter:card" content="summary">
<meta name="twitter:title"ontent="{{ block('title') }}">
<meta name="twitter:image" content="{{ absolute_url(asset('provider/images/favicon.png')) }}">
{% block extra_header %}
{% endblock %}
{# --- Données Structurées (JSON-LD) --- #}
<script type="application/ld+json">
[
{
"@context": "https://schema.org",
"@type": "LocalBusiness",
"name": "Ludikevent",
"image": "{{ absolute_url(asset('provider/images/favicon.png')) }}",
"telephone": "+33614172447",
"email": "contact@ludikevent.fr",
"url": "{{ app.request.schemeAndHttpHost }}",
"address": {
"@type": "PostalAddress",
"streetAddress": "6 Rue du Château",
"addressLocality": "Danizy",
"postalCode": "02800",
"addressCountry": "FR"
}, c
"geo": {
"@type": "GeoCoordinates",
"latitude": 49.6644,
"longitude": 3.3852
},
"sameAs": [
"https://www.facebook.com/profile.php?id=61574652399326"
],
"priceRange": "€€"
}
]
</script>
{% block jsonld %}{% endblock %}
{# --- PWA & Analytics --- #}
{% if app.environment != 'dev' %}
{{ pwa(swAttributes={ 'nonce': csp_nonce('script') }) }}
<script data-host-url="https://tools-security.esy-web.dev" nonce="{{ csp_nonce('script') }}" defer src="/utm_reserve.js" data-website-id="38d713c3-3923-4791-875a-dfe5f45372c3"></script>
{% else %}
<script data-host-url="https://tools-security.esy-web.dev" nonce="{{ csp_nonce('script') }}" defer src="/utm_reserve.js" data-website-id="bc640e0d-43fb-4c3a-bb17-1ac01cec9643"></script>
{% endif %}
<script nonce="{{ csp_nonce('script') }}" src="/ts.js"></script>
{{ vite_asset('reserve.js',{}) }}
{% block stylesheets %}{% endblock %}
</head>
<body class="bg-gray-50 text-gray-900 font-sans antialiased min-h-screen flex flex-col">
{% if is_granted('ROLE_USER') %}
<utm-account id="{{ app.user.id }}" email="{{ app.user.email }}" name="{{ app.user.name }} {{ app.user.surname }}"></utm-account>
{% endif %}
{# --- NAVIGATION --- #}
<nav class="sticky top-0 z-50 bg-white/95 backdrop-blur-md border-b border-gray-100" role="navigation" aria-label="Menu principal">
<div class="max-w-8xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-20">
{# Logo #}
<div class="flex-shrink-0 flex items-center">
<a href="{{ path('reservation') }}" class="flex items-center gap-2 group">
<img src="{{ asset('provider/images/favicon.png') | imagine_filter('logo') }}"
width="48"
height="48"
class="w-12 h-12 relative z-10 animate-pulse"
alt="Ludikevent">
<span class="text-2xl font-black tracking-tighter uppercase text-[#f39e36]">
{# Correction contraste : amber-500 -> amber-700 pour lisibilité sur blanc #}
Ludik Event</span>
</span>
</a>
</div>
{# Menu Desktop #}
<div class="hidden md:flex items-center space-x-8">
<a href="{{ path('reservation') }}" class="text-gray-700 hover:text-blue-600 font-medium transition-colors">Accueil</a>
<a href="{{ path('reservation_catalogue') }}" class="text-gray-700 hover:text-blue-600 font-medium transition-colors">Nos structures </a>
<a href="{{ path('reservation_formules') }}" class="text-gray-700 hover:text-blue-600 font-medium transition-colors">Nos Formules </a>
<a target="_blank" href="/provider/Catalogue.pdf" class="text-gray-700 hover:text-blue-600 font-medium transition-colors">Catalogue</a>
<a href="{{ path('reservation_workflow') }}" class="text-gray-700 hover:text-blue-600 font-medium transition-colors">Comment Reserver</a>
<a href="{{ path('reservation_contact') }}" class="text-gray-700 hover:text-blue-600 font-medium transition-colors">Contact</a>
<a href="{{ path('reservation_search') }}" class="p-2 text-gray-600 hover:text-blue-600 transition-colors" aria-label="Rechercher une structure">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
</a>
{% if app.user %}
<div class="flex items-center gap-4">
{% if is_granted('ROLE_ADMIN') %}
<a target="_blank" href="https://intranet.ludikevent.fr/crm" class="text-xs font-black uppercase tracking-widest text-amber-800 bg-amber-50 px-3 py-1 rounded-full border border-amber-200 hover:bg-amber-100 transition-colors">
Admin
</a>
{% endif %}
<a href="{{ path('gestion_contrat') }}" class="text-[#f39e36] flex items-center gap-2 font-bold hover:opacity-70 transition-opacity">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/></svg>
Mon Espace
</a>
<a href="{{ path('reservation_logout') }}" class="text-gray-500 hover:text-red-600 transition-colors" title="Déconnexion" aria-label="Se déconnecter">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"/></svg>
</a>
</div>
{% else %}
<a href="{{ path('reservation_login') }}" class="text-[#f39e36] font-bold transition-colors flex items-center gap-2">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"/></svg>
Connexion
</a>
{% endif %}
<a href="tel:0614172447" class="inline-flex items-center px-6 py-3 border border-transparent text-sm font-bold rounded-full text-white bg-[#f39e36] shadow-lg shadow-blue-200 transition-all hover:-translate-y-0.5">
06 14 17 24 47
</a>
</div>
{# Bouton Menu Mobile #}
<div class="md:hidden flex items-center">
{# Correction : Ajout de aria-label pour le nom accessible #}
<button id="menu-button" type="button" class="text-gray-700 p-2 focus:outline-none" aria-expanded="false" aria-controls="mobile-menu" aria-label="Ouvrir le menu">
<svg class="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16m-7 6h7" />
</svg>
</button>
</div>
</div>
</div>
{# Menu Mobile #}
<div id="mobile-menu" class="hidden md:hidden bg-white border-t border-gray-100 shadow-xl">
<div class="px-4 pt-2 pb-6 space-y-2">
<a href="{{ path('reservation') }}" class="block px-3 py-2 text-base font-medium text-gray-700 hover:bg-gray-50 rounded-xl">Accueil</a>
<a href="{{ path('reservation_catalogue') }}" class="block px-3 py-2 text-base font-medium text-gray-700 hover:bg-gray-50 rounded-xl">Nos structures</a>
<a href="{{ path('reservation_formules') }}" class="text-gray-700 hover:text-blue-600 font-medium transition-colors">Nos Formules </a>
<a target="_blank" href="/provider/Catalogue.pdf" class="block px-3 py-2 text-base font-medium text-gray-700 hover:bg-gray-50 rounded-xl">Catalogue</a>
<a href="{{ path('reservation_workflow') }}" class="block px-3 py-2 text-base font-medium text-gray-700 hover:bg-gray-50 rounded-xl">Comment reserver</a>
<a href="{{ path('reservation_search') }}" class="block px-3 py-2 text-base font-medium text-gray-700 hover:bg-gray-50 rounded-xl">Rechercher</a>
<div class="pt-4 border-t border-gray-50">
<a href="tel:0614172447" class="block px-3 py-3 text-center bg-blue-600 text-white rounded-xl font-bold">
Appeler le 06 14 17 24 47
</a>
</div>
</div>
</div>
</nav>
{# --- MESSAGES FLASH --- #}
{% for label, messages in app.flashes %}
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 mt-4" role="alert">
{% for message in messages %}
<div class="flex items-center justify-between p-4 rounded-2xl shadow-lg border
{% if label == 'success' %} bg-emerald-50 border-emerald-200 text-emerald-900
{% elseif label == 'error' or label == 'danger' %} bg-red-50 border-red-200 text-red-900
{% else %} bg-blue-50 border-blue-200 text-blue-900 {% endif %}">
<div class="flex items-center gap-3">
<span class="text-xl" aria-hidden="true">
{% if label == 'success' %}{% elseif label == 'error' or label == 'danger' %}{% else %}{% endif %}
</span>
<p class="text-sm font-bold uppercase italic">{{ message }}</p>
</div>
<button onclick="this.parentElement.remove()" class="p-2 hover:opacity-50" aria-label="Fermer la notification">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
{% endfor %}
</div>
{% endfor %}
{# --- CONTENU --- #}
<main class="flex-grow" id="main-content" role="main">
{% block body %}{% endblock %}
</main>
{# --- PIED DE PAGE --- #}
<footer class="bg-white border-t border-gray-100 py-10 mt-auto" role="contentinfo">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex flex-col md:flex-row justify-between items-center gap-8">
<div class="text-center md:text-left">
<p class="text-sm text-gray-700">
&copy; {{ "now"|date("Y") }} <span class="font-bold text-[#f39e36]">Ludikevent</span>.
Tous droits réservés.
</p>
{# Correction contraste : gray-400 -> gray-600 #}
<p class="text-xs text-gray-600 mt-1">Location de structures gonflables de haute qualité.</p>
</div>
{# Correction contraste liens : text-gray-500 -> text-gray-700 #}
<div class="flex flex-wrap justify-center gap-x-6 gap-y-2 text-xs text-gray-700 font-semibold">
<a href="{{ path('reservation_mentions-legal') }}" class="hover:text-blue-700 transition-colors">Mentions légales</a>
<a href="{{ path('reservation_cgv') }}" class="hover:text-blue-700 transition-colors">CGV</a>
<a href="{{ path('reservation_rgpd') }}" class="hover:text-blue-700 transition-colors">RGPD</a>
<a href="{{ path('reservation_cookies') }}" class="hover:text-blue-700 transition-colors">Cookies</a>
</div>
<div class="flex items-center gap-4">
<a href="https://www.facebook.com/profile.php?id=61574652399326" target="_blank" rel="noopener" class="text-gray-500 hover:text-blue-700 transition-colors" aria-label="Suivre Ludikevent sur Facebook">
<svg class="h-6 w-6" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M22 12c0-5.523-4.477-10-10-10S2 6.477 2 12c0 4.991 3.657 9.128 8.438 9.878v-6.987h-2.54V12h2.54V9.797c0-2.506 1.492-3.89 3.777-3.89 1.094 0 2.238.195 2.238.195v2.46h-1.26c-1.243 0-1.63.771-1.63 1.562V12h2.773l-.443 2.89h-2.33v6.988C18.343 21.128 22 16.991 22 12z"/></svg>
</a>
</div>
</div>
</div>
</footer>
<cookie-banner></cookie-banner>
{% block javascripts %}{% endblock %}
</body>
</html>