<?php
use Twig\Environment;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Extension\CoreExtension;
use Twig\Extension\SandboxExtension;
use Twig\Markup;
use Twig\Sandbox\SecurityError;
use Twig\Sandbox\SecurityNotAllowedTagError;
use Twig\Sandbox\SecurityNotAllowedFilterError;
use Twig\Sandbox\SecurityNotAllowedFunctionError;
use Twig\Source;
use Twig\Template;
use Twig\TemplateWrapper;
/* base_home.html.twig */
class __TwigTemplate_90b41beb24c02f5a72f80f659d5bffef extends Template
{
private Source $source;
/**
* @var array<string, Template>
*/
private array $macros = [];
public function __construct(Environment $env)
{
parent::__construct($env);
$this->source = $this->getSourceContext();
$this->parent = false;
$this->blocks = [
'title' => [$this, 'block_title'],
'stylesheets' => [$this, 'block_stylesheets'],
'body' => [$this, 'block_body'],
'javascripts' => [$this, 'block_javascripts'],
];
}
protected function doDisplay(array $context, array $blocks = []): iterable
{
$macros = $this->macros;
$__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
$__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "template", "base_home.html.twig"));
$__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "template", "base_home.html.twig"));
// line 1
yield "<!DOCTYPE html>
<html lang=\"fr\" class=\"no-js\" data-theme=\"light\" data-bs-theme=\"light\">
<head>
<!-- Mobile Specific Meta -->
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no\">
<meta name=\"mobile-web-app-capable\" content=\"yes\">
<meta name=\"apple-mobile-web-app-capable\" content=\"yes\">
<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"default\">
<meta name=\"apple-mobile-web-app-title\" content=\"MaketOu\">
<meta name=\"theme-color\" content=\"#ffa200\">
<meta name=\"msapplication-TileColor\" content=\"#ffa200\">
<meta name=\"msapplication-config\" content=\"";
// line 13
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("favicon/browserconfig.xml"), "html", null, true);
yield "\">
<!-- Favicon-->
<link rel=\"shortcut icon\" href=\"";
// line 16
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("favicon/favicon-16x16.png"), "html", null, true);
yield "\">
<link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"";
// line 17
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("favicon/apple-touch-icon.png"), "html", null, true);
yield "\">
<link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"";
// line 18
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("favicon/favicon-32x32.png"), "html", null, true);
yield "\">
<link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"";
// line 19
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("favicon/favicon-16x16.png"), "html", null, true);
yield "\">
<!-- PWA Manifest -->
<link rel=\"manifest\" href=\"";
// line 22
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("manifest.json"), "html", null, true);
yield "\">
<!-- Author Meta -->
<meta name=\"author\" content=\"Foulgor Tech\">
<!-- Meta Description -->
<meta name=\"description\" content=\"\">
<!-- Meta Keyword -->
<meta name=\"keywords\" content=\"\">
<!-- meta character set -->
<meta charset=\"UTF-8\">
<!-- Site Title -->
<title>";
// line 32
yield from $this->unwrap()->yieldBlock('title', $context, $blocks);
yield "</title>
<script>
(function () {
try {
var storageKey = 'maketou-theme';
var savedTheme = window.localStorage.getItem(storageKey);
var theme = savedTheme === 'dark' || savedTheme === 'light'
? savedTheme
: (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', theme);
document.documentElement.setAttribute('data-bs-theme', theme);
document.documentElement.classList.toggle('dark-mode', theme === 'dark');
} catch (error) {
document.documentElement.setAttribute('data-theme', 'light');
document.documentElement.setAttribute('data-bs-theme', 'light');
}
})();
</script>
<!--
CSS
============================================= -->
<link rel=\"stylesheet\" href=\"https://unpkg.com/dropzone@5/dist/min/dropzone.min.css\" />
<link rel=\"stylesheet\" href=\"";
// line 54
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/linearicons.css"), "html", null, true);
yield "\">
<link rel=\"stylesheet\" href=\"";
// line 55
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/font-awesome.min.css"), "html", null, true);
yield "\">
<link rel=\"stylesheet\" href=\"";
// line 56
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/themify-icons.css"), "html", null, true);
yield "\">
<link rel=\"stylesheet\" href=\"";
// line 57
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/bootstrap.css"), "html", null, true);
yield "\">
<link rel=\"stylesheet\" href=\"";
// line 58
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/owl.carousel.css"), "html", null, true);
yield "\">
<link rel=\"stylesheet\" href=\"";
// line 59
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/nice-select.css"), "html", null, true);
yield "\">
<link rel=\"stylesheet\" href=\"";
// line 60
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/nouislider.min.css"), "html", null, true);
yield "\">
<link rel=\"stylesheet\" href=\"";
// line 61
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/ion.rangeSlider.css"), "html", null, true);
yield "\"/>
<link rel=\"stylesheet\" href=\"";
// line 62
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/ion.rangeSlider.skinFlat.css"), "html", null, true);
yield "\"/>
<link rel=\"stylesheet\" href=\"";
// line 63
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/magnific-popup.css"), "html", null, true);
yield "\">
<link rel=\"stylesheet\" href=\"";
// line 64
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/main.css"), "html", null, true);
yield "\">
<link rel=\"stylesheet\" href=\"";
// line 65
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/buttons-unified.css"), "html", null, true);
yield "\">
<link rel=\"stylesheet\" href=\"";
// line 66
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/theme-public.css"), "html", null, true);
yield "\">
<meta charset=\"UTF-8\">
";
// line 69
yield "
<style>
/* Styles pour l'icône de notification */
.notification-icon {
position: relative;
display: inline-block;
color: #333;
text-decoration: none;
transition: color 0.3s ease;
}
.notification-icon:hover {
color: #007bff;
}
.notification-badge {
position: absolute;
top: -4px;
right: -2px;
background: #dc3545 !important;
color: white !important;
border-radius: 50%;
width: 18px;
height: 18px;
font-size: 8px !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
font-weight: bold !important;
animation: pulse 2s infinite;
z-index: 10;
line-height: 1 !important;
}
/* Forcer le texte en blanc pour tous les éléments du badge - avec spécificité maximale */
.notification-badge,
.notification-badge.text-white,
.notification-badge *,
#notificationBadge,
#notificationBadge.text-white,
#notificationBadge *,
span.notification-badge,
span.notification-badge.text-white,
span#notificationBadge,
span#notificationBadge.text-white {
color: white !important;
text-color: white !important;
-webkit-text-fill-color: white !important;
}
/* S'assurer que le contenu texte est bien en blanc */
.notification-badge::before,
.notification-badge::after {
color: white !important;
}
/* Forcer la couleur pour tous les sélecteurs possibles avec spécificité maximale */
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon .notification-badge,
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon .notification-badge.text-white,
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon span.notification-badge,
.notification-icon .notification-badge,
.notification-icon .notification-badge.text-white,
.notification-icon span.notification-badge,
a.notification-icon .notification-badge,
a.notification-icon span.notification-badge {
color: white !important;
text-color: white !important;
-webkit-text-fill-color: white !important;
}
/* Forcer la couleur pour tous les enfants directs */
.notification-icon > .notification-badge,
.notification-icon > span.notification-badge {
color: white !important;
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.1); }
100% { transform: scale(1); }
}
.notification-icon:hover .notification-badge {
animation: none;
}
/* Container pour les icônes - toujours alignées horizontalement */
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper {
display: flex !important;
flex-direction: row !important;
align-items: center !important;
justify-content: center !important;
gap: 15px !important;
list-style: none !important;
margin: 0 !important;
padding: 0 !important;
width: auto !important;
}
/* Surcharger les styles existants pour les li contenant le wrapper */
.header_area .navbar .nav.navbar-nav.navbar-right li:has(.navbar-icons-wrapper) {
margin-left: 0 !important;
margin-right: 0 !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
}
/* Styles pour les icônes */
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .cart,
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon,
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search {
display: flex !important;
align-items: center !important;
justify-content: center !important;
width: 40px !important;
height: 40px !important;
min-width: 40px !important;
min-height: 40px !important;
color: #333 !important;
text-decoration: none !important;
transition: all 0.3s ease !important;
border-radius: 50% !important;
position: relative !important;
margin: 0 !important;
padding: 0 !important;
}
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .cart:hover,
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon:hover,
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search:hover {
background-color: #f0f0f0 !important;
color: #ffa200 !important;
transform: scale(1.1) !important;
}
/* Surcharger le line-height de main.css */
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .cart span,
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon span,
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search span {
font-size: 18px !important;
line-height: 1 !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
color: inherit !important;
font-weight: normal !important;
}
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search {
background: transparent !important;
border: 0 !important;
cursor: pointer !important;
padding: 0 !important;
}
/* Alignement des icônes navbar sur mobile */
@media (max-width: 991.98px) {
/* Container navbar-right en colonne sur mobile */
.header_area .navbar .nav.navbar-nav.navbar-right {
display: flex !important;
flex-direction: column !important;
align-items: center !important;
justify-content: center !important;
width: 100% !important;
gap: 0 !important;
margin: 0 !important;
padding: 10px 0 !important;
}
/* Le container d'icônes reste horizontal */
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper {
width: 100% !important;
justify-content: center !important;
display: flex !important;
flex-direction: row !important;
}
/* Le bouton compte en bas - pleine largeur */
.header_area .navbar .nav.navbar-nav.navbar-right li:last-child {
width: 100% !important;
display: flex !important;
justify-content: center !important;
margin-top: 12px !important;
padding-top: 12px !important;
border-top: 1px solid #e0e0e0 !important;
}
/* Bouton compte responsive */
.header_area .navbar .nav.navbar-nav.navbar-right .btn-account {
width: 100%;
max-width: 200px;
padding: 10px 20px;
font-size: 14px;
}
}
/* Styles pour les messages flash - Design moderne */
.flash-message {
animation: slideInDownFlash 0.4s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
overflow: visible !important;
border: none !important;
padding: 16px 20px !important;
border-radius: 12px !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
display: flex !important;
align-items: center;
gap: 12px;
margin-bottom: 15px;
backdrop-filter: blur(10px);
transition: all 0.3s ease;
}
/* S'assurer que les icônes Font Awesome sont visibles */
.flash-message i.fa {
display: inline-block !important;
visibility: visible !important;
opacity: 1 !important;
width: auto !important;
height: auto !important;
font-family: \"FontAwesome\" !important;
font-style: normal !important;
font-weight: normal !important;
text-rendering: auto !important;
-webkit-font-smoothing: antialiased !important;
-moz-osx-font-smoothing: grayscale !important;
line-height: 1 !important;
flex-shrink: 0 !important;
}
/* Forcer l'affichage des pseudo-éléments Font Awesome */
.flash-message i.fa::before {
display: inline-block !important;
visibility: visible !important;
opacity: 1 !important;
content: attr(data-icon) !important;
}
/* Styles spécifiques pour chaque icône */
.flash-message i.fa-check-circle::before {
content: \"\\f058\" !important;
}
.flash-message i.fa-exclamation-circle::before {
content: \"\\f06a\" !important;
}
.flash-message i.fa-exclamation-triangle::before {
content: \"\\f071\" !important;
}
.flash-message i.fa-info-circle::before {
content: \"\\f05a\" !important;
}
.flash-message:hover {
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2) !important;
transform: translateY(-2px);
}
.flash-message::before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 5px;
background: linear-gradient(180deg, currentColor 0%, rgba(255,255,255,0.3) 100%);
border-radius: 12px 0 0 12px;
}
.flash-message.alert-success {
background: linear-gradient(135deg, #d4edda 0%, #c3e6cb 100%) !important;
color: #155724 !important;
border-left: 5px solid #28a745 !important;
}
.flash-message.alert-success i.fa {
color: #28a745 !important;
font-size: 1.3rem !important;
display: inline-block !important;
margin-right: 8px;
vertical-align: middle;
}
.flash-message.alert-danger {
background: linear-gradient(135deg, #f8d7da 0%, #f5c6cb 100%) !important;
color: #721c24 !important;
border-left: 5px solid #dc3545 !important;
}
.flash-message.alert-danger i.fa {
color: #dc3545 !important;
font-size: 1.3rem !important;
display: inline-block !important;
margin-right: 8px;
vertical-align: middle;
}
.flash-message.alert-warning {
background: linear-gradient(135deg, #fff3cd 0%, #ffeaa7 100%) !important;
color: #856404 !important;
border-left: 5px solid #ffc107 !important;
}
.flash-message.alert-warning i.fa {
color: #ffa200 !important;
font-size: 1.3rem !important;
display: inline-block !important;
margin-right: 8px;
vertical-align: middle;
}
.flash-message.alert-info {
background: linear-gradient(135deg, #d1ecf1 0%, #bee5eb 100%) !important;
color: #0c5460 !important;
border-left: 5px solid #17a2b8 !important;
}
.flash-message.alert-info i.fa {
color: #17a2b8 !important;
font-size: 1.3rem !important;
display: inline-block !important;
margin-right: 8px;
vertical-align: middle;
}
.flash-message strong {
flex: 1;
font-weight: 600;
font-size: 0.95rem;
line-height: 1.5;
}
.flash-message .btn-close {
opacity: 0.7;
padding: 8px !important;
margin: -8px -8px -8px auto !important;
transition: all 0.2s ease;
border-radius: 50% !important;
background: rgba(0, 0, 0, 0.05) !important;
width: 32px !important;
height: 32px !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
border: none !important;
cursor: pointer !important;
position: relative !important;
}
/* Ajouter une icône X visible dans le bouton */
.flash-message .btn-close::before {
content: '×' !important;
font-size: 24px !important;
line-height: 1 !important;
color: currentColor !important;
font-weight: bold !important;
display: block !important;
position: absolute !important;
top: 50% !important;
left: 50% !important;
transform: translate(-50%, -50%) !important;
}
.flash-message .btn-close:hover {
opacity: 1 !important;
background: rgba(0, 0, 0, 0.15) !important;
transform: rotate(90deg) !important;
}
.flash-message .btn-close:hover::before {
transform: translate(-50%, -50%) rotate(-90deg) !important;
}
@keyframes slideInDownFlash {
from {
opacity: 0;
transform: translateY(-30px) scale(0.95);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
#flash-messages-container {
margin-top: 20px;
margin-bottom: 0;
}
@media (max-width: 768px) {
.flash-message {
padding: 14px 16px !important;
font-size: 0.9rem;
}
.flash-message i {
font-size: 1.2rem !important;
}
}
/* Styles pour l'icône de comparaison */
.comparison-icon {
position: relative;
display: inline-block;
color: #333;
text-decoration: none;
transition: color 0.3s ease;
}
.comparison-icon:hover {
color: #ffa200;
}
.comparison-badge {
position: absolute;
top: 17px;
left: 12px;
background: #ffa200;
color: white;
border-radius: 50%;
width: 18px;
height: 18px;
font-size: 10px;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
animation: pulse 2s infinite;
}
.comparison-icon:hover .comparison-badge {
animation: none;
}
/* Styles pour les mega-menus - style comme la barre de recherche */
.mega-menu {
width: 100%;
max-width: 1200px;
left: 50%;
transform: translateX(-50%);
padding: 25px;
border-radius: 12px;
box-shadow: 0 8px 30px rgba(0,0,0,0.12);
border: none;
background: white;
display: none;
position: absolute;
top: 100%;
z-index: 9999 !important;
margin-top: 10px;
opacity: 0;
visibility: hidden;
transition: opacity 0.3s ease, visibility 0.3s ease, transform 0.3s ease;
}
.mega-menu.active {
display: block;
opacity: 1;
visibility: visible;
transform: translateX(-50%) translateY(0);
}
.nav-item.dropdown {
position: relative !important;
}
@media (min-width: 768px) {
.nav-item.dropdown {
position: relative !important;
}
.mega-menu {
position: absolute !important;
left: 50% !important;
transform: translateX(-50%) !important;
width: auto !important;
min-width: 600px !important;
}
}
/* Correction supplémentaire pour l'affichage sur la page d'accueil */
body.home .nav-item.dropdown,
.nav-item.dropdown {
position: relative !important;
}
body.home .mega-menu,
.mega-menu {
position: absolute !important;
left: 50% !important;
transform: translateX(-50%) translateY(0) !important;
width: auto !important;
min-width: 600px !important;
max-width: 90% !important;
top: 100% !important;
margin-top: 10px !important;
}
/* Assurer que les mega-menus sont toujours visibles au survol */
.nav-item.dropdown:hover .mega-menu {
opacity: 1 !important;
visibility: visible !important;
display: block !important;
transform: translateX(-50%) translateY(0) !important;
}
.mega-menu .dropdown-item {
padding: 0;
border: none;
}
.mega-menu .dropdown-header {
font-weight: 700;
color: #2c3e50;
margin-bottom: 18px;
padding-bottom: 10px;
border-bottom: 3px solid #3498db;
font-size: 16px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.mega-menu .dropdown-item a {
display: block;
padding: 10px 15px;
color: #555;
text-decoration: none;
border-radius: 6px;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
overflow: hidden;
}
.mega-menu .dropdown-item a::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(52, 152, 219, 0.1), transparent);
transition: left 0.5s;
}
.mega-menu .dropdown-item a:hover::before {
left: 100%;
}
.mega-menu .dropdown-item a:hover {
background: linear-gradient(135deg, #f8f9fa, #e3f2fd);
color: #2980b9;
transform: translateX(8px);
box-shadow: 0 2px 8px rgba(52, 152, 219, 0.2);
}
.mega-menu .dropdown-item a i {
width: 22px;
text-align: center;
margin-right: 8px;
color: #3498db;
transition: color 0.3s ease;
}
.mega-menu .dropdown-item a:hover i {
color: #2980b9;
}
/* Animation d'apparition améliorée */
@keyframes slideInDown {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.mega-menu {
animation: slideInDown 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Effet de survol sur le lien principal */
.nav-item.dropdown .nav-link {
position: relative;
transition: all 0.3s ease;
}
.nav-item.dropdown .nav-link::after {
content: '';
position: absolute;
bottom: -2px;
left: 50%;
width: 0;
height: 2px;
background: linear-gradient(90deg, #3498db, #2980b9);
transition: all 0.3s ease;
transform: translateX(-50%);
}
.nav-item.dropdown:hover .nav-link::after {
width: 100%;
}
.nav-item.dropdown:hover .nav-link {
color: #2980b9;
}
@keyframes fadeInDown {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Responsive */
@media (max-width: 768px) {
.mega-menu {
width: 100%;
left: 0;
padding: 15px;
}
.mega-menu .row {
margin: 0;
}
.mega-menu .col-md-3 {
margin-bottom: 20px;
}
}
</style>
";
// line 711
yield from $this->unwrap()->yieldBlock('stylesheets', $context, $blocks);
// line 714
yield "
<!-- Script pour forcer l'application des styles CSS après chargement -->
<script>
document.addEventListener('DOMContentLoaded', function() {
// Forcer le masquage du toggle sur grands écrans
if (window.innerWidth >= 992) {
const togglers = document.querySelectorAll('.navbar-toggler, .header_area .navbar .navbar-toggler');
togglers.forEach(function(toggler) {
if (toggler) {
toggler.style.display = 'none';
toggler.style.visibility = 'hidden';
toggler.style.opacity = '0';
toggler.style.width = '0';
toggler.style.height = '0';
toggler.style.padding = '0';
toggler.style.margin = '0';
toggler.style.border = 'none';
toggler.style.position = 'absolute';
toggler.style.left = '-9999px';
}
});
const iconBars = document.querySelectorAll('.navbar-toggler .icon-bar, .header_area .navbar .navbar-toggler .icon-bar, .navbar-toggler-icon');
iconBars.forEach(function(bar) {
if (bar) {
bar.style.display = 'none';
bar.style.visibility = 'hidden';
}
});
}
// Alignement des icônes navbar sur mobile
const navbarRight = document.querySelectorAll('.navbar-right, .header_area .navbar .nav.navbar-nav.navbar-right');
navbarRight.forEach(function(nav) {
if (nav && window.innerWidth <= 991.98) {
// Mobile: colonne avec icônes alignées horizontalement
nav.style.display = 'flex';
nav.style.flexDirection = 'column';
nav.style.alignItems = 'center';
nav.style.textAlign = 'center';
// Le container d'icônes reste horizontal
const iconsContainer = nav.querySelector('.navbar-icons-wrapper');
if (iconsContainer) {
iconsContainer.style.display = 'flex';
iconsContainer.style.flexDirection = 'row';
iconsContainer.style.justifyContent = 'center';
}
// Le bouton compte en bas
const accountBtn = nav.querySelector('li:last-child');
if (accountBtn) {
accountBtn.style.width = '100%';
accountBtn.style.display = 'flex';
accountBtn.style.justifyContent = 'center';
accountBtn.style.marginTop = '12px';
accountBtn.style.paddingTop = '12px';
accountBtn.style.borderTop = '1px solid #e0e0e0';
}
} else if (nav && window.innerWidth > 991.98) {
// Desktop: alignement horizontal normal
nav.style.display = 'flex';
nav.style.flexDirection = 'row';
nav.style.alignItems = 'center';
nav.style.justifyContent = 'flex-end';
}
});
});
// Réappliquer lors du redimensionnement
window.addEventListener('resize', function() {
if (window.innerWidth >= 992) {
const togglers = document.querySelectorAll('.navbar-toggler, .header_area .navbar .navbar-toggler');
togglers.forEach(function(toggler) {
if (toggler) {
toggler.style.display = 'none';
toggler.style.visibility = 'hidden';
}
});
}
// Réappliquer l'alignement des icônes navbar
const navbarRight = document.querySelectorAll('.navbar-right, .header_area .navbar .nav.navbar-nav.navbar-right');
navbarRight.forEach(function(nav) {
if (nav && window.innerWidth <= 991.98) {
// Mobile: colonne avec icônes alignées horizontalement
nav.style.display = 'flex';
nav.style.flexDirection = 'column';
nav.style.alignItems = 'center';
nav.style.textAlign = 'center';
// Le container d'icônes reste horizontal
const iconsContainer = nav.querySelector('.navbar-icons-wrapper');
if (iconsContainer) {
iconsContainer.style.display = 'flex';
iconsContainer.style.flexDirection = 'row';
iconsContainer.style.justifyContent = 'center';
}
const accountBtn = nav.querySelector('li:last-child');
if (accountBtn) {
accountBtn.style.width = '100%';
accountBtn.style.display = 'flex';
accountBtn.style.justifyContent = 'center';
accountBtn.style.marginTop = '12px';
accountBtn.style.paddingTop = '12px';
accountBtn.style.borderTop = '1px solid #e0e0e0';
}
} else if (nav && window.innerWidth > 991.98) {
// Desktop: alignement horizontal normal
nav.style.display = 'flex';
nav.style.flexDirection = 'row';
nav.style.alignItems = 'center';
nav.style.justifyContent = 'flex-end';
}
});
});
</script>
";
// line 834
$context["current_route"] = CoreExtension::getAttribute($this->env, $this->source, CoreExtension::getAttribute($this->env, $this->source, CoreExtension::getAttribute($this->env, $this->source, ($context["app"] ?? null), "request", [], "any", false, false, false, 834), "attributes", [], "any", false, false, false, 834), "get", ["_route"], "method", false, false, false, 834);
// line 835
yield " ";
$context["is_account_route"] = ((is_string($_v0 = ($context["current_route"] ?? null)) && is_string($_v1 = "ui_account_") && str_starts_with($_v0, $_v1)) || (($context["current_route"] ?? null) == "notifications_list"));
// line 836
yield " <style>
/* Shared dark-mode fixes for the public account area. */
@media (prefers-color-scheme: dark) {
body.account-theme-scope {
background-color: #111827;
color: #e5e7eb;
}
body.account-theme-scope .card,
body.account-theme-scope .notification-item,
body.account-theme-scope .list-group-item,
body.account-theme-scope .modal-content,
body.account-theme-scope .dropdown-menu,
body.account-theme-scope .form-control,
body.account-theme-scope .form-select,
body.account-theme-scope .input-group-text,
body.account-theme-scope .accordion-item,
body.account-theme-scope .table,
body.account-theme-scope .table td,
body.account-theme-scope .table th {
background-color: #1f2937 !important;
border-color: #374151 !important;
color: #e5e7eb !important;
}
body.account-theme-scope .card-header,
body.account-theme-scope .card-header.bg-white,
body.account-theme-scope .bg-white,
body.account-theme-scope .account-menu-list .menu-main {
background-color: #182131 !important;
border-color: #374151 !important;
}
body.account-theme-scope .text-muted,
body.account-theme-scope .form-text,
body.account-theme-scope .form-label,
body.account-theme-scope small,
body.account-theme-scope .small,
body.account-theme-scope .btn-outline-secondary,
body.account-theme-scope .btn-outline-secondary i {
color: #aeb8c7 !important;
}
body.account-theme-scope h1,
body.account-theme-scope h2,
body.account-theme-scope h3,
body.account-theme-scope h4,
body.account-theme-scope h5,
body.account-theme-scope h6,
body.account-theme-scope .list-group-item,
body.account-theme-scope .card-title,
body.account-theme-scope .card-text,
body.account-theme-scope .notification-title,
body.account-theme-scope .notification-message,
body.account-theme-scope .notification-meta,
body.account-theme-scope .table,
body.account-theme-scope .table td,
body.account-theme-scope .table th,
body.account-theme-scope .table strong,
body.account-theme-scope .table a:not(.btn),
body.account-theme-scope .breadcrumb-banner,
body.account-theme-scope .breadcrumb-banner a,
body.account-theme-scope .breadcrumb-banner h1,
body.account-theme-scope .empty-state-title,
body.account-theme-scope .empty-state-text {
color: #e5e7eb !important;
}
body.account-theme-scope .account-menu-list .list-group-item:hover:not(.menu-action-active):not(.menu-main) {
background-color: #243041 !important;
}
body.account-theme-scope .notification-item.unread {
background-color: #172554 !important;
border-left-color: #60a5fa !important;
}
body.account-theme-scope .notification-item.archived {
opacity: 0.85;
}
body.account-theme-scope .btn-outline-primary,
body.account-theme-scope .btn-outline-secondary,
body.account-theme-scope .btn-outline-warning,
body.account-theme-scope .btn-outline-danger {
background-color: transparent !important;
}
body.account-theme-scope .empty-state-icon {
color: #6b7280 !important;
}
body.account-theme-scope .profile-picture-container .profile-picture,
body.account-theme-scope .profile-picture-mobile,
body.account-theme-scope .profile-picture-edit-icon,
body.account-theme-scope .profile-picture-edit-icon-mobile {
border-color: #111827 !important;
}
}
html.dark-mode body.account-theme-scope,
body.dark-mode.account-theme-scope,
html[data-theme=\"dark\"] body.account-theme-scope,
body[data-theme=\"dark\"].account-theme-scope,
html[data-bs-theme=\"dark\"] body.account-theme-scope,
body[data-bs-theme=\"dark\"].account-theme-scope {
background-color: #111827;
color: #e5e7eb;
}
html.dark-mode body.account-theme-scope .card,
html.dark-mode body.account-theme-scope .notification-item,
html.dark-mode body.account-theme-scope .list-group-item,
html.dark-mode body.account-theme-scope .modal-content,
html.dark-mode body.account-theme-scope .dropdown-menu,
html.dark-mode body.account-theme-scope .form-control,
html.dark-mode body.account-theme-scope .form-select,
html.dark-mode body.account-theme-scope .input-group-text,
html.dark-mode body.account-theme-scope .accordion-item,
html.dark-mode body.account-theme-scope .table,
html.dark-mode body.account-theme-scope .table td,
html.dark-mode body.account-theme-scope .table th,
body.dark-mode.account-theme-scope .card,
body.dark-mode.account-theme-scope .notification-item,
body.dark-mode.account-theme-scope .list-group-item,
body.dark-mode.account-theme-scope .modal-content,
body.dark-mode.account-theme-scope .dropdown-menu,
body.dark-mode.account-theme-scope .form-control,
body.dark-mode.account-theme-scope .form-select,
body.dark-mode.account-theme-scope .input-group-text,
body.dark-mode.account-theme-scope .accordion-item,
body.dark-mode.account-theme-scope .table,
body.dark-mode.account-theme-scope .table td,
body.dark-mode.account-theme-scope .table th,
html[data-theme=\"dark\"] body.account-theme-scope .card,
html[data-theme=\"dark\"] body.account-theme-scope .notification-item,
html[data-theme=\"dark\"] body.account-theme-scope .list-group-item,
html[data-theme=\"dark\"] body.account-theme-scope .modal-content,
html[data-theme=\"dark\"] body.account-theme-scope .dropdown-menu,
html[data-theme=\"dark\"] body.account-theme-scope .form-control,
html[data-theme=\"dark\"] body.account-theme-scope .form-select,
html[data-theme=\"dark\"] body.account-theme-scope .input-group-text,
html[data-theme=\"dark\"] body.account-theme-scope .accordion-item,
html[data-theme=\"dark\"] body.account-theme-scope .table,
html[data-theme=\"dark\"] body.account-theme-scope .table td,
html[data-theme=\"dark\"] body.account-theme-scope .table th,
body[data-theme=\"dark\"].account-theme-scope .card,
body[data-theme=\"dark\"].account-theme-scope .notification-item,
body[data-theme=\"dark\"].account-theme-scope .list-group-item,
body[data-theme=\"dark\"].account-theme-scope .modal-content,
body[data-theme=\"dark\"].account-theme-scope .dropdown-menu,
body[data-theme=\"dark\"].account-theme-scope .form-control,
body[data-theme=\"dark\"].account-theme-scope .form-select,
body[data-theme=\"dark\"].account-theme-scope .input-group-text,
body[data-theme=\"dark\"].account-theme-scope .accordion-item,
body[data-theme=\"dark\"].account-theme-scope .table,
body[data-theme=\"dark\"].account-theme-scope .table td,
body[data-theme=\"dark\"].account-theme-scope .table th,
html[data-bs-theme=\"dark\"] body.account-theme-scope .card,
html[data-bs-theme=\"dark\"] body.account-theme-scope .notification-item,
html[data-bs-theme=\"dark\"] body.account-theme-scope .list-group-item,
html[data-bs-theme=\"dark\"] body.account-theme-scope .modal-content,
html[data-bs-theme=\"dark\"] body.account-theme-scope .dropdown-menu,
html[data-bs-theme=\"dark\"] body.account-theme-scope .form-control,
html[data-bs-theme=\"dark\"] body.account-theme-scope .form-select,
html[data-bs-theme=\"dark\"] body.account-theme-scope .input-group-text,
html[data-bs-theme=\"dark\"] body.account-theme-scope .accordion-item,
html[data-bs-theme=\"dark\"] body.account-theme-scope .table,
html[data-bs-theme=\"dark\"] body.account-theme-scope .table td,
html[data-bs-theme=\"dark\"] body.account-theme-scope .table th,
body[data-bs-theme=\"dark\"].account-theme-scope .card,
body[data-bs-theme=\"dark\"].account-theme-scope .notification-item,
body[data-bs-theme=\"dark\"].account-theme-scope .list-group-item,
body[data-bs-theme=\"dark\"].account-theme-scope .modal-content,
body[data-bs-theme=\"dark\"].account-theme-scope .dropdown-menu,
body[data-bs-theme=\"dark\"].account-theme-scope .form-control,
body[data-bs-theme=\"dark\"].account-theme-scope .form-select,
body[data-bs-theme=\"dark\"].account-theme-scope .input-group-text,
body[data-bs-theme=\"dark\"].account-theme-scope .accordion-item,
body[data-bs-theme=\"dark\"].account-theme-scope .table,
body[data-bs-theme=\"dark\"].account-theme-scope .table td,
body[data-bs-theme=\"dark\"].account-theme-scope .table th {
background-color: #1f2937 !important;
border-color: #374151 !important;
color: #e5e7eb !important;
}
html.dark-mode body.account-theme-scope .card-header,
html.dark-mode body.account-theme-scope .card-header.bg-white,
html.dark-mode body.account-theme-scope .bg-white,
html.dark-mode body.account-theme-scope .account-menu-list .menu-main,
body.dark-mode.account-theme-scope .card-header,
body.dark-mode.account-theme-scope .card-header.bg-white,
body.dark-mode.account-theme-scope .bg-white,
body.dark-mode.account-theme-scope .account-menu-list .menu-main,
html[data-theme=\"dark\"] body.account-theme-scope .card-header,
html[data-theme=\"dark\"] body.account-theme-scope .card-header.bg-white,
html[data-theme=\"dark\"] body.account-theme-scope .bg-white,
html[data-theme=\"dark\"] body.account-theme-scope .account-menu-list .menu-main,
body[data-theme=\"dark\"].account-theme-scope .card-header,
body[data-theme=\"dark\"].account-theme-scope .card-header.bg-white,
body[data-theme=\"dark\"].account-theme-scope .bg-white,
body[data-theme=\"dark\"].account-theme-scope .account-menu-list .menu-main,
html[data-bs-theme=\"dark\"] body.account-theme-scope .card-header,
html[data-bs-theme=\"dark\"] body.account-theme-scope .card-header.bg-white,
html[data-bs-theme=\"dark\"] body.account-theme-scope .bg-white,
html[data-bs-theme=\"dark\"] body.account-theme-scope .account-menu-list .menu-main,
body[data-bs-theme=\"dark\"].account-theme-scope .card-header,
body[data-bs-theme=\"dark\"].account-theme-scope .card-header.bg-white,
body[data-bs-theme=\"dark\"].account-theme-scope .bg-white,
body[data-bs-theme=\"dark\"].account-theme-scope .account-menu-list .menu-main {
background-color: #182131 !important;
border-color: #374151 !important;
}
html.dark-mode body.account-theme-scope .text-muted,
html.dark-mode body.account-theme-scope .form-text,
html.dark-mode body.account-theme-scope .form-label,
html.dark-mode body.account-theme-scope small,
html.dark-mode body.account-theme-scope .small,
html.dark-mode body.account-theme-scope .btn-outline-secondary,
html.dark-mode body.account-theme-scope .btn-outline-secondary i,
body.dark-mode.account-theme-scope .text-muted,
body.dark-mode.account-theme-scope .form-text,
body.dark-mode.account-theme-scope .form-label,
body.dark-mode.account-theme-scope small,
body.dark-mode.account-theme-scope .small,
body.dark-mode.account-theme-scope .btn-outline-secondary,
body.dark-mode.account-theme-scope .btn-outline-secondary i,
html[data-theme=\"dark\"] body.account-theme-scope .text-muted,
html[data-theme=\"dark\"] body.account-theme-scope .form-text,
html[data-theme=\"dark\"] body.account-theme-scope .form-label,
html[data-theme=\"dark\"] body.account-theme-scope small,
html[data-theme=\"dark\"] body.account-theme-scope .small,
html[data-theme=\"dark\"] body.account-theme-scope .btn-outline-secondary,
html[data-theme=\"dark\"] body.account-theme-scope .btn-outline-secondary i,
body[data-theme=\"dark\"].account-theme-scope .text-muted,
body[data-theme=\"dark\"].account-theme-scope .form-text,
body[data-theme=\"dark\"].account-theme-scope .form-label,
body[data-theme=\"dark\"].account-theme-scope small,
body[data-theme=\"dark\"].account-theme-scope .small,
body[data-theme=\"dark\"].account-theme-scope .btn-outline-secondary,
body[data-theme=\"dark\"].account-theme-scope .btn-outline-secondary i,
html[data-bs-theme=\"dark\"] body.account-theme-scope .text-muted,
html[data-bs-theme=\"dark\"] body.account-theme-scope .form-text,
html[data-bs-theme=\"dark\"] body.account-theme-scope .form-label,
html[data-bs-theme=\"dark\"] body.account-theme-scope small,
html[data-bs-theme=\"dark\"] body.account-theme-scope .small,
html[data-bs-theme=\"dark\"] body.account-theme-scope .btn-outline-secondary,
html[data-bs-theme=\"dark\"] body.account-theme-scope .btn-outline-secondary i,
body[data-bs-theme=\"dark\"].account-theme-scope .text-muted,
body[data-bs-theme=\"dark\"].account-theme-scope .form-text,
body[data-bs-theme=\"dark\"].account-theme-scope .form-label,
body[data-bs-theme=\"dark\"].account-theme-scope small,
body[data-bs-theme=\"dark\"].account-theme-scope .small,
body[data-bs-theme=\"dark\"].account-theme-scope .btn-outline-secondary,
body[data-bs-theme=\"dark\"].account-theme-scope .btn-outline-secondary i {
color: #aeb8c7 !important;
}
html.dark-mode body.account-theme-scope .empty-state-icon,
body.dark-mode.account-theme-scope .empty-state-icon,
html[data-theme=\"dark\"] body.account-theme-scope .empty-state-icon,
body[data-theme=\"dark\"].account-theme-scope .empty-state-icon,
html[data-bs-theme=\"dark\"] body.account-theme-scope .empty-state-icon,
body[data-bs-theme=\"dark\"].account-theme-scope .empty-state-icon {
color: #6b7280 !important;
}
</style>
</head>
<body ";
// line 1106
if ((array_key_exists("current_menu", $context) && (($context["current_menu"] ?? null) == "listing"))) {
yield "id=\"category\"";
}
yield " class=\"";
if ((($tmp = ($context["is_account_route"] ?? null)) && $tmp instanceof Markup ? (string) $tmp : $tmp)) {
yield "account-theme-scope";
}
yield "\">
<!-- Start Header Area -->
<header class=\"header_area sticky-header\">
<div class=\"main_menu\">
<nav class=\"navbar navbar-expand-lg navbar-light main_box\">
<div class=\"container\">
<!-- Brand and toggle get grouped for better mobile display -->
<a class=\"navbar-brand logo_h\" href=\"";
// line 1114
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_home");
yield "\"><img style=\"width: auto;height: 60px\" src=\"";
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("logo.png"), "html", null, true);
yield "\" alt=\"\"></a>
<button class=\"navbar-toggler\" type=\"button\" data-bs-toggle=\"collapse\" data-bs-target=\"#navbarSupportedContent\"
aria-controls=\"navbarSupportedContent\" aria-expanded=\"false\" aria-label=\"Toggle navigation\">
<span class=\"icon-bar\"></span>
<span class=\"icon-bar\"></span>
<span class=\"icon-bar\"></span>
</button>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class=\"collapse navbar-collapse offset\" id=\"navbarSupportedContent\">
<ul class=\"nav navbar-nav menu_nav ml-auto\">
<li class=\"nav-item ";
// line 1124
if ((array_key_exists("current_menu", $context) && (($context["current_menu"] ?? null) == "home"))) {
yield "active";
}
yield "\">
<a class=\"nav-link\" href=\"";
// line 1125
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_home");
yield "\">Accueil</a>
</li>
<li class=\"nav-item ";
// line 1127
if ((array_key_exists("current_menu", $context) && (($context["current_menu"] ?? null) == "shops"))) {
yield "active";
}
yield "\">
<a class=\"nav-link\" href=\"";
// line 1128
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_shops_list");
yield "\">Boutiques</a>
</li>
<li class=\"nav-item ";
// line 1130
if ((array_key_exists("current_menu", $context) && (($context["current_menu"] ?? null) == "listing"))) {
yield "active";
}
yield "\">
<a class=\"nav-link\" href=\"";
// line 1131
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
yield "\">Produits</a>
</li>
<li class=\"nav-item ";
// line 1133
if ((array_key_exists("current_menu", $context) && (($context["current_menu"] ?? null) == "blog"))) {
yield "active";
}
yield "\">
<a class=\"nav-link\" href=\"";
// line 1134
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_blog");
yield "\">Blog</a>
</li>
<li class=\"nav-item ";
// line 1136
if ((array_key_exists("current_menu", $context) && (($context["current_menu"] ?? null) == "contact"))) {
yield "active";
}
yield "\">
<a class=\"nav-link\" href=\"";
// line 1137
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_contact");
yield "\">Contact</a>
</li>
</ul>
<ul class=\"nav navbar-nav navbar-right\">
<li class=\"nav-item header-icons-item\">
<div class=\"navbar-icons-wrapper\">
<a href=\"";
// line 1143
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_cart");
yield "\" class=\"cart ";
if ((array_key_exists("current_menu", $context) && (($context["current_menu"] ?? null) == "cart"))) {
yield "active";
}
yield "\" aria-label=\"Panier\">
<span class=\"ti-bag\"></span>
</a>
<a href=\"";
// line 1146
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_product_comparison");
yield "\" class=\"comparison-icon ";
if ((array_key_exists("current_menu", $context) && (($context["current_menu"] ?? null) == "comparison"))) {
yield "active";
}
yield "\" title=\"Comparaison premium\" aria-label=\"Comparaison premium\">
<span class=\"lnr lnr-sync\"></span>
<span class=\"comparison-badge\" id=\"comparisonBadge\" data-comparison-badge style=\"display: none;\">0</span>
</a>
";
// line 1150
if ((($tmp = CoreExtension::getAttribute($this->env, $this->source, ($context["app"] ?? null), "user", [], "any", false, false, false, 1150)) && $tmp instanceof Markup ? (string) $tmp : $tmp)) {
// line 1151
yield " <a href=\"";
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("notifications_list");
yield "\" class=\"notification-icon\" title=\"Notifications\" aria-label=\"Notifications\">
<span class=\"ti-bell\"></span>
<span class=\"notification-badge text-white\" id=\"notificationBadge\" style=\"display: none;color: white;\">0</span>
</a>
";
}
// line 1156
yield " <button class=\"theme-toggle-btn\" type=\"button\" data-theme-toggle aria-label=\"Passer au mode sombre\" title=\"Passer au mode sombre\">
<span class=\"ti-moon\" data-theme-icon></span>
</button>
<button class=\"search\" type=\"button\" aria-label=\"Recherche\">
<span class=\"lnr lnr-magnifier\" id=\"search\"></span>
</button>
</div>
</li>
<li class=\"nav-item header-account-item\">
";
// line 1165
if ((($tmp = CoreExtension::getAttribute($this->env, $this->source, ($context["app"] ?? null), "user", [], "any", false, false, false, 1165)) && $tmp instanceof Markup ? (string) $tmp : $tmp)) {
// line 1166
yield " <a class=\"btn btn-primary btn-account header-account-link text-white\" href=\"";
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_account_index");
yield "\">
<i class=\"ti-user\"></i> Mon compte
</a>
";
} else {
// line 1170
yield " <a class=\"btn btn-primary btn-account header-account-link text-white\" href=\"";
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_app_login");
yield "\">
<i class=\"ti-lock\"></i>Se connecter
</a>
";
}
// line 1174
yield " </li>
</ul>
</div>
</div>
</nav>
</div>
<div class=\"search_input\" id=\"search_input_box\">
<div class=\"container\">
<form class=\"d-flex justify-content-between\">
<input type=\"text\" class=\"form-control\" id=\"search_input\" placeholder=\"Search Here\">
<button type=\"submit\" class=\"btn\"></button>
<span class=\"lnr lnr-cross\" id=\"close_search\" title=\"Close Search\"></span>
</form>
</div>
</div>
</header>
<!-- End Header Area -->
<!-- Flash Messages -->
<div class=\"container mt-3\" id=\"flash-messages-container\" style=\"position: relative; z-index: 1050;\">
<div class=\"row\">
<div class=\"col-12\">
";
// line 1196
$context['_parent'] = $context;
$context['_seq'] = CoreExtension::ensureTraversable(CoreExtension::getAttribute($this->env, $this->source, ($context["app"] ?? null), "flashes", ["success"], "method", false, false, false, 1196));
foreach ($context['_seq'] as $context["_key"] => $context["message"]) {
// line 1197
yield " <div class=\"alert alert-success alert-dismissible fade show flash-message\" role=\"alert\">
<i class=\"fa fa-check-circle\"></i>
<strong>";
// line 1199
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($context["message"], "html", null, true);
yield "</strong>
<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
</div>
";
}
$_parent = $context['_parent'];
unset($context['_seq'], $context['_key'], $context['message'], $context['_parent']);
$context = array_intersect_key($context, $_parent) + $_parent;
// line 1203
yield "
";
// line 1204
$context['_parent'] = $context;
$context['_seq'] = CoreExtension::ensureTraversable(CoreExtension::getAttribute($this->env, $this->source, ($context["app"] ?? null), "flashes", ["error"], "method", false, false, false, 1204));
foreach ($context['_seq'] as $context["_key"] => $context["message"]) {
// line 1205
yield " <div class=\"alert alert-danger alert-dismissible fade show flash-message\" role=\"alert\">
<i class=\"fa fa-exclamation-circle\"></i>
<strong>";
// line 1207
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($context["message"], "html", null, true);
yield "</strong>
<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
</div>
";
}
$_parent = $context['_parent'];
unset($context['_seq'], $context['_key'], $context['message'], $context['_parent']);
$context = array_intersect_key($context, $_parent) + $_parent;
// line 1211
yield "
";
// line 1212
$context['_parent'] = $context;
$context['_seq'] = CoreExtension::ensureTraversable(CoreExtension::getAttribute($this->env, $this->source, ($context["app"] ?? null), "flashes", ["warning"], "method", false, false, false, 1212));
foreach ($context['_seq'] as $context["_key"] => $context["message"]) {
// line 1213
yield " <div class=\"alert alert-warning alert-dismissible fade show flash-message\" role=\"alert\">
<i class=\"fa fa-exclamation-triangle\"></i>
<strong>";
// line 1215
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($context["message"], "html", null, true);
yield "</strong>
<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
</div>
";
}
$_parent = $context['_parent'];
unset($context['_seq'], $context['_key'], $context['message'], $context['_parent']);
$context = array_intersect_key($context, $_parent) + $_parent;
// line 1219
yield "
";
// line 1220
$context['_parent'] = $context;
$context['_seq'] = CoreExtension::ensureTraversable(CoreExtension::getAttribute($this->env, $this->source, ($context["app"] ?? null), "flashes", ["info"], "method", false, false, false, 1220));
foreach ($context['_seq'] as $context["_key"] => $context["message"]) {
// line 1221
yield " <div class=\"alert alert-info alert-dismissible fade show flash-message\" role=\"alert\">
<i class=\"fa fa-info-circle\"></i>
<strong>";
// line 1223
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($context["message"], "html", null, true);
yield "</strong>
<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
</div>
";
}
$_parent = $context['_parent'];
unset($context['_seq'], $context['_key'], $context['message'], $context['_parent']);
$context = array_intersect_key($context, $_parent) + $_parent;
// line 1227
yield " </div>
</div>
</div>
<div id=\"comparisonTray\" class=\"comparison-tray\" aria-live=\"polite\">
<div class=\"comparison-tray__header\">
<div>
<p class=\"comparison-tray__title\">Comparaison premium</p>
<p class=\"comparison-tray__meta\" id=\"comparisonTrayMeta\">Aucun produit en comparaison</p>
</div>
<a href=\"";
// line 1237
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_product_comparison");
yield "\" class=\"comparison-tray__go\">Ouvrir</a>
</div>
<div class=\"comparison-tray__items\" id=\"comparisonTrayItems\"></div>
<p class=\"comparison-tray__empty\" id=\"comparisonTrayEmpty\">Ajoute des produits d'une meme categorie pour obtenir une comparaison ultra pertinente.</p>
<div class=\"comparison-tray__actions\">
<a href=\"";
// line 1242
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_product_comparison");
yield "\" class=\"comparison-tray__go\">Comparer maintenant</a>
<button type=\"button\" class=\"comparison-tray__clear\" id=\"comparisonTrayClear\">Vider</button>
</div>
</div>
";
// line 1247
yield from $this->unwrap()->yieldBlock('body', $context, $blocks);
// line 1248
yield "
<!-- start footer Area -->
<footer class=\"footer-area section_gap\">
<div class=\"footer-pattern\"></div>
<div class=\"container\">
<div class=\"row\">
<div class=\"col-lg-3 col-md-6 col-sm-6 mb-4 mb-lg-0\">
<div class=\"single-footer-widget\">
<div class=\"footer-logo mb-3\">
<h4 class=\"footer-brand\">MaketOu</h4>
</div>
<p class=\"footer-description\">
MaketOu est la première marketplace haïtienne qui connecte les acheteurs et les vendeurs.
Nous offrons une plateforme sécurisée et moderne pour le commerce en ligne en Haïti.
</p>
<div class=\"footer-social mt-3\">
<h6 class=\"mb-2\">Suivez-nous</h6>
<div class=\"footer-social-icons\">
<a href=\"#\" class=\"social-icon\" aria-label=\"Facebook\" title=\"Facebook\">
<i class=\"fa fa-facebook\"></i>
</a>
<a href=\"#\" class=\"social-icon\" aria-label=\"Twitter\" title=\"Twitter\">
<i class=\"fa fa-twitter\"></i>
</a>
<a href=\"#\" class=\"social-icon\" aria-label=\"Instagram\" title=\"Instagram\">
<i class=\"fa fa-instagram\"></i>
</a>
<a href=\"#\" class=\"social-icon\" aria-label=\"LinkedIn\" title=\"LinkedIn\">
<i class=\"fa fa-linkedin\"></i>
</a>
</div>
</div>
</div>
</div>
<div class=\"col-lg-2 col-md-6 col-sm-6 mb-4 mb-lg-0\">
<div class=\"single-footer-widget\">
<h6 class=\"footer-widget-title\">Liens rapides</h6>
<ul class=\"footer-list\">
<li><a href=\"";
// line 1286
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_home");
yield "\"><i class=\"fa fa-angle-right me-2\"></i>Accueil</a></li>
<li><a href=\"";
// line 1287
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
yield "\"><i class=\"fa fa-angle-right me-2\"></i>Produits</a></li>
<li><a href=\"";
// line 1288
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_shops_list");
yield "\"><i class=\"fa fa-angle-right me-2\"></i>Boutiques</a></li>
";
// line 1289
if ((($tmp = CoreExtension::getAttribute($this->env, $this->source, ($context["app"] ?? null), "user", [], "any", false, false, false, 1289)) && $tmp instanceof Markup ? (string) $tmp : $tmp)) {
// line 1290
yield " <li><a href=\"";
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_account_index");
yield "\"><i class=\"fa fa-angle-right me-2\"></i>Mon compte</a></li>
";
} else {
// line 1292
yield " <li><a href=\"";
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_app_login");
yield "\"><i class=\"fa fa-angle-right me-2\"></i>Se connecter</a></li>
<li><a href=\"";
// line 1293
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_app_register");
yield "\"><i class=\"fa fa-angle-right me-2\"></i>S'inscrire</a></li>
";
}
// line 1295
yield " </ul>
</div>
</div>
<div class=\"col-lg-2 col-md-6 col-sm-6 mb-4 mb-lg-0\">
<div class=\"single-footer-widget\">
<h6 class=\"footer-widget-title\">Pour les vendeurs</h6>
<ul class=\"footer-list\">
<li><a href=\"";
// line 1302
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("seller_index");
yield "\"><i class=\"fa fa-angle-right me-2\"></i>Ouvrir une boutique</a></li>
<li><a href=\"";
// line 1303
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("seller_help_how_to_sell");
yield "\"><i class=\"fa fa-angle-right me-2\"></i>Comment vendre</a></li>
<li><a href=\"";
// line 1304
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("seller_help_pricing");
yield "\"><i class=\"fa fa-angle-right me-2\"></i>Tarifs</a></li>
<li><a href=\"";
// line 1305
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("seller_help_support");
yield "\"><i class=\"fa fa-angle-right me-2\"></i>Support vendeur</a></li>
</ul>
</div>
</div>
<div class=\"col-lg-2 col-md-6 col-sm-6 mb-4 mb-lg-0\">
<div class=\"single-footer-widget\">
<h6 class=\"footer-widget-title\">Support</h6>
<ul class=\"footer-list\">
<li><a href=\"";
// line 1313
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_help");
yield "\"><i class=\"fa fa-angle-right me-2\"></i> Centre d'Aide</a></li>
<li><a href=\"";
// line 1314
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_contact");
yield "\"><i class=\"fa fa-angle-right me-2\"></i> Contactez-nous</a></li>
<li><a href=\"";
// line 1315
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_faq");
yield "\"><i class=\"fa fa-angle-right me-2\"></i> FAQ</a></li>
<li><a href=\"";
// line 1316
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_privacy");
yield "\"><i class=\"fa fa-angle-right me-2\"></i> Politique de Confidentialité</a></li>
<li><a href=\"";
// line 1317
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_terms");
yield "\"><i class=\"fa fa-angle-right me-2\"></i> Conditions d'Utilisation</a></li>
</ul>
</div>
</div>
<div class=\"col-lg-3 col-md-6 col-sm-6\">
<div class=\"single-footer-widget\">
<h6 class=\"footer-widget-title\">Newsletter</h6>
<p class=\"footer-newsletter-text\">Restez informé des dernières nouveautés</p>
<div class=\"footer-newsletter-wrapper\" id=\"mc_embed_signup\">
<form action=\"";
// line 1326
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_newsletter_subscribe");
yield "\" method=\"post\" class=\"footer-newsletter-form\">
<div class=\"newsletter-input-group\">
<i class=\"fa fa-envelope newsletter-icon\"></i>
<input class=\"form-control newsletter-input\" name=\"email\" placeholder=\"Votre email\" required type=\"email\">
<button type=\"submit\" class=\"newsletter-btn\" aria-label=\"S'abonner\">
<span class=\"newsletter-btn-icon\">
<i class=\"fa fa-paper-plane\" aria-hidden=\"true\"></i>
</span>
<span class=\"newsletter-btn-loader\" style=\"display: none;\">
<i class=\"fa fa-spinner fa-spin\" aria-hidden=\"true\"></i>
</span>
</button>
</div>
</form>
</div>
<div class=\"footer-trust-badges mt-3\">
<div class=\"trust-item\">
<i class=\"fa fa-shield\"></i>
<span>Paiement sécurisé</span>
</div>
<div class=\"trust-item\">
<i class=\"fa fa-truck\"></i>
<span>Livraison rapide</span>
</div>
</div>
</div>
</div>
</div>
<div class=\"footer-divider\"></div>
<div class=\"footer-bottom d-flex justify-content-center align-items-center flex-wrap\">
<p class=\"footer-text m-0\">
Copyright ©<script>document.write(new Date().getFullYear());</script>
Tous droits réservés | Ce site a été fait avec <i class=\"fa fa-heart-o\" aria-hidden=\"true\" style=\"color: #dc3545;\"></i> par <a
href=\"https://tech.foulgor.com\" target=\"_blank\" style=\"color: #ffa200;\">Foulgor Tech</a>
</p>
</div>
</div>
</footer>
<style>
/* ============================================
FOOTER MODERNE - Design amélioré
============================================ */
.footer-area {
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
position: relative;
overflow: hidden;
padding: 50px 0 20px;
}
.footer-pattern {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image:
radial-gradient(circle at 20% 50%, rgba(255, 162, 0, 0.1) 0%, transparent 50%),
radial-gradient(circle at 80% 80%, rgba(255, 162, 0, 0.08) 0%, transparent 50%);
pointer-events: none;
}
.footer-area .container {
position: relative;
z-index: 1;
}
/* Widgets */
.single-footer-widget {
color: rgba(255, 255, 255, 0.9);
}
.footer-brand {
font-size: 1.6rem;
font-weight: 700;
background: linear-gradient(135deg, #ffa200 0%, #e8910a 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 12px;
display: inline-block;
}
.footer-widget-title {
color: #fff;
font-size: 1rem;
font-weight: 600;
margin-bottom: 18px;
position: relative;
padding-bottom: 8px;
}
.footer-widget-title::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 40px;
height: 3px;
background: linear-gradient(135deg, #ffa200 0%, #e8910a 100%);
border-radius: 2px;
}
.footer-description {
color: rgba(255, 255, 255, 0.7);
line-height: 1.6;
font-size: 0.9rem;
margin-bottom: 0;
}
/* Liste de liens */
.footer-list {
list-style: none;
padding: 0;
margin: 0;
}
.footer-list li {
margin-bottom: 10px;
}
.footer-list li a {
color: rgba(255, 255, 255, 0.7);
text-decoration: none;
transition: all 0.3s ease;
font-size: 0.9rem;
display: inline-flex;
align-items: center;
}
.footer-list li a i {
font-size: 0.8rem;
opacity: 0.6;
transition: all 0.3s ease;
}
.footer-list li a:hover {
color: #ffa200;
transform: translateX(5px);
}
.footer-list li a:hover i {
opacity: 1;
color: #ffa200;
}
/* Newsletter */
.footer-newsletter-text {
color: rgba(255, 255, 255, 0.7);
font-size: 0.85rem;
margin-bottom: 15px;
line-height: 1.5;
}
.footer-newsletter-wrapper {
margin-bottom: 15px;
}
.newsletter-input-group {
display: flex;
align-items: center;
background: rgba(255, 255, 255, 0.08);
border-radius: 30px;
padding: 4px 4px 4px 15px;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.15);
transition: all 0.3s ease;
gap: 8px;
}
.newsletter-input-group:focus-within {
background: rgba(255, 255, 255, 0.12);
border-color: rgba(255, 162, 0, 0.6);
box-shadow: 0 0 0 2px rgba(255, 162, 0, 0.15);
}
.newsletter-icon {
color: rgba(255, 255, 255, 0.5);
font-size: 0.9rem;
flex-shrink: 0;
}
.newsletter-input-group:focus-within .newsletter-icon {
color: #ffa200;
}
.newsletter-input {
flex: 1;
background: transparent;
border: none;
color: #fff;
padding: 10px 8px;
font-size: 0.9rem;
min-width: 0;
}
.newsletter-input::placeholder {
color: rgba(255, 255, 255, 0.4);
font-size: 0.85rem;
}
.newsletter-input:focus {
outline: none;
box-shadow: none;
}
.newsletter-btn {
background: linear-gradient(135deg, #ffa200 0%, #e8910a 100%);
border: none;
color: white;
width: 42px;
height: 42px;
min-width: 42px;
min-height: 42px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
flex-shrink: 0;
box-shadow: 0 4px 15px rgba(255, 162, 0, 0.4),
0 0 0 0 rgba(255, 162, 0, 0.4);
font-size: 0.9rem;
position: relative;
overflow: hidden;
}
.newsletter-btn::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
border-radius: 50%;
background: rgba(255, 255, 255, 0.3);
transform: translate(-50%, -50%);
transition: width 0.6s ease, height 0.6s ease;
}
.newsletter-btn:hover::before {
width: 100%;
height: 100%;
}
.newsletter-btn:hover {
transform: translateX(3px) scale(1.05);
box-shadow: 0 6px 20px rgba(255, 162, 0, 0.5),
0 0 0 8px rgba(255, 162, 0, 0.1);
background: linear-gradient(135deg, #e8910a 0%, #ffa200 100%);
}
.newsletter-btn:active {
transform: translateX(3px) scale(0.98);
box-shadow: 0 3px 10px rgba(255, 162, 0, 0.4);
}
.newsletter-btn:focus {
outline: none;
box-shadow: 0 4px 15px rgba(255, 162, 0, 0.4),
0 0 0 3px rgba(255, 162, 0, 0.3);
}
.newsletter-btn-icon,
.newsletter-btn-loader {
position: relative;
z-index: 2;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
}
.newsletter-btn:hover .newsletter-btn-icon {
transform: translateX(2px) rotate(-10deg);
}
.newsletter-btn.loading .newsletter-btn-icon {
opacity: 0;
transform: scale(0);
}
.newsletter-btn.loading .newsletter-btn-loader {
display: flex !important;
}
.newsletter-btn.success {
background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
box-shadow: 0 4px 15px rgba(40, 167, 69, 0.4);
}
.newsletter-btn.success .newsletter-btn-icon i::before {
content: \"\\f00c\";
}
/* Trust badges */
.footer-trust-badges {
display: flex;
flex-direction: row;
gap: 15px;
flex-wrap: wrap;
}
.trust-item {
display: flex;
align-items: center;
gap: 6px;
color: rgba(255, 255, 255, 0.6);
font-size: 0.8rem;
}
.trust-item i {
color: #ffa200;
font-size: 0.9rem;
}
/* Social icons */
.footer-social {
margin-top: 0 !important;
position: relative !important;
width: 100% !important;
clear: both !important;
float: none !important;
}
.footer-social h6 {
color: #fff;
font-size: 0.95rem;
font-weight: 600;
margin-bottom: 12px !important;
display: block !important;
width: 100% !important;
position: relative !important;
clear: both !important;
float: none !important;
}
.footer-social-icons {
display: flex !important;
gap: 12px !important;
flex-wrap: wrap !important;
align-items: center !important;
justify-content: flex-start !important;
width: 100% !important;
position: relative !important;
clear: both !important;
float: none !important;
margin: 0 !important;
padding: 0 !important;
}
.social-icon {
width: 38px !important;
height: 38px !important;
min-width: 38px !important;
min-height: 38px !important;
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
background: rgba(255, 255, 255, 0.1) !important;
border-radius: 50% !important;
color: rgba(255, 255, 255, 0.8) !important;
text-decoration: none !important;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
font-size: 16px !important;
line-height: 1 !important;
backdrop-filter: blur(10px) !important;
border: 1px solid rgba(255, 255, 255, 0.1) !important;
flex-shrink: 0 !important;
position: relative !important;
float: none !important;
margin: 0 !important;
padding: 0 !important;
vertical-align: middle !important;
}
.social-icon i {
font-size: 16px !important;
line-height: 1 !important;
display: inline-block !important;
transition: transform 0.3s ease !important;
position: relative !important;
z-index: 1 !important;
margin: 0 !important;
padding: 0 !important;
}
.social-icon:hover {
background: linear-gradient(135deg, #ffa200 0%, #e8910a 100%) !important;
transform: translateY(-5px) scale(1.1) !important;
color: white !important;
border-color: transparent !important;
box-shadow: 0 8px 20px rgba(255, 162, 0, 0.4) !important;
}
.social-icon:hover i {
transform: scale(1.1) !important;
}
/* Footer divider */
.footer-divider {
height: 1px;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
margin: 30px 0 20px;
}
/* Footer bottom */
.footer-bottom {
padding-top: 15px;
}
.footer-text {
color: rgba(255, 255, 255, 0.6);
font-size: 0.9rem;
margin: 0;
text-align: center;
}
/* Responsive */
@media(max-width: 991.98px) {
.footer-area {
padding: 40px 0 20px;
}
.single-footer-widget {
margin-bottom: 30px;
}
.footer-social {
margin-top: 15px;
}
}
@media(max-width: 767.98px) {
.footer-area {
padding: 35px 0 18px;
}
.footer-brand {
font-size: 1.4rem;
}
.footer-widget-title {
font-size: 0.95rem;
}
.newsletter-input-group {
padding: 3px 3px 3px 12px;
}
.newsletter-input {
padding: 8px 6px;
font-size: 0.85rem;
}
.newsletter-btn {
width: 38px;
height: 38px;
min-width: 38px;
min-height: 38px;
font-size: 0.85rem;
}
.footer-trust-badges {
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
gap: 12px;
}
}
@media(max-width: 575.98px) {
.footer-area {
padding: 40px 0 20px;
}
.footer-brand {
font-size: 1.3rem;
}
.social-icon {
width: 38px;
height: 38px;
font-size: 16px;
}
.social-icon i {
font-size: 16px;
}
}
</style>
<script>
// Debounced autocomplete for header search
(function(){
const input = document.getElementById('search_input');
const box = document.getElementById('search_suggestions');
if (!input || !box) return;
let t = null;
input.addEventListener('input', function(){
const q = input.value.trim();
clearTimeout(t);
if (q.length === 0) { box.style.display = 'none'; box.innerHTML=''; return; }
t = setTimeout(() => fetchSuggestions(q), 200);
});
function fetchSuggestions(q){
const url = '";
// line 1837
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_api_search_suggest");
yield "' + '?q=' + encodeURIComponent(q);
fetch(url).then(r => r.json()).then(data => {
if (!data.success) { box.style.display='none'; return; }
renderSuggestions(data.results || []);
}).catch(() => { box.style.display='none'; });
}
function renderSuggestions(items){
if (!items.length) { box.style.display='none'; box.innerHTML=''; return; }
box.innerHTML = items.map(it => suggestionItem(it)).join('');
box.style.display = 'block';
}
function suggestionItem(it){
const icon = it.type === 'product' ? 'ti-package' : (it.type === 'shop' ? 'ti-briefcase' : (it.type === 'category' ? 'ti-layers' : 'ti-tag'));
return '<a href=\"' + it.url + '\" class=\"list-group-item list-group-item-action d-flex align-items-center\">'
+ '<i class=\"' + icon + ' me-4\"></i>'
+ '<span class=\"ml-2\">' + escapeHtml(it.label) + '</span>'
+ '<span class=\"badge bg-light text-dark ms-auto\">' + it.type + '</span>'
+ '</a>';
}
function escapeHtml(s){
return s.replace(/[&<>\"]+/g, c => ({'&':'&','<':'<','>':'>','\"':'"'}[c]));
}
document.addEventListener('click', function(e){
if (!box.contains(e.target) && e.target !== input) {
box.style.display='none';
}
});
window.handleSearchSubmit = function(e){
if (e) e.preventDefault();
const first = box.querySelector('a');
if (first) { window.location.href = first.getAttribute('href'); return false; }
// fallback to listing page search by name
const q = input.value.trim();
if (q.length) {
window.location.href = '";
// line 1876
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
yield "' + '?q=' + encodeURIComponent(q);
}
return false;
}
})();
// Gestion des mega-menus avec clic (comme la barre de recherche)
document.addEventListener('DOMContentLoaded', function() {
const dropdownItems = document.querySelectorAll('.nav-item.dropdown');
dropdownItems.forEach(function(item) {
const dropdownToggle = item.querySelector('.dropdown-toggle');
const dropdownMenu = item.querySelector('.mega-menu');
if (!dropdownToggle || !dropdownMenu) return;
// Fermer les autres menus quand on ouvre un nouveau
function closeAllMenus() {
dropdownItems.forEach(function(otherItem) {
const otherMenu = otherItem.querySelector('.mega-menu');
if (otherMenu && otherMenu !== dropdownMenu) {
\$(otherMenu).slideUp(300);
otherMenu.classList.remove('active');
}
});
}
// Toggle au clic (comme la barre de recherche)
dropdownToggle.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
closeAllMenus();
if (dropdownMenu.classList.contains('active')) {
// Fermer le menu
dropdownMenu.style.opacity = '0';
dropdownMenu.style.visibility = 'hidden';
dropdownMenu.style.transform = 'translateX(-50%) translateY(-10px)';
setTimeout(() => {
dropdownMenu.classList.remove('active');
dropdownMenu.style.display = 'none';
}, 300);
} else {
// Ouvrir le menu
dropdownMenu.style.display = 'block';
setTimeout(() => {
dropdownMenu.classList.add('active');
dropdownMenu.style.opacity = '1';
dropdownMenu.style.visibility = 'visible';
dropdownMenu.style.transform = 'translateX(-50%) translateY(0)';
}, 10);
}
});
// Fermer au clic en dehors
document.addEventListener('click', function(e) {
if (!item.contains(e.target) && dropdownMenu.classList.contains('active')) {
dropdownMenu.style.opacity = '0';
dropdownMenu.style.visibility = 'hidden';
dropdownMenu.style.transform = 'translateX(-50%) translateY(-10px)';
setTimeout(() => {
dropdownMenu.classList.remove('active');
dropdownMenu.style.display = 'none';
}, 300);
}
});
// Animation des éléments du menu
const menuItems = dropdownMenu.querySelectorAll('.dropdown-item a');
menuItems.forEach(function(menuItem, index) {
menuItem.style.animationDelay = (index * 0.05) + 's';
});
});
// Gestion des clics sur mobile
if (window.innerWidth <= 768) {
dropdownItems.forEach(function(item) {
const dropdownToggle = item.querySelector('.dropdown-toggle');
const dropdownMenu = item.querySelector('.mega-menu');
dropdownToggle.addEventListener('click', function(e) {
e.preventDefault();
// Fermer tous les autres menus
dropdownItems.forEach(function(otherItem) {
if (otherItem !== item) {
const otherMenu = otherItem.querySelector('.mega-menu');
otherMenu.style.opacity = '0';
otherMenu.style.visibility = 'hidden';
otherMenu.style.transform = 'translateY(-10px)';
}
});
// Toggle le menu actuel
if (dropdownMenu.style.opacity === '1') {
dropdownMenu.style.opacity = '0';
dropdownMenu.style.visibility = 'hidden';
dropdownMenu.style.transform = 'translateY(-10px)';
} else {
dropdownMenu.style.opacity = '1';
dropdownMenu.style.visibility = 'visible';
dropdownMenu.style.transform = 'translateY(0)';
}
});
});
}
// Fermer les menus quand on clique ailleurs
document.addEventListener('click', function(e) {
if (!e.target.closest('.nav-item.dropdown')) {
dropdownItems.forEach(function(item) {
const dropdownMenu = item.querySelector('.mega-menu');
dropdownMenu.style.opacity = '0';
dropdownMenu.style.visibility = 'hidden';
dropdownMenu.style.transform = 'translateY(-10px)';
});
}
});
});
</script>
<!-- End footer Area -->
<script src=\"";
// line 1999
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/vendor/jquery-2.2.4.min.js"), "html", null, true);
yield "\"></script>
<script src=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js\"></script>
<script>
// Initialiser le collapse Bootstrap 5 pour le menu hamburger après chargement de Bootstrap
document.addEventListener('DOMContentLoaded', function() {
// Attendre que Bootstrap soit complètement chargé
if (typeof bootstrap !== 'undefined') {
const navbarToggler = document.querySelector('.navbar-toggler');
const navbarCollapse = document.getElementById('navbarSupportedContent');
if (navbarToggler && navbarCollapse) {
// Bootstrap 5 devrait gérer automatiquement avec data-bs-toggle
// Mais on s'assure que ça fonctionne en écoutant les événements
navbarCollapse.addEventListener('show.bs.collapse', function() {
navbarToggler.setAttribute('aria-expanded', 'true');
navbarToggler.classList.add('active');
});
navbarCollapse.addEventListener('hide.bs.collapse', function() {
navbarToggler.setAttribute('aria-expanded', 'false');
navbarToggler.classList.remove('active');
});
}
}
});
</script>
<script src=\"https://unpkg.com/dropzone@5/dist/min/dropzone.min.js\"></script>
<script src=\"";
// line 2026
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/jquery.ajaxchimp.min.js"), "html", null, true);
yield "\"></script>
<script src=\"";
// line 2027
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/jquery.nice-select.min.js"), "html", null, true);
yield "\"></script>
<script src=\"";
// line 2028
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/jquery.sticky.js"), "html", null, true);
yield "\"></script>
<script src=\"";
// line 2029
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/nouislider.min.js"), "html", null, true);
yield "\"></script>
<script src=\"";
// line 2030
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/countdown.js"), "html", null, true);
yield "\"></script>
<script src=\"";
// line 2031
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/jquery.magnific-popup.min.js"), "html", null, true);
yield "\"></script>
<script src=\"";
// line 2032
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/owl.carousel.min.js"), "html", null, true);
yield "\"></script>
<script src=\"https://maps.googleapis.com/maps/api/js?key=AIzaSyCjCGmQ0Uq4exrzdcL6rvxywDDOvfAu6eE\"></script>
<script src=\"";
// line 2034
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/gmaps.min.js"), "html", null, true);
yield "\"></script>
<script src=\"";
// line 2035
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/main.js"), "html", null, true);
yield "\"></script>
<script>
window.maketouConfig = {
themeStorageKey: 'maketou-theme',
comparison: {
assetBase: '";
// line 2040
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl(""), "js"), "html", null, true);
yield "',
addUrlTemplate: '";
// line 2041
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_api_comparison_add", ["id" => "__ID__"]), "js"), "html", null, true);
yield "',
removeUrlTemplate: '";
// line 2042
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_api_comparison_remove", ["id" => "__ID__"]), "js"), "html", null, true);
yield "',
clearUrl: '";
// line 2043
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_api_comparison_clear"), "js"), "html", null, true);
yield "',
countUrl: '";
// line 2044
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_api_comparison_count"), "js"), "html", null, true);
yield "',
dataUrl: '";
// line 2045
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_api_comparison_data"), "js"), "html", null, true);
yield "',
pageUrl: '";
// line 2046
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_product_comparison"), "js"), "html", null, true);
yield "'
}
};
</script>
<script src=\"";
// line 2050
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/theme-public.js"), "html", null, true);
yield "\"></script>
<script src=\"";
// line 2051
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/comparison-v2.js"), "html", null, true);
yield "\"></script>
";
// line 2053
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->env->getFunction('encore_entry_script_tags')->getCallable()("app"), "html", null, true);
yield "
<!-- PWA Service Worker Registration -->
<script>
// Enregistrement du Service Worker
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('";
// line 2060
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("sw.js"), "html", null, true);
yield "')
.then((registration) => {
console.log('Service Worker enregistré avec succès:', registration.scope);
// Vérifie les mises à jour du service worker
registration.addEventListener('updatefound', () => {
const newWorker = registration.installing;
newWorker.addEventListener('statechange', () => {
if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
// Nouveau service worker disponible
if (confirm('Une nouvelle version de MaketOu est disponible. Voulez-vous l\\'installer maintenant ?')) {
newWorker.postMessage({ type: 'SKIP_WAITING' });
window.location.reload();
}
}
});
});
})
.catch((error) => {
console.log('Échec de l\\'enregistrement du Service Worker:', error);
});
// Écoute les messages du service worker
navigator.serviceWorker.addEventListener('message', (event) => {
console.log('Message du Service Worker:', event.data);
});
});
}
</script>
<!-- PWA Install Script -->
<script src=\"";
// line 2091
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("js/pwa-install.js"), "html", null, true);
yield "\"></script>
<script>
// Charger les compteurs au chargement de la page
document.addEventListener('DOMContentLoaded', function() {
";
// line 2096
if ((($tmp = CoreExtension::getAttribute($this->env, $this->source, ($context["app"] ?? null), "user", [], "any", false, false, false, 2096)) && $tmp instanceof Markup ? (string) $tmp : $tmp)) {
// line 2097
yield " loadNotificationCount();
// Délai pour s'assurer que la session est bien établie après connexion
setTimeout(function() {
loadComparisonCount();
}, 500);
";
}
// line 2103
yield "
// Gérer le bouton de recherche mobile
const searchMobileBtn = document.getElementById('searchMobileBtn');
if (searchMobileBtn) {
searchMobileBtn.addEventListener('click', function(e) {
e.preventDefault();
// Utiliser le même comportement que le bouton desktop
const searchBox = document.getElementById('search_input_box');
if (searchBox) {
searchBox.style.display = 'block';
const searchInput = document.getElementById('search_input');
if (searchInput) {
setTimeout(() => searchInput.focus(), 100);
}
}
});
}
});
function loadNotificationCount() {
";
// line 2123
if ((($tmp = CoreExtension::getAttribute($this->env, $this->source, ($context["app"] ?? null), "user", [], "any", false, false, false, 2123)) && $tmp instanceof Markup ? (string) $tmp : $tmp)) {
// line 2124
yield " fetch('";
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("api_notifications_count");
yield "')
.then(response => {
if (!response.ok) {
throw new Error('Erreur HTTP: ' + response.status);
}
return response.json();
})
.then(data => {
const count = data.count || 0;
// Mettre à jour tous les badges de notification
const badges = [
document.getElementById('notificationBadge'),
document.getElementById('notificationBadgeMobile'),
document.querySelector('.notification-badge')
].filter(badge => badge !== null);
badges.forEach(badge => {
if (count > 0) {
badge.textContent = count;
badge.style.display = 'flex';
badge.style.color = 'white';
badge.style.backgroundColor = '#dc3545';
} else {
badge.style.display = 'none';
}
});
// Si on est sur la page des notifications, mettre à jour aussi le contenu de la page
if (typeof updateNotificationPageContent === 'function') {
updateNotificationPageContent(count);
}
})
.catch(error => {
console.error('Erreur lors du chargement du compteur de notifications:', error);
});
";
}
// line 2161
yield " }
// Exposer la fonction globalement pour qu'elle puisse être appelée depuis d'autres pages
window.loadNotificationCount = loadNotificationCount;
// Recharger le compteur toutes les 30 secondes pour garder les données à jour
";
// line 2167
if ((($tmp = CoreExtension::getAttribute($this->env, $this->source, ($context["app"] ?? null), "user", [], "any", false, false, false, 2167)) && $tmp instanceof Markup ? (string) $tmp : $tmp)) {
// line 2168
yield " setInterval(function() {
loadNotificationCount();
}, 30000);
";
}
// line 2172
yield "
function loadComparisonCount() {
// Ne pas appeler l'API si on est sur une page d'erreur ou de redirection
if (window.location.pathname.includes('/api/') || window.location.pathname.includes('/login')) {
return;
}
// Utiliser un try-catch pour éviter toute redirection
try {
fetch('";
// line 2181
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_api_comparison_count");
yield "', {
method: 'GET',
headers: {
'X-Requested-With': 'XMLHttpRequest',
'Accept': 'application/json'
},
credentials: 'same-origin',
redirect: 'error' // Empêcher les redirections automatiques
})
.then(response => {
// Vérifier si la réponse est OK
if (!response.ok) {
// Si c'est une redirection (301, 302, etc.) ou une erreur d'authentification, ignorer silencieusement
if (response.status >= 300 && response.status < 400) {
console.warn('Redirection détectée, arrêt de la requête');
return null;
}
if (response.status === 401 || response.status === 403) {
console.warn('Utilisateur non authentifié pour la comparaison');
return null;
}
// Pour les autres erreurs, throw pour être capturé par catch
throw new Error('Erreur HTTP: ' + response.status);
}
// Vérifier que c'est bien du JSON
const contentType = response.headers.get('content-type');
if (!contentType || !contentType.includes('application/json')) {
// Si ce n'est pas du JSON, c'est probablement une redirection HTML
console.warn('La réponse n\\'est pas du JSON, probable redirection');
return null;
}
return response.json();
})
.then(data => {
// Si data est null (redirection ou erreur), ne rien faire
if (!data || typeof data.count === 'undefined') {
return;
}
// Mettre à jour les badges desktop et mobile
const badges = [
document.getElementById('comparisonBadge'),
document.getElementById('comparisonBadgeMobile')
];
badges.forEach(badge => {
if (badge) {
if (data.count > 0) {
badge.textContent = data.count;
badge.style.display = 'flex';
} else {
badge.style.display = 'none';
}
}
});
})
.catch(error => {
// Ne pas afficher d'erreur si c'est juste une absence d'authentification ou une redirection
if (error.message && !error.message.includes('401') && !error.message.includes('403') && !error.message.includes('redirect')) {
console.error('Erreur lors du chargement du compteur de comparaison:', error);
}
// Empêcher toute redirection vers l'URL de l'API
return false;
});
} catch (e) {
// Capturer toute erreur qui pourrait causer une redirection
console.warn('Erreur lors de l\\'appel à l\\'API de comparaison:', e);
}
}
// Fonction globale pour gérer la comparaison
function toggleComparison(productId, element) {
if (!element) {
element = document.querySelector(`.comparison-btn[data-product-id=\"\${productId}\"]`);
}
if (!element) {
console.error('Bouton de comparaison non trouvé pour le produit', productId);
return;
}
const originalHtml = element.innerHTML;
// Désactiver le bouton/lien
if (element.tagName === 'BUTTON') {
element.disabled = true;
} else {
element.style.pointerEvents = 'none';
element.style.opacity = '0.6';
}
element.innerHTML = '<span class=\"spinner-border spinner-border-sm\"></span>';
// Vérifier d'abord si le produit est déjà en comparaison
let isInComparison = false;
fetch(`/api/comparison/status/\${productId}`)
.then(response => {
const contentType = response.headers.get('content-type');
if (contentType && contentType.includes('text/html')) {
window.location.href = '";
// line 2279
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_app_login");
yield "';
throw new Error('Not authenticated');
}
return response.json();
})
.then(data => {
isInComparison = data.inComparison;
const url = isInComparison ? `/api/comparison/remove/\${productId}` : `/api/comparison/add/\${productId}`;
return fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
}
});
})
.then(response => {
const contentType = response.headers.get('content-type');
if (contentType && contentType.includes('text/html')) {
window.location.href = '";
// line 2299
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_app_login");
yield "';
throw new Error('Not authenticated');
}
return response.json();
})
.then(data => {
if (data.success) {
// Mettre à jour le compteur
loadComparisonCount();
// Mettre à jour l'apparence du bouton
if (element) {
// Inverser l'état (car on vient de le changer)
const newState = !isInComparison;
// Restaurer le HTML original puis mettre à jour
element.innerHTML = originalHtml;
if (newState) {
element.classList.add('active');
// Mettre à jour le texte pour les deux types de boutons
const textEl = element.querySelector('.comparison-text') || element.querySelector('.hover-text') || element.querySelector('p.hover-text');
if (textEl) textEl.textContent = 'En comparaison';
// Mettre à jour l'icône si nécessaire (chercher dans span ou i)
const iconEl = element.querySelector('.lnr-sync, span.lnr-sync, [class*=\"sync\"], i[class*=\"sync\"]');
if (iconEl) {
iconEl.style.color = '#28a745';
iconEl.classList.add('active');
}
} else {
element.classList.remove('active');
const textEl = element.querySelector('.comparison-text') || element.querySelector('.hover-text') || element.querySelector('p.hover-text');
if (textEl) textEl.textContent = 'Comparer';
// Restaurer la couleur de l'icône
const iconEl = element.querySelector('.lnr-sync, span.lnr-sync, [class*=\"sync\"], i[class*=\"sync\"]');
if (iconEl) {
iconEl.style.color = '';
iconEl.classList.remove('active');
}
}
}
// Afficher une notification
showNotification(data.message, 'success');
} else {
showNotification(data.message, 'error');
if (element) {
element.innerHTML = originalHtml;
}
}
})
.catch(error => {
console.error('Erreur:', error);
showNotification('Une erreur est survenue', 'error');
if (element) {
element.innerHTML = originalHtml;
}
})
.finally(() => {
if (element) {
if (element.tagName === 'BUTTON') {
element.disabled = false;
} else {
element.style.pointerEvents = '';
element.style.opacity = '';
}
}
});
}
// Fonction globale pour gérer les favoris
function toggleWishlist(productId, element) {
if (!element) {
element = document.querySelector(`.wishlist-btn[data-product-id=\"\${productId}\"]`);
}
if (!element) {
console.error('Bouton de wishlist non trouvé pour le produit', productId);
return;
}
const originalHtml = element.innerHTML;
// Désactiver le bouton/lien
if (element.tagName === 'BUTTON') {
element.disabled = true;
} else {
element.style.pointerEvents = 'none';
element.style.opacity = '0.6';
}
element.innerHTML = '<span class=\"spinner-border spinner-border-sm\"></span>';
// Vérifier d'abord si le produit est déjà en favoris
let isInWishlist = false;
fetch(`/api/wishlist/status/\${productId}`)
.then(response => {
const contentType = response.headers.get('content-type');
if (contentType && contentType.includes('text/html')) {
window.location.href = '";
// line 2396
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_app_login");
yield "';
throw new Error('Not authenticated');
}
return response.json();
})
.then(data => {
isInWishlist = data.inWishlist;
const url = isInWishlist ? `/api/wishlist/remove/\${productId}` : `/api/wishlist/add/\${productId}`;
return fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
}
});
})
.then(response => {
const contentType = response.headers.get('content-type');
if (contentType && contentType.includes('text/html')) {
window.location.href = '";
// line 2416
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_app_login");
yield "';
throw new Error('Not authenticated');
}
return response.json();
})
.then(data => {
if (data.success) {
// Mettre à jour l'apparence du bouton
if (element) {
// Inverser l'état (car on vient de le changer)
const newState = !isInWishlist;
// Restaurer le HTML original puis mettre à jour
element.innerHTML = originalHtml;
// Chercher l'icône dans span ou i
const icon = element.querySelector('span.lnr-heart, i.lnr-heart, [class*=\"lnr-heart\"]');
const text = element.querySelector('.wishlist-text') || element.querySelector('.hover-text') || element.querySelector('p.hover-text');
if (newState) {
if (icon) {
// Pour les icônes linr, on change la classe
if (icon.classList.contains('lnr-heart')) {
icon.classList.remove('lnr-heart');
}
if (!icon.classList.contains('lnr-heart-filled')) {
icon.classList.add('lnr-heart-filled');
}
icon.style.color = '#dc3545';
}
element.classList.add('active');
if (text) text.textContent = 'Dans favoris';
} else {
if (icon) {
// Restaurer l'icône originale
if (icon.classList.contains('lnr-heart-filled')) {
icon.classList.remove('lnr-heart-filled');
}
if (!icon.classList.contains('lnr-heart')) {
icon.classList.add('lnr-heart');
}
icon.style.color = '';
}
element.classList.remove('active');
if (text) text.textContent = 'Favoris';
}
}
// Afficher une notification
showNotification(data.message, 'success');
// Si on est sur la page wishlist, recharger la page
if (window.location.pathname.includes('/account/wishlist')) {
setTimeout(() => location.reload(), 1000);
}
} else {
showNotification(data.message, 'error');
if (element) {
element.innerHTML = originalHtml;
}
}
})
.catch(error => {
console.error('Erreur:', error);
showNotification('Une erreur est survenue', 'error');
if (element) {
element.innerHTML = originalHtml;
}
})
.finally(() => {
if (element) {
if (element.tagName === 'BUTTON') {
element.disabled = false;
} else {
element.style.pointerEvents = '';
element.style.opacity = '';
}
}
});
}
// Fonction pour afficher des notifications
function showNotification(message, type = 'success') {
// Créer l'élément de notification
const notification = document.createElement('div');
notification.className = `alert alert-\${type === 'success' ? 'success' : 'danger'} alert-dismissible fade show position-fixed`;
notification.style.cssText = 'top: 20px; right: 20px; z-index: 9999; min-width: 300px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);';
notification.innerHTML = `
\${message}
<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\"></button>
`;
document.body.appendChild(notification);
// Supprimer automatiquement après 3 secondes
setTimeout(() => {
notification.remove();
}, 3000);
}
// Initialiser les alertes Bootstrap 5 pour la fermeture
document.addEventListener('DOMContentLoaded', function() {
// S'assurer que les alertes peuvent être fermées
const alertCloseButtons = document.querySelectorAll('.flash-message .btn-close');
alertCloseButtons.forEach(function(button) {
button.addEventListener('click', function() {
const alert = this.closest('.alert');
if (alert) {
alert.classList.remove('show');
setTimeout(function() {
alert.remove();
}, 150);
}
});
});
// Charger les statuts initiaux des produits
";
// line 2533
if ((($tmp = CoreExtension::getAttribute($this->env, $this->source, ($context["app"] ?? null), "user", [], "any", false, false, false, 2533)) && $tmp instanceof Markup ? (string) $tmp : $tmp)) {
// line 2534
yield " // Charger les statuts de comparaison pour tous les produits visibles
document.querySelectorAll('.comparison-btn[data-product-id]').forEach(btn => {
const productId = btn.dataset.productId;
fetch(`/api/comparison/status/\${productId}`)
.then(response => response.json())
.then(data => {
if (data.inComparison) {
btn.classList.add('active');
// Mettre à jour le texte pour les deux types de boutons
const textEl = btn.querySelector('.comparison-text') || btn.querySelector('.hover-text') || btn.querySelector('p.hover-text');
if (textEl) textEl.textContent = 'En comparaison';
// Mettre à jour l'icône si nécessaire
const iconEl = btn.querySelector('.lnr-sync, [class*=\"sync\"]');
if (iconEl) iconEl.style.color = '#28a745';
}
})
.catch(() => {});
});
// Charger les statuts de wishlist pour tous les produits visibles
document.querySelectorAll('.wishlist-btn[data-product-id]').forEach(btn => {
const productId = btn.dataset.productId;
fetch(`/api/wishlist/status/\${productId}`)
.then(response => response.json())
.then(data => {
if (data.inWishlist) {
btn.classList.add('active');
// Chercher l'icône dans span ou i
const icon = btn.querySelector('span.lnr-heart, i.lnr-heart, [class*=\"lnr-heart\"]');
if (icon) {
icon.classList.remove('lnr-heart');
icon.classList.add('lnr-heart-filled');
icon.style.color = '#dc3545';
}
// Mettre à jour le texte pour les deux types de boutons
const textEl = btn.querySelector('.wishlist-text') || btn.querySelector('.hover-text') || btn.querySelector('p.hover-text');
if (textEl) textEl.textContent = 'Dans favoris';
}
})
.catch(() => {});
});
// Charger le compteur de comparaison
loadComparisonCount();
";
}
// line 2579
yield " });
</script>
<script>
// Loader global pour tous les boutons de formulaire
document.addEventListener('DOMContentLoaded', function() {
// Intercepter tous les formulaires
const forms = document.querySelectorAll('form');
forms.forEach(function(form) {
form.addEventListener('submit', function(e) {
const submitButtons = form.querySelectorAll('button[type=\"submit\"], input[type=\"submit\"], button:not([type])');
submitButtons.forEach(function(button) {
// Vérifier si le bouton n'est pas déjà désactivé
if (!button.disabled && !button.classList.contains('loading')) {
button.classList.add('loading');
button.disabled = true;
// Sauvegarder le texte original
const originalText = button.innerHTML;
button.setAttribute('data-original-text', originalText);
// Ajouter le loader
button.innerHTML = '<span class=\"spinner-border spinner-border-sm me-2\" role=\"status\" aria-hidden=\"true\"></span>Envoi...';
// Si le formulaire n'est pas valide, réactiver le bouton après 1 seconde
setTimeout(function() {
if (!form.checkValidity()) {
button.classList.remove('loading');
button.disabled = false;
button.innerHTML = originalText;
}
}, 1000);
}
});
});
});
// Pour les boutons qui déclenchent des actions AJAX
const ajaxButtons = document.querySelectorAll('[data-ajax], .ajax-submit, button[data-submit]');
ajaxButtons.forEach(function(button) {
button.addEventListener('click', function(e) {
if (this.disabled || this.classList.contains('loading')) {
e.preventDefault();
return false;
}
this.classList.add('loading');
this.disabled = true;
const originalText = this.innerHTML;
this.setAttribute('data-original-text', originalText);
this.innerHTML = '<span class=\"spinner-border spinner-border-sm me-2\" role=\"status\" aria-hidden=\"true\"></span>Chargement...';
});
});
// Gestionnaire spécifique pour le formulaire de newsletter
const newsletterForm = document.querySelector('.footer-newsletter-form');
if (newsletterForm) {
newsletterForm.addEventListener('submit', function(e) {
const submitBtn = this.querySelector('.newsletter-btn');
if (submitBtn && !submitBtn.disabled) {
submitBtn.classList.add('loading');
submitBtn.disabled = true;
// Afficher le loader et masquer l'icône
const icon = submitBtn.querySelector('.newsletter-btn-icon');
const loader = submitBtn.querySelector('.newsletter-btn-loader');
if (icon) icon.style.display = 'none';
if (loader) loader.style.display = 'flex';
// Réactiver le bouton après 5 secondes au cas où la requête échoue silencieusement
setTimeout(function() {
if (submitBtn.classList.contains('loading')) {
submitBtn.classList.remove('loading');
submitBtn.disabled = false;
if (icon) icon.style.display = 'flex';
if (loader) loader.style.display = 'none';
}
}, 5000);
}
});
// Gérer la réponse du formulaire (si AJAX)
newsletterForm.addEventListener('submit', function(e) {
// Si le formulaire est soumis normalement (non-AJAX), le navigateur gère la réponse
// Sinon, on peut intercepter pour gérer la réponse AJAX ici
});
}
});
// CSS pour le spinner
const style = document.createElement('style');
style.textContent = `
.spinner-border-sm {
width: 1rem;
height: 1rem;
border-width: 0.15em;
}
.spinner-border {
display: inline-block;
width: 1rem;
height: 1rem;
vertical-align: text-bottom;
border: 0.15em solid currentColor;
border-right-color: transparent;
border-radius: 50%;
animation: spinner-border 0.75s linear infinite;
}
@keyframes spinner-border {
to { transform: rotate(360deg); }
}
button.loading {
opacity: 0.7;
cursor: not-allowed !important;
}
`;
document.head.appendChild(style);
</script>
\t<!-- Modal Global Custom Alert -->
\t<div class=\"modal fade custom-alert-modal\" id=\"customAlertModal\" tabindex=\"-1\" aria-labelledby=\"customAlertModalLabel\" aria-hidden=\"true\">
\t\t<div class=\"modal-dialog modal-dialog-centered\">
\t\t\t<div class=\"modal-content\">
\t\t\t\t<div class=\"modal-header\">
\t\t\t\t\t<h5 class=\"modal-title text-white\" id=\"customAlertModalLabel\">Notification</h5>
\t\t\t\t\t<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Close\"></button>
\t\t\t\t</div>
\t\t\t\t<div class=\"modal-body\">
\t\t\t\t\t<div class=\"alert-icon\" id=\"alertIcon\">
\t\t\t\t\t\t<i class=\"lnr lnr-info-circle\"></i>
\t\t\t\t\t</div>
\t\t\t\t\t<p class=\"alert-message\" id=\"alertMessage\"></p>
\t\t\t\t</div>
\t\t\t\t<div class=\"modal-footer\">
\t\t\t\t\t<button type=\"button\" class=\"btn btn-primary\" data-bs-dismiss=\"modal\">OK</button>
\t\t\t\t</div>
\t\t\t</div>
\t\t</div>
\t</div>
\t<script>
\t\t// Fonction globale pour remplacer alert() ou afficher des messages
\t\tfunction showCustomAlert(message, type = 'info') {
\t\t\tconst modalEl = document.getElementById('customAlertModal');
\t\t\tif (!modalEl) {
\t\t\t\t// Fallback sur showNotification
\t\t\t\tlet notifyType = type === 'error' || type === 'danger' ? 'error' : (type === 'success' ? 'success' : 'warning');
\t\t\t\tif (typeof showNotification === 'function') {
\t\t\t\t\tshowNotification(message, notifyType);
\t\t\t\t} else {
\t\t\t\t\talert(message);
\t\t\t\t}
\t\t\t\treturn;
\t\t\t}
\t\t\t
\t\t\tconst modal = new bootstrap.Modal(modalEl);
\t\t\tconst alertMessage = document.getElementById('alertMessage');
\t\t\tconst alertIcon = document.getElementById('alertIcon');
\t\t\tconst modalTitle = document.getElementById('customAlertModalLabel');
\t\t\talertMessage.textContent = message;
\t\t\t// Définir l'icône et le titre selon le type
\t\t\tlet iconClass = 'lnr lnr-info-circle';
\t\t\tlet title = 'Information';
\t\t\tswitch (type) {
\t\t\t\tcase 'success':
\t\t\t\t\ticonClass = 'lnr lnr-checkmark-circle';
\t\t\t\t\ttitle = 'Succès';
\t\t\t\t\talertIcon.className = 'alert-icon success';
\t\t\t\t\tbreak;
\t\t\t\tcase 'error':
\t\t\t\tcase 'danger':
\t\t\t\t\ticonClass = 'lnr lnr-warning';
\t\t\t\t\ttitle = 'Erreur';
\t\t\t\t\talertIcon.className = 'alert-icon error';
\t\t\t\t\tbreak;
\t\t\t\tcase 'warning':
\t\t\t\t\ticonClass = 'lnr lnr-warning';
\t\t\t\t\ttitle = 'Attention';
\t\t\t\t\talertIcon.className = 'alert-icon warning';
\t\t\t\t\tbreak;
\t\t\t\tdefault:
\t\t\t\t\ticonClass = 'lnr lnr-info-circle';
\t\t\t\t\ttitle = 'Information';
\t\t\t\t\talertIcon.className = 'alert-icon info';
\t\t\t}
\t\t\talertIcon.innerHTML = `<i class=\"\${iconClass}\"></i>`;
\t\t\tmodalTitle.textContent = title;
\t\t\tmodal.show();
\t\t};
\t</script>
";
// line 2779
yield from $this->unwrap()->yieldBlock('javascripts', $context, $blocks);
// line 2781
yield "</body>
</html>
";
$__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
yield from [];
}
// line 32
/**
* @return iterable<null|scalar|\Stringable>
*/
public function block_title(array $context, array $blocks = []): iterable
{
$macros = $this->macros;
$__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
$__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "title"));
$__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "title"));
yield "MaketOu";
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
$__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
yield from [];
}
// line 711
/**
* @return iterable<null|scalar|\Stringable>
*/
public function block_stylesheets(array $context, array $blocks = []): iterable
{
$macros = $this->macros;
$__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
$__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "stylesheets"));
$__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "stylesheets"));
// line 712
yield " ";
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->env->getFunction('encore_entry_link_tags')->getCallable()("app"), "html", null, true);
yield "
";
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
$__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
yield from [];
}
// line 1247
/**
* @return iterable<null|scalar|\Stringable>
*/
public function block_body(array $context, array $blocks = []): iterable
{
$macros = $this->macros;
$__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
$__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "body"));
$__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "body"));
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
$__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
yield from [];
}
// line 2779
/**
* @return iterable<null|scalar|\Stringable>
*/
public function block_javascripts(array $context, array $blocks = []): iterable
{
$macros = $this->macros;
$__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
$__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "javascripts"));
$__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "javascripts"));
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
$__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
yield from [];
}
/**
* @codeCoverageIgnore
*/
public function getTemplateName(): string
{
return "base_home.html.twig";
}
/**
* @codeCoverageIgnore
*/
public function isTraitable(): bool
{
return false;
}
/**
* @codeCoverageIgnore
*/
public function getDebugInfo(): array
{
return array ( 3295 => 2779, 3273 => 1247, 3259 => 712, 3246 => 711, 3223 => 32, 3210 => 2781, 3208 => 2779, 3006 => 2579, 2959 => 2534, 2957 => 2533, 2837 => 2416, 2814 => 2396, 2714 => 2299, 2691 => 2279, 2590 => 2181, 2579 => 2172, 2573 => 2168, 2571 => 2167, 2563 => 2161, 2522 => 2124, 2520 => 2123, 2498 => 2103, 2490 => 2097, 2488 => 2096, 2480 => 2091, 2446 => 2060, 2436 => 2053, 2431 => 2051, 2427 => 2050, 2420 => 2046, 2416 => 2045, 2412 => 2044, 2408 => 2043, 2404 => 2042, 2400 => 2041, 2396 => 2040, 2388 => 2035, 2384 => 2034, 2379 => 2032, 2375 => 2031, 2371 => 2030, 2367 => 2029, 2363 => 2028, 2359 => 2027, 2355 => 2026, 2325 => 1999, 2199 => 1876, 2157 => 1837, 1643 => 1326, 1631 => 1317, 1627 => 1316, 1623 => 1315, 1619 => 1314, 1615 => 1313, 1604 => 1305, 1600 => 1304, 1596 => 1303, 1592 => 1302, 1583 => 1295, 1578 => 1293, 1573 => 1292, 1567 => 1290, 1565 => 1289, 1561 => 1288, 1557 => 1287, 1553 => 1286, 1513 => 1248, 1511 => 1247, 1503 => 1242, 1495 => 1237, 1483 => 1227, 1473 => 1223, 1469 => 1221, 1465 => 1220, 1462 => 1219, 1452 => 1215, 1448 => 1213, 1444 => 1212, 1441 => 1211, 1431 => 1207, 1427 => 1205, 1423 => 1204, 1420 => 1203, 1410 => 1199, 1406 => 1197, 1402 => 1196, 1378 => 1174, 1370 => 1170, 1362 => 1166, 1360 => 1165, 1349 => 1156, 1340 => 1151, 1338 => 1150, 1327 => 1146, 1317 => 1143, 1308 => 1137, 1302 => 1136, 1297 => 1134, 1291 => 1133, 1286 => 1131, 1280 => 1130, 1275 => 1128, 1269 => 1127, 1264 => 1125, 1258 => 1124, 1243 => 1114, 1226 => 1106, 954 => 836, 951 => 835, 949 => 834, 827 => 714, 825 => 711, 181 => 69, 176 => 66, 172 => 65, 168 => 64, 164 => 63, 160 => 62, 156 => 61, 152 => 60, 148 => 59, 144 => 58, 140 => 57, 136 => 56, 132 => 55, 128 => 54, 103 => 32, 90 => 22, 84 => 19, 80 => 18, 76 => 17, 72 => 16, 66 => 13, 52 => 1,);
}
public function getSourceContext(): Source
{
return new Source("<!DOCTYPE html>
<html lang=\"fr\" class=\"no-js\" data-theme=\"light\" data-bs-theme=\"light\">
<head>
<!-- Mobile Specific Meta -->
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no\">
<meta name=\"mobile-web-app-capable\" content=\"yes\">
<meta name=\"apple-mobile-web-app-capable\" content=\"yes\">
<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"default\">
<meta name=\"apple-mobile-web-app-title\" content=\"MaketOu\">
<meta name=\"theme-color\" content=\"#ffa200\">
<meta name=\"msapplication-TileColor\" content=\"#ffa200\">
<meta name=\"msapplication-config\" content=\"{{ asset('favicon/browserconfig.xml') }}\">
<!-- Favicon-->
<link rel=\"shortcut icon\" href=\"{{ asset('favicon/favicon-16x16.png') }}\">
<link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"{{ asset('favicon/apple-touch-icon.png') }}\">
<link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"{{ asset('favicon/favicon-32x32.png') }}\">
<link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"{{ asset('favicon/favicon-16x16.png') }}\">
<!-- PWA Manifest -->
<link rel=\"manifest\" href=\"{{ asset('manifest.json') }}\">
<!-- Author Meta -->
<meta name=\"author\" content=\"Foulgor Tech\">
<!-- Meta Description -->
<meta name=\"description\" content=\"\">
<!-- Meta Keyword -->
<meta name=\"keywords\" content=\"\">
<!-- meta character set -->
<meta charset=\"UTF-8\">
<!-- Site Title -->
<title>{% block title %}MaketOu{% endblock %}</title>
<script>
(function () {
try {
var storageKey = 'maketou-theme';
var savedTheme = window.localStorage.getItem(storageKey);
var theme = savedTheme === 'dark' || savedTheme === 'light'
? savedTheme
: (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', theme);
document.documentElement.setAttribute('data-bs-theme', theme);
document.documentElement.classList.toggle('dark-mode', theme === 'dark');
} catch (error) {
document.documentElement.setAttribute('data-theme', 'light');
document.documentElement.setAttribute('data-bs-theme', 'light');
}
})();
</script>
<!--
CSS
============================================= -->
<link rel=\"stylesheet\" href=\"https://unpkg.com/dropzone@5/dist/min/dropzone.min.css\" />
<link rel=\"stylesheet\" href=\"{{ asset('ui/css/linearicons.css') }}\">
<link rel=\"stylesheet\" href=\"{{ asset('ui/css/font-awesome.min.css') }}\">
<link rel=\"stylesheet\" href=\"{{ asset('ui/css/themify-icons.css') }}\">
<link rel=\"stylesheet\" href=\"{{ asset('ui/css/bootstrap.css') }}\">
<link rel=\"stylesheet\" href=\"{{ asset('ui/css/owl.carousel.css') }}\">
<link rel=\"stylesheet\" href=\"{{ asset('ui/css/nice-select.css') }}\">
<link rel=\"stylesheet\" href=\"{{ asset('ui/css/nouislider.min.css') }}\">
<link rel=\"stylesheet\" href=\"{{ asset('ui/css/ion.rangeSlider.css') }}\"/>
<link rel=\"stylesheet\" href=\"{{ asset('ui/css/ion.rangeSlider.skinFlat.css') }}\"/>
<link rel=\"stylesheet\" href=\"{{ asset('ui/css/magnific-popup.css') }}\">
<link rel=\"stylesheet\" href=\"{{ asset('ui/css/main.css') }}\">
<link rel=\"stylesheet\" href=\"{{ asset('ui/css/buttons-unified.css') }}\">
<link rel=\"stylesheet\" href=\"{{ asset('ui/css/theme-public.css') }}\">
<meta charset=\"UTF-8\">
{# Run `composer require symfony/webpack-encore-bundle` to start using Symfony UX #}
<style>
/* Styles pour l'icône de notification */
.notification-icon {
position: relative;
display: inline-block;
color: #333;
text-decoration: none;
transition: color 0.3s ease;
}
.notification-icon:hover {
color: #007bff;
}
.notification-badge {
position: absolute;
top: -4px;
right: -2px;
background: #dc3545 !important;
color: white !important;
border-radius: 50%;
width: 18px;
height: 18px;
font-size: 8px !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
font-weight: bold !important;
animation: pulse 2s infinite;
z-index: 10;
line-height: 1 !important;
}
/* Forcer le texte en blanc pour tous les éléments du badge - avec spécificité maximale */
.notification-badge,
.notification-badge.text-white,
.notification-badge *,
#notificationBadge,
#notificationBadge.text-white,
#notificationBadge *,
span.notification-badge,
span.notification-badge.text-white,
span#notificationBadge,
span#notificationBadge.text-white {
color: white !important;
text-color: white !important;
-webkit-text-fill-color: white !important;
}
/* S'assurer que le contenu texte est bien en blanc */
.notification-badge::before,
.notification-badge::after {
color: white !important;
}
/* Forcer la couleur pour tous les sélecteurs possibles avec spécificité maximale */
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon .notification-badge,
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon .notification-badge.text-white,
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon span.notification-badge,
.notification-icon .notification-badge,
.notification-icon .notification-badge.text-white,
.notification-icon span.notification-badge,
a.notification-icon .notification-badge,
a.notification-icon span.notification-badge {
color: white !important;
text-color: white !important;
-webkit-text-fill-color: white !important;
}
/* Forcer la couleur pour tous les enfants directs */
.notification-icon > .notification-badge,
.notification-icon > span.notification-badge {
color: white !important;
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.1); }
100% { transform: scale(1); }
}
.notification-icon:hover .notification-badge {
animation: none;
}
/* Container pour les icônes - toujours alignées horizontalement */
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper {
display: flex !important;
flex-direction: row !important;
align-items: center !important;
justify-content: center !important;
gap: 15px !important;
list-style: none !important;
margin: 0 !important;
padding: 0 !important;
width: auto !important;
}
/* Surcharger les styles existants pour les li contenant le wrapper */
.header_area .navbar .nav.navbar-nav.navbar-right li:has(.navbar-icons-wrapper) {
margin-left: 0 !important;
margin-right: 0 !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
}
/* Styles pour les icônes */
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .cart,
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon,
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search {
display: flex !important;
align-items: center !important;
justify-content: center !important;
width: 40px !important;
height: 40px !important;
min-width: 40px !important;
min-height: 40px !important;
color: #333 !important;
text-decoration: none !important;
transition: all 0.3s ease !important;
border-radius: 50% !important;
position: relative !important;
margin: 0 !important;
padding: 0 !important;
}
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .cart:hover,
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon:hover,
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search:hover {
background-color: #f0f0f0 !important;
color: #ffa200 !important;
transform: scale(1.1) !important;
}
/* Surcharger le line-height de main.css */
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .cart span,
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon span,
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search span {
font-size: 18px !important;
line-height: 1 !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
color: inherit !important;
font-weight: normal !important;
}
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search {
background: transparent !important;
border: 0 !important;
cursor: pointer !important;
padding: 0 !important;
}
/* Alignement des icônes navbar sur mobile */
@media (max-width: 991.98px) {
/* Container navbar-right en colonne sur mobile */
.header_area .navbar .nav.navbar-nav.navbar-right {
display: flex !important;
flex-direction: column !important;
align-items: center !important;
justify-content: center !important;
width: 100% !important;
gap: 0 !important;
margin: 0 !important;
padding: 10px 0 !important;
}
/* Le container d'icônes reste horizontal */
.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper {
width: 100% !important;
justify-content: center !important;
display: flex !important;
flex-direction: row !important;
}
/* Le bouton compte en bas - pleine largeur */
.header_area .navbar .nav.navbar-nav.navbar-right li:last-child {
width: 100% !important;
display: flex !important;
justify-content: center !important;
margin-top: 12px !important;
padding-top: 12px !important;
border-top: 1px solid #e0e0e0 !important;
}
/* Bouton compte responsive */
.header_area .navbar .nav.navbar-nav.navbar-right .btn-account {
width: 100%;
max-width: 200px;
padding: 10px 20px;
font-size: 14px;
}
}
/* Styles pour les messages flash - Design moderne */
.flash-message {
animation: slideInDownFlash 0.4s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
overflow: visible !important;
border: none !important;
padding: 16px 20px !important;
border-radius: 12px !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
display: flex !important;
align-items: center;
gap: 12px;
margin-bottom: 15px;
backdrop-filter: blur(10px);
transition: all 0.3s ease;
}
/* S'assurer que les icônes Font Awesome sont visibles */
.flash-message i.fa {
display: inline-block !important;
visibility: visible !important;
opacity: 1 !important;
width: auto !important;
height: auto !important;
font-family: \"FontAwesome\" !important;
font-style: normal !important;
font-weight: normal !important;
text-rendering: auto !important;
-webkit-font-smoothing: antialiased !important;
-moz-osx-font-smoothing: grayscale !important;
line-height: 1 !important;
flex-shrink: 0 !important;
}
/* Forcer l'affichage des pseudo-éléments Font Awesome */
.flash-message i.fa::before {
display: inline-block !important;
visibility: visible !important;
opacity: 1 !important;
content: attr(data-icon) !important;
}
/* Styles spécifiques pour chaque icône */
.flash-message i.fa-check-circle::before {
content: \"\\f058\" !important;
}
.flash-message i.fa-exclamation-circle::before {
content: \"\\f06a\" !important;
}
.flash-message i.fa-exclamation-triangle::before {
content: \"\\f071\" !important;
}
.flash-message i.fa-info-circle::before {
content: \"\\f05a\" !important;
}
.flash-message:hover {
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2) !important;
transform: translateY(-2px);
}
.flash-message::before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 5px;
background: linear-gradient(180deg, currentColor 0%, rgba(255,255,255,0.3) 100%);
border-radius: 12px 0 0 12px;
}
.flash-message.alert-success {
background: linear-gradient(135deg, #d4edda 0%, #c3e6cb 100%) !important;
color: #155724 !important;
border-left: 5px solid #28a745 !important;
}
.flash-message.alert-success i.fa {
color: #28a745 !important;
font-size: 1.3rem !important;
display: inline-block !important;
margin-right: 8px;
vertical-align: middle;
}
.flash-message.alert-danger {
background: linear-gradient(135deg, #f8d7da 0%, #f5c6cb 100%) !important;
color: #721c24 !important;
border-left: 5px solid #dc3545 !important;
}
.flash-message.alert-danger i.fa {
color: #dc3545 !important;
font-size: 1.3rem !important;
display: inline-block !important;
margin-right: 8px;
vertical-align: middle;
}
.flash-message.alert-warning {
background: linear-gradient(135deg, #fff3cd 0%, #ffeaa7 100%) !important;
color: #856404 !important;
border-left: 5px solid #ffc107 !important;
}
.flash-message.alert-warning i.fa {
color: #ffa200 !important;
font-size: 1.3rem !important;
display: inline-block !important;
margin-right: 8px;
vertical-align: middle;
}
.flash-message.alert-info {
background: linear-gradient(135deg, #d1ecf1 0%, #bee5eb 100%) !important;
color: #0c5460 !important;
border-left: 5px solid #17a2b8 !important;
}
.flash-message.alert-info i.fa {
color: #17a2b8 !important;
font-size: 1.3rem !important;
display: inline-block !important;
margin-right: 8px;
vertical-align: middle;
}
.flash-message strong {
flex: 1;
font-weight: 600;
font-size: 0.95rem;
line-height: 1.5;
}
.flash-message .btn-close {
opacity: 0.7;
padding: 8px !important;
margin: -8px -8px -8px auto !important;
transition: all 0.2s ease;
border-radius: 50% !important;
background: rgba(0, 0, 0, 0.05) !important;
width: 32px !important;
height: 32px !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
border: none !important;
cursor: pointer !important;
position: relative !important;
}
/* Ajouter une icône X visible dans le bouton */
.flash-message .btn-close::before {
content: '×' !important;
font-size: 24px !important;
line-height: 1 !important;
color: currentColor !important;
font-weight: bold !important;
display: block !important;
position: absolute !important;
top: 50% !important;
left: 50% !important;
transform: translate(-50%, -50%) !important;
}
.flash-message .btn-close:hover {
opacity: 1 !important;
background: rgba(0, 0, 0, 0.15) !important;
transform: rotate(90deg) !important;
}
.flash-message .btn-close:hover::before {
transform: translate(-50%, -50%) rotate(-90deg) !important;
}
@keyframes slideInDownFlash {
from {
opacity: 0;
transform: translateY(-30px) scale(0.95);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
#flash-messages-container {
margin-top: 20px;
margin-bottom: 0;
}
@media (max-width: 768px) {
.flash-message {
padding: 14px 16px !important;
font-size: 0.9rem;
}
.flash-message i {
font-size: 1.2rem !important;
}
}
/* Styles pour l'icône de comparaison */
.comparison-icon {
position: relative;
display: inline-block;
color: #333;
text-decoration: none;
transition: color 0.3s ease;
}
.comparison-icon:hover {
color: #ffa200;
}
.comparison-badge {
position: absolute;
top: 17px;
left: 12px;
background: #ffa200;
color: white;
border-radius: 50%;
width: 18px;
height: 18px;
font-size: 10px;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
animation: pulse 2s infinite;
}
.comparison-icon:hover .comparison-badge {
animation: none;
}
/* Styles pour les mega-menus - style comme la barre de recherche */
.mega-menu {
width: 100%;
max-width: 1200px;
left: 50%;
transform: translateX(-50%);
padding: 25px;
border-radius: 12px;
box-shadow: 0 8px 30px rgba(0,0,0,0.12);
border: none;
background: white;
display: none;
position: absolute;
top: 100%;
z-index: 9999 !important;
margin-top: 10px;
opacity: 0;
visibility: hidden;
transition: opacity 0.3s ease, visibility 0.3s ease, transform 0.3s ease;
}
.mega-menu.active {
display: block;
opacity: 1;
visibility: visible;
transform: translateX(-50%) translateY(0);
}
.nav-item.dropdown {
position: relative !important;
}
@media (min-width: 768px) {
.nav-item.dropdown {
position: relative !important;
}
.mega-menu {
position: absolute !important;
left: 50% !important;
transform: translateX(-50%) !important;
width: auto !important;
min-width: 600px !important;
}
}
/* Correction supplémentaire pour l'affichage sur la page d'accueil */
body.home .nav-item.dropdown,
.nav-item.dropdown {
position: relative !important;
}
body.home .mega-menu,
.mega-menu {
position: absolute !important;
left: 50% !important;
transform: translateX(-50%) translateY(0) !important;
width: auto !important;
min-width: 600px !important;
max-width: 90% !important;
top: 100% !important;
margin-top: 10px !important;
}
/* Assurer que les mega-menus sont toujours visibles au survol */
.nav-item.dropdown:hover .mega-menu {
opacity: 1 !important;
visibility: visible !important;
display: block !important;
transform: translateX(-50%) translateY(0) !important;
}
.mega-menu .dropdown-item {
padding: 0;
border: none;
}
.mega-menu .dropdown-header {
font-weight: 700;
color: #2c3e50;
margin-bottom: 18px;
padding-bottom: 10px;
border-bottom: 3px solid #3498db;
font-size: 16px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.mega-menu .dropdown-item a {
display: block;
padding: 10px 15px;
color: #555;
text-decoration: none;
border-radius: 6px;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
overflow: hidden;
}
.mega-menu .dropdown-item a::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(52, 152, 219, 0.1), transparent);
transition: left 0.5s;
}
.mega-menu .dropdown-item a:hover::before {
left: 100%;
}
.mega-menu .dropdown-item a:hover {
background: linear-gradient(135deg, #f8f9fa, #e3f2fd);
color: #2980b9;
transform: translateX(8px);
box-shadow: 0 2px 8px rgba(52, 152, 219, 0.2);
}
.mega-menu .dropdown-item a i {
width: 22px;
text-align: center;
margin-right: 8px;
color: #3498db;
transition: color 0.3s ease;
}
.mega-menu .dropdown-item a:hover i {
color: #2980b9;
}
/* Animation d'apparition améliorée */
@keyframes slideInDown {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.mega-menu {
animation: slideInDown 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Effet de survol sur le lien principal */
.nav-item.dropdown .nav-link {
position: relative;
transition: all 0.3s ease;
}
.nav-item.dropdown .nav-link::after {
content: '';
position: absolute;
bottom: -2px;
left: 50%;
width: 0;
height: 2px;
background: linear-gradient(90deg, #3498db, #2980b9);
transition: all 0.3s ease;
transform: translateX(-50%);
}
.nav-item.dropdown:hover .nav-link::after {
width: 100%;
}
.nav-item.dropdown:hover .nav-link {
color: #2980b9;
}
@keyframes fadeInDown {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Responsive */
@media (max-width: 768px) {
.mega-menu {
width: 100%;
left: 0;
padding: 15px;
}
.mega-menu .row {
margin: 0;
}
.mega-menu .col-md-3 {
margin-bottom: 20px;
}
}
</style>
{% block stylesheets %}
{{ encore_entry_link_tags('app') }}
{% endblock %}
<!-- Script pour forcer l'application des styles CSS après chargement -->
<script>
document.addEventListener('DOMContentLoaded', function() {
// Forcer le masquage du toggle sur grands écrans
if (window.innerWidth >= 992) {
const togglers = document.querySelectorAll('.navbar-toggler, .header_area .navbar .navbar-toggler');
togglers.forEach(function(toggler) {
if (toggler) {
toggler.style.display = 'none';
toggler.style.visibility = 'hidden';
toggler.style.opacity = '0';
toggler.style.width = '0';
toggler.style.height = '0';
toggler.style.padding = '0';
toggler.style.margin = '0';
toggler.style.border = 'none';
toggler.style.position = 'absolute';
toggler.style.left = '-9999px';
}
});
const iconBars = document.querySelectorAll('.navbar-toggler .icon-bar, .header_area .navbar .navbar-toggler .icon-bar, .navbar-toggler-icon');
iconBars.forEach(function(bar) {
if (bar) {
bar.style.display = 'none';
bar.style.visibility = 'hidden';
}
});
}
// Alignement des icônes navbar sur mobile
const navbarRight = document.querySelectorAll('.navbar-right, .header_area .navbar .nav.navbar-nav.navbar-right');
navbarRight.forEach(function(nav) {
if (nav && window.innerWidth <= 991.98) {
// Mobile: colonne avec icônes alignées horizontalement
nav.style.display = 'flex';
nav.style.flexDirection = 'column';
nav.style.alignItems = 'center';
nav.style.textAlign = 'center';
// Le container d'icônes reste horizontal
const iconsContainer = nav.querySelector('.navbar-icons-wrapper');
if (iconsContainer) {
iconsContainer.style.display = 'flex';
iconsContainer.style.flexDirection = 'row';
iconsContainer.style.justifyContent = 'center';
}
// Le bouton compte en bas
const accountBtn = nav.querySelector('li:last-child');
if (accountBtn) {
accountBtn.style.width = '100%';
accountBtn.style.display = 'flex';
accountBtn.style.justifyContent = 'center';
accountBtn.style.marginTop = '12px';
accountBtn.style.paddingTop = '12px';
accountBtn.style.borderTop = '1px solid #e0e0e0';
}
} else if (nav && window.innerWidth > 991.98) {
// Desktop: alignement horizontal normal
nav.style.display = 'flex';
nav.style.flexDirection = 'row';
nav.style.alignItems = 'center';
nav.style.justifyContent = 'flex-end';
}
});
});
// Réappliquer lors du redimensionnement
window.addEventListener('resize', function() {
if (window.innerWidth >= 992) {
const togglers = document.querySelectorAll('.navbar-toggler, .header_area .navbar .navbar-toggler');
togglers.forEach(function(toggler) {
if (toggler) {
toggler.style.display = 'none';
toggler.style.visibility = 'hidden';
}
});
}
// Réappliquer l'alignement des icônes navbar
const navbarRight = document.querySelectorAll('.navbar-right, .header_area .navbar .nav.navbar-nav.navbar-right');
navbarRight.forEach(function(nav) {
if (nav && window.innerWidth <= 991.98) {
// Mobile: colonne avec icônes alignées horizontalement
nav.style.display = 'flex';
nav.style.flexDirection = 'column';
nav.style.alignItems = 'center';
nav.style.textAlign = 'center';
// Le container d'icônes reste horizontal
const iconsContainer = nav.querySelector('.navbar-icons-wrapper');
if (iconsContainer) {
iconsContainer.style.display = 'flex';
iconsContainer.style.flexDirection = 'row';
iconsContainer.style.justifyContent = 'center';
}
const accountBtn = nav.querySelector('li:last-child');
if (accountBtn) {
accountBtn.style.width = '100%';
accountBtn.style.display = 'flex';
accountBtn.style.justifyContent = 'center';
accountBtn.style.marginTop = '12px';
accountBtn.style.paddingTop = '12px';
accountBtn.style.borderTop = '1px solid #e0e0e0';
}
} else if (nav && window.innerWidth > 991.98) {
// Desktop: alignement horizontal normal
nav.style.display = 'flex';
nav.style.flexDirection = 'row';
nav.style.alignItems = 'center';
nav.style.justifyContent = 'flex-end';
}
});
});
</script>
{% set current_route = app.request.attributes.get('_route') %}
{% set is_account_route = current_route starts with 'ui_account_' or current_route == 'notifications_list' %}
<style>
/* Shared dark-mode fixes for the public account area. */
@media (prefers-color-scheme: dark) {
body.account-theme-scope {
background-color: #111827;
color: #e5e7eb;
}
body.account-theme-scope .card,
body.account-theme-scope .notification-item,
body.account-theme-scope .list-group-item,
body.account-theme-scope .modal-content,
body.account-theme-scope .dropdown-menu,
body.account-theme-scope .form-control,
body.account-theme-scope .form-select,
body.account-theme-scope .input-group-text,
body.account-theme-scope .accordion-item,
body.account-theme-scope .table,
body.account-theme-scope .table td,
body.account-theme-scope .table th {
background-color: #1f2937 !important;
border-color: #374151 !important;
color: #e5e7eb !important;
}
body.account-theme-scope .card-header,
body.account-theme-scope .card-header.bg-white,
body.account-theme-scope .bg-white,
body.account-theme-scope .account-menu-list .menu-main {
background-color: #182131 !important;
border-color: #374151 !important;
}
body.account-theme-scope .text-muted,
body.account-theme-scope .form-text,
body.account-theme-scope .form-label,
body.account-theme-scope small,
body.account-theme-scope .small,
body.account-theme-scope .btn-outline-secondary,
body.account-theme-scope .btn-outline-secondary i {
color: #aeb8c7 !important;
}
body.account-theme-scope h1,
body.account-theme-scope h2,
body.account-theme-scope h3,
body.account-theme-scope h4,
body.account-theme-scope h5,
body.account-theme-scope h6,
body.account-theme-scope .list-group-item,
body.account-theme-scope .card-title,
body.account-theme-scope .card-text,
body.account-theme-scope .notification-title,
body.account-theme-scope .notification-message,
body.account-theme-scope .notification-meta,
body.account-theme-scope .table,
body.account-theme-scope .table td,
body.account-theme-scope .table th,
body.account-theme-scope .table strong,
body.account-theme-scope .table a:not(.btn),
body.account-theme-scope .breadcrumb-banner,
body.account-theme-scope .breadcrumb-banner a,
body.account-theme-scope .breadcrumb-banner h1,
body.account-theme-scope .empty-state-title,
body.account-theme-scope .empty-state-text {
color: #e5e7eb !important;
}
body.account-theme-scope .account-menu-list .list-group-item:hover:not(.menu-action-active):not(.menu-main) {
background-color: #243041 !important;
}
body.account-theme-scope .notification-item.unread {
background-color: #172554 !important;
border-left-color: #60a5fa !important;
}
body.account-theme-scope .notification-item.archived {
opacity: 0.85;
}
body.account-theme-scope .btn-outline-primary,
body.account-theme-scope .btn-outline-secondary,
body.account-theme-scope .btn-outline-warning,
body.account-theme-scope .btn-outline-danger {
background-color: transparent !important;
}
body.account-theme-scope .empty-state-icon {
color: #6b7280 !important;
}
body.account-theme-scope .profile-picture-container .profile-picture,
body.account-theme-scope .profile-picture-mobile,
body.account-theme-scope .profile-picture-edit-icon,
body.account-theme-scope .profile-picture-edit-icon-mobile {
border-color: #111827 !important;
}
}
html.dark-mode body.account-theme-scope,
body.dark-mode.account-theme-scope,
html[data-theme=\"dark\"] body.account-theme-scope,
body[data-theme=\"dark\"].account-theme-scope,
html[data-bs-theme=\"dark\"] body.account-theme-scope,
body[data-bs-theme=\"dark\"].account-theme-scope {
background-color: #111827;
color: #e5e7eb;
}
html.dark-mode body.account-theme-scope .card,
html.dark-mode body.account-theme-scope .notification-item,
html.dark-mode body.account-theme-scope .list-group-item,
html.dark-mode body.account-theme-scope .modal-content,
html.dark-mode body.account-theme-scope .dropdown-menu,
html.dark-mode body.account-theme-scope .form-control,
html.dark-mode body.account-theme-scope .form-select,
html.dark-mode body.account-theme-scope .input-group-text,
html.dark-mode body.account-theme-scope .accordion-item,
html.dark-mode body.account-theme-scope .table,
html.dark-mode body.account-theme-scope .table td,
html.dark-mode body.account-theme-scope .table th,
body.dark-mode.account-theme-scope .card,
body.dark-mode.account-theme-scope .notification-item,
body.dark-mode.account-theme-scope .list-group-item,
body.dark-mode.account-theme-scope .modal-content,
body.dark-mode.account-theme-scope .dropdown-menu,
body.dark-mode.account-theme-scope .form-control,
body.dark-mode.account-theme-scope .form-select,
body.dark-mode.account-theme-scope .input-group-text,
body.dark-mode.account-theme-scope .accordion-item,
body.dark-mode.account-theme-scope .table,
body.dark-mode.account-theme-scope .table td,
body.dark-mode.account-theme-scope .table th,
html[data-theme=\"dark\"] body.account-theme-scope .card,
html[data-theme=\"dark\"] body.account-theme-scope .notification-item,
html[data-theme=\"dark\"] body.account-theme-scope .list-group-item,
html[data-theme=\"dark\"] body.account-theme-scope .modal-content,
html[data-theme=\"dark\"] body.account-theme-scope .dropdown-menu,
html[data-theme=\"dark\"] body.account-theme-scope .form-control,
html[data-theme=\"dark\"] body.account-theme-scope .form-select,
html[data-theme=\"dark\"] body.account-theme-scope .input-group-text,
html[data-theme=\"dark\"] body.account-theme-scope .accordion-item,
html[data-theme=\"dark\"] body.account-theme-scope .table,
html[data-theme=\"dark\"] body.account-theme-scope .table td,
html[data-theme=\"dark\"] body.account-theme-scope .table th,
body[data-theme=\"dark\"].account-theme-scope .card,
body[data-theme=\"dark\"].account-theme-scope .notification-item,
body[data-theme=\"dark\"].account-theme-scope .list-group-item,
body[data-theme=\"dark\"].account-theme-scope .modal-content,
body[data-theme=\"dark\"].account-theme-scope .dropdown-menu,
body[data-theme=\"dark\"].account-theme-scope .form-control,
body[data-theme=\"dark\"].account-theme-scope .form-select,
body[data-theme=\"dark\"].account-theme-scope .input-group-text,
body[data-theme=\"dark\"].account-theme-scope .accordion-item,
body[data-theme=\"dark\"].account-theme-scope .table,
body[data-theme=\"dark\"].account-theme-scope .table td,
body[data-theme=\"dark\"].account-theme-scope .table th,
html[data-bs-theme=\"dark\"] body.account-theme-scope .card,
html[data-bs-theme=\"dark\"] body.account-theme-scope .notification-item,
html[data-bs-theme=\"dark\"] body.account-theme-scope .list-group-item,
html[data-bs-theme=\"dark\"] body.account-theme-scope .modal-content,
html[data-bs-theme=\"dark\"] body.account-theme-scope .dropdown-menu,
html[data-bs-theme=\"dark\"] body.account-theme-scope .form-control,
html[data-bs-theme=\"dark\"] body.account-theme-scope .form-select,
html[data-bs-theme=\"dark\"] body.account-theme-scope .input-group-text,
html[data-bs-theme=\"dark\"] body.account-theme-scope .accordion-item,
html[data-bs-theme=\"dark\"] body.account-theme-scope .table,
html[data-bs-theme=\"dark\"] body.account-theme-scope .table td,
html[data-bs-theme=\"dark\"] body.account-theme-scope .table th,
body[data-bs-theme=\"dark\"].account-theme-scope .card,
body[data-bs-theme=\"dark\"].account-theme-scope .notification-item,
body[data-bs-theme=\"dark\"].account-theme-scope .list-group-item,
body[data-bs-theme=\"dark\"].account-theme-scope .modal-content,
body[data-bs-theme=\"dark\"].account-theme-scope .dropdown-menu,
body[data-bs-theme=\"dark\"].account-theme-scope .form-control,
body[data-bs-theme=\"dark\"].account-theme-scope .form-select,
body[data-bs-theme=\"dark\"].account-theme-scope .input-group-text,
body[data-bs-theme=\"dark\"].account-theme-scope .accordion-item,
body[data-bs-theme=\"dark\"].account-theme-scope .table,
body[data-bs-theme=\"dark\"].account-theme-scope .table td,
body[data-bs-theme=\"dark\"].account-theme-scope .table th {
background-color: #1f2937 !important;
border-color: #374151 !important;
color: #e5e7eb !important;
}
html.dark-mode body.account-theme-scope .card-header,
html.dark-mode body.account-theme-scope .card-header.bg-white,
html.dark-mode body.account-theme-scope .bg-white,
html.dark-mode body.account-theme-scope .account-menu-list .menu-main,
body.dark-mode.account-theme-scope .card-header,
body.dark-mode.account-theme-scope .card-header.bg-white,
body.dark-mode.account-theme-scope .bg-white,
body.dark-mode.account-theme-scope .account-menu-list .menu-main,
html[data-theme=\"dark\"] body.account-theme-scope .card-header,
html[data-theme=\"dark\"] body.account-theme-scope .card-header.bg-white,
html[data-theme=\"dark\"] body.account-theme-scope .bg-white,
html[data-theme=\"dark\"] body.account-theme-scope .account-menu-list .menu-main,
body[data-theme=\"dark\"].account-theme-scope .card-header,
body[data-theme=\"dark\"].account-theme-scope .card-header.bg-white,
body[data-theme=\"dark\"].account-theme-scope .bg-white,
body[data-theme=\"dark\"].account-theme-scope .account-menu-list .menu-main,
html[data-bs-theme=\"dark\"] body.account-theme-scope .card-header,
html[data-bs-theme=\"dark\"] body.account-theme-scope .card-header.bg-white,
html[data-bs-theme=\"dark\"] body.account-theme-scope .bg-white,
html[data-bs-theme=\"dark\"] body.account-theme-scope .account-menu-list .menu-main,
body[data-bs-theme=\"dark\"].account-theme-scope .card-header,
body[data-bs-theme=\"dark\"].account-theme-scope .card-header.bg-white,
body[data-bs-theme=\"dark\"].account-theme-scope .bg-white,
body[data-bs-theme=\"dark\"].account-theme-scope .account-menu-list .menu-main {
background-color: #182131 !important;
border-color: #374151 !important;
}
html.dark-mode body.account-theme-scope .text-muted,
html.dark-mode body.account-theme-scope .form-text,
html.dark-mode body.account-theme-scope .form-label,
html.dark-mode body.account-theme-scope small,
html.dark-mode body.account-theme-scope .small,
html.dark-mode body.account-theme-scope .btn-outline-secondary,
html.dark-mode body.account-theme-scope .btn-outline-secondary i,
body.dark-mode.account-theme-scope .text-muted,
body.dark-mode.account-theme-scope .form-text,
body.dark-mode.account-theme-scope .form-label,
body.dark-mode.account-theme-scope small,
body.dark-mode.account-theme-scope .small,
body.dark-mode.account-theme-scope .btn-outline-secondary,
body.dark-mode.account-theme-scope .btn-outline-secondary i,
html[data-theme=\"dark\"] body.account-theme-scope .text-muted,
html[data-theme=\"dark\"] body.account-theme-scope .form-text,
html[data-theme=\"dark\"] body.account-theme-scope .form-label,
html[data-theme=\"dark\"] body.account-theme-scope small,
html[data-theme=\"dark\"] body.account-theme-scope .small,
html[data-theme=\"dark\"] body.account-theme-scope .btn-outline-secondary,
html[data-theme=\"dark\"] body.account-theme-scope .btn-outline-secondary i,
body[data-theme=\"dark\"].account-theme-scope .text-muted,
body[data-theme=\"dark\"].account-theme-scope .form-text,
body[data-theme=\"dark\"].account-theme-scope .form-label,
body[data-theme=\"dark\"].account-theme-scope small,
body[data-theme=\"dark\"].account-theme-scope .small,
body[data-theme=\"dark\"].account-theme-scope .btn-outline-secondary,
body[data-theme=\"dark\"].account-theme-scope .btn-outline-secondary i,
html[data-bs-theme=\"dark\"] body.account-theme-scope .text-muted,
html[data-bs-theme=\"dark\"] body.account-theme-scope .form-text,
html[data-bs-theme=\"dark\"] body.account-theme-scope .form-label,
html[data-bs-theme=\"dark\"] body.account-theme-scope small,
html[data-bs-theme=\"dark\"] body.account-theme-scope .small,
html[data-bs-theme=\"dark\"] body.account-theme-scope .btn-outline-secondary,
html[data-bs-theme=\"dark\"] body.account-theme-scope .btn-outline-secondary i,
body[data-bs-theme=\"dark\"].account-theme-scope .text-muted,
body[data-bs-theme=\"dark\"].account-theme-scope .form-text,
body[data-bs-theme=\"dark\"].account-theme-scope .form-label,
body[data-bs-theme=\"dark\"].account-theme-scope small,
body[data-bs-theme=\"dark\"].account-theme-scope .small,
body[data-bs-theme=\"dark\"].account-theme-scope .btn-outline-secondary,
body[data-bs-theme=\"dark\"].account-theme-scope .btn-outline-secondary i {
color: #aeb8c7 !important;
}
html.dark-mode body.account-theme-scope .empty-state-icon,
body.dark-mode.account-theme-scope .empty-state-icon,
html[data-theme=\"dark\"] body.account-theme-scope .empty-state-icon,
body[data-theme=\"dark\"].account-theme-scope .empty-state-icon,
html[data-bs-theme=\"dark\"] body.account-theme-scope .empty-state-icon,
body[data-bs-theme=\"dark\"].account-theme-scope .empty-state-icon {
color: #6b7280 !important;
}
</style>
</head>
<body {% if current_menu is defined and current_menu == \"listing\" %}id=\"category\"{% endif %} class=\"{% if is_account_route %}account-theme-scope{% endif %}\">
<!-- Start Header Area -->
<header class=\"header_area sticky-header\">
<div class=\"main_menu\">
<nav class=\"navbar navbar-expand-lg navbar-light main_box\">
<div class=\"container\">
<!-- Brand and toggle get grouped for better mobile display -->
<a class=\"navbar-brand logo_h\" href=\"{{ path('ui_home') }}\"><img style=\"width: auto;height: 60px\" src=\"{{ asset('logo.png') }}\" alt=\"\"></a>
<button class=\"navbar-toggler\" type=\"button\" data-bs-toggle=\"collapse\" data-bs-target=\"#navbarSupportedContent\"
aria-controls=\"navbarSupportedContent\" aria-expanded=\"false\" aria-label=\"Toggle navigation\">
<span class=\"icon-bar\"></span>
<span class=\"icon-bar\"></span>
<span class=\"icon-bar\"></span>
</button>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class=\"collapse navbar-collapse offset\" id=\"navbarSupportedContent\">
<ul class=\"nav navbar-nav menu_nav ml-auto\">
<li class=\"nav-item {% if current_menu is defined and current_menu == \"home\" %}active{% endif %}\">
<a class=\"nav-link\" href=\"{{ path('ui_home') }}\">Accueil</a>
</li>
<li class=\"nav-item {% if current_menu is defined and current_menu == \"shops\" %}active{% endif %}\">
<a class=\"nav-link\" href=\"{{ path('ui_shops_list') }}\">Boutiques</a>
</li>
<li class=\"nav-item {% if current_menu is defined and current_menu == \"listing\" %}active{% endif %}\">
<a class=\"nav-link\" href=\"{{ path('ui_listing') }}\">Produits</a>
</li>
<li class=\"nav-item {% if current_menu is defined and current_menu == \"blog\" %}active{% endif %}\">
<a class=\"nav-link\" href=\"{{ path('ui_blog') }}\">Blog</a>
</li>
<li class=\"nav-item {% if current_menu is defined and current_menu == \"contact\" %}active{% endif %}\">
<a class=\"nav-link\" href=\"{{ path('ui_contact') }}\">Contact</a>
</li>
</ul>
<ul class=\"nav navbar-nav navbar-right\">
<li class=\"nav-item header-icons-item\">
<div class=\"navbar-icons-wrapper\">
<a href=\"{{ path('ui_cart') }}\" class=\"cart {% if current_menu is defined and current_menu == \"cart\" %}active{% endif %}\" aria-label=\"Panier\">
<span class=\"ti-bag\"></span>
</a>
<a href=\"{{ path('ui_product_comparison') }}\" class=\"comparison-icon {% if current_menu is defined and current_menu == \"comparison\" %}active{% endif %}\" title=\"Comparaison premium\" aria-label=\"Comparaison premium\">
<span class=\"lnr lnr-sync\"></span>
<span class=\"comparison-badge\" id=\"comparisonBadge\" data-comparison-badge style=\"display: none;\">0</span>
</a>
{% if app.user %}
<a href=\"{{ path('notifications_list') }}\" class=\"notification-icon\" title=\"Notifications\" aria-label=\"Notifications\">
<span class=\"ti-bell\"></span>
<span class=\"notification-badge text-white\" id=\"notificationBadge\" style=\"display: none;color: white;\">0</span>
</a>
{% endif %}
<button class=\"theme-toggle-btn\" type=\"button\" data-theme-toggle aria-label=\"Passer au mode sombre\" title=\"Passer au mode sombre\">
<span class=\"ti-moon\" data-theme-icon></span>
</button>
<button class=\"search\" type=\"button\" aria-label=\"Recherche\">
<span class=\"lnr lnr-magnifier\" id=\"search\"></span>
</button>
</div>
</li>
<li class=\"nav-item header-account-item\">
{% if app.user %}
<a class=\"btn btn-primary btn-account header-account-link text-white\" href=\"{{ path('ui_account_index') }}\">
<i class=\"ti-user\"></i> Mon compte
</a>
{% else %}
<a class=\"btn btn-primary btn-account header-account-link text-white\" href=\"{{ path('ui_app_login') }}\">
<i class=\"ti-lock\"></i>Se connecter
</a>
{% endif %}
</li>
</ul>
</div>
</div>
</nav>
</div>
<div class=\"search_input\" id=\"search_input_box\">
<div class=\"container\">
<form class=\"d-flex justify-content-between\">
<input type=\"text\" class=\"form-control\" id=\"search_input\" placeholder=\"Search Here\">
<button type=\"submit\" class=\"btn\"></button>
<span class=\"lnr lnr-cross\" id=\"close_search\" title=\"Close Search\"></span>
</form>
</div>
</div>
</header>
<!-- End Header Area -->
<!-- Flash Messages -->
<div class=\"container mt-3\" id=\"flash-messages-container\" style=\"position: relative; z-index: 1050;\">
<div class=\"row\">
<div class=\"col-12\">
{% for message in app.flashes('success') %}
<div class=\"alert alert-success alert-dismissible fade show flash-message\" role=\"alert\">
<i class=\"fa fa-check-circle\"></i>
<strong>{{ message }}</strong>
<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
</div>
{% endfor %}
{% for message in app.flashes('error') %}
<div class=\"alert alert-danger alert-dismissible fade show flash-message\" role=\"alert\">
<i class=\"fa fa-exclamation-circle\"></i>
<strong>{{ message }}</strong>
<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
</div>
{% endfor %}
{% for message in app.flashes('warning') %}
<div class=\"alert alert-warning alert-dismissible fade show flash-message\" role=\"alert\">
<i class=\"fa fa-exclamation-triangle\"></i>
<strong>{{ message }}</strong>
<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
</div>
{% endfor %}
{% for message in app.flashes('info') %}
<div class=\"alert alert-info alert-dismissible fade show flash-message\" role=\"alert\">
<i class=\"fa fa-info-circle\"></i>
<strong>{{ message }}</strong>
<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
</div>
{% endfor %}
</div>
</div>
</div>
<div id=\"comparisonTray\" class=\"comparison-tray\" aria-live=\"polite\">
<div class=\"comparison-tray__header\">
<div>
<p class=\"comparison-tray__title\">Comparaison premium</p>
<p class=\"comparison-tray__meta\" id=\"comparisonTrayMeta\">Aucun produit en comparaison</p>
</div>
<a href=\"{{ path('ui_product_comparison') }}\" class=\"comparison-tray__go\">Ouvrir</a>
</div>
<div class=\"comparison-tray__items\" id=\"comparisonTrayItems\"></div>
<p class=\"comparison-tray__empty\" id=\"comparisonTrayEmpty\">Ajoute des produits d'une meme categorie pour obtenir une comparaison ultra pertinente.</p>
<div class=\"comparison-tray__actions\">
<a href=\"{{ path('ui_product_comparison') }}\" class=\"comparison-tray__go\">Comparer maintenant</a>
<button type=\"button\" class=\"comparison-tray__clear\" id=\"comparisonTrayClear\">Vider</button>
</div>
</div>
{% block body %}{% endblock %}
<!-- start footer Area -->
<footer class=\"footer-area section_gap\">
<div class=\"footer-pattern\"></div>
<div class=\"container\">
<div class=\"row\">
<div class=\"col-lg-3 col-md-6 col-sm-6 mb-4 mb-lg-0\">
<div class=\"single-footer-widget\">
<div class=\"footer-logo mb-3\">
<h4 class=\"footer-brand\">MaketOu</h4>
</div>
<p class=\"footer-description\">
MaketOu est la première marketplace haïtienne qui connecte les acheteurs et les vendeurs.
Nous offrons une plateforme sécurisée et moderne pour le commerce en ligne en Haïti.
</p>
<div class=\"footer-social mt-3\">
<h6 class=\"mb-2\">Suivez-nous</h6>
<div class=\"footer-social-icons\">
<a href=\"#\" class=\"social-icon\" aria-label=\"Facebook\" title=\"Facebook\">
<i class=\"fa fa-facebook\"></i>
</a>
<a href=\"#\" class=\"social-icon\" aria-label=\"Twitter\" title=\"Twitter\">
<i class=\"fa fa-twitter\"></i>
</a>
<a href=\"#\" class=\"social-icon\" aria-label=\"Instagram\" title=\"Instagram\">
<i class=\"fa fa-instagram\"></i>
</a>
<a href=\"#\" class=\"social-icon\" aria-label=\"LinkedIn\" title=\"LinkedIn\">
<i class=\"fa fa-linkedin\"></i>
</a>
</div>
</div>
</div>
</div>
<div class=\"col-lg-2 col-md-6 col-sm-6 mb-4 mb-lg-0\">
<div class=\"single-footer-widget\">
<h6 class=\"footer-widget-title\">Liens rapides</h6>
<ul class=\"footer-list\">
<li><a href=\"{{ path('ui_home') }}\"><i class=\"fa fa-angle-right me-2\"></i>Accueil</a></li>
<li><a href=\"{{ path('ui_listing') }}\"><i class=\"fa fa-angle-right me-2\"></i>Produits</a></li>
<li><a href=\"{{ path('ui_shops_list') }}\"><i class=\"fa fa-angle-right me-2\"></i>Boutiques</a></li>
{% if app.user %}
<li><a href=\"{{ path('ui_account_index') }}\"><i class=\"fa fa-angle-right me-2\"></i>Mon compte</a></li>
{% else %}
<li><a href=\"{{ path('ui_app_login') }}\"><i class=\"fa fa-angle-right me-2\"></i>Se connecter</a></li>
<li><a href=\"{{ path('ui_app_register') }}\"><i class=\"fa fa-angle-right me-2\"></i>S'inscrire</a></li>
{% endif %}
</ul>
</div>
</div>
<div class=\"col-lg-2 col-md-6 col-sm-6 mb-4 mb-lg-0\">
<div class=\"single-footer-widget\">
<h6 class=\"footer-widget-title\">Pour les vendeurs</h6>
<ul class=\"footer-list\">
<li><a href=\"{{ path('seller_index') }}\"><i class=\"fa fa-angle-right me-2\"></i>Ouvrir une boutique</a></li>
<li><a href=\"{{ path('seller_help_how_to_sell') }}\"><i class=\"fa fa-angle-right me-2\"></i>Comment vendre</a></li>
<li><a href=\"{{ path('seller_help_pricing') }}\"><i class=\"fa fa-angle-right me-2\"></i>Tarifs</a></li>
<li><a href=\"{{ path('seller_help_support') }}\"><i class=\"fa fa-angle-right me-2\"></i>Support vendeur</a></li>
</ul>
</div>
</div>
<div class=\"col-lg-2 col-md-6 col-sm-6 mb-4 mb-lg-0\">
<div class=\"single-footer-widget\">
<h6 class=\"footer-widget-title\">Support</h6>
<ul class=\"footer-list\">
<li><a href=\"{{ path('ui_help') }}\"><i class=\"fa fa-angle-right me-2\"></i> Centre d'Aide</a></li>
<li><a href=\"{{ path('ui_contact') }}\"><i class=\"fa fa-angle-right me-2\"></i> Contactez-nous</a></li>
<li><a href=\"{{ path('ui_faq') }}\"><i class=\"fa fa-angle-right me-2\"></i> FAQ</a></li>
<li><a href=\"{{ path('ui_privacy') }}\"><i class=\"fa fa-angle-right me-2\"></i> Politique de Confidentialité</a></li>
<li><a href=\"{{ path('ui_terms') }}\"><i class=\"fa fa-angle-right me-2\"></i> Conditions d'Utilisation</a></li>
</ul>
</div>
</div>
<div class=\"col-lg-3 col-md-6 col-sm-6\">
<div class=\"single-footer-widget\">
<h6 class=\"footer-widget-title\">Newsletter</h6>
<p class=\"footer-newsletter-text\">Restez informé des dernières nouveautés</p>
<div class=\"footer-newsletter-wrapper\" id=\"mc_embed_signup\">
<form action=\"{{ path('ui_newsletter_subscribe') }}\" method=\"post\" class=\"footer-newsletter-form\">
<div class=\"newsletter-input-group\">
<i class=\"fa fa-envelope newsletter-icon\"></i>
<input class=\"form-control newsletter-input\" name=\"email\" placeholder=\"Votre email\" required type=\"email\">
<button type=\"submit\" class=\"newsletter-btn\" aria-label=\"S'abonner\">
<span class=\"newsletter-btn-icon\">
<i class=\"fa fa-paper-plane\" aria-hidden=\"true\"></i>
</span>
<span class=\"newsletter-btn-loader\" style=\"display: none;\">
<i class=\"fa fa-spinner fa-spin\" aria-hidden=\"true\"></i>
</span>
</button>
</div>
</form>
</div>
<div class=\"footer-trust-badges mt-3\">
<div class=\"trust-item\">
<i class=\"fa fa-shield\"></i>
<span>Paiement sécurisé</span>
</div>
<div class=\"trust-item\">
<i class=\"fa fa-truck\"></i>
<span>Livraison rapide</span>
</div>
</div>
</div>
</div>
</div>
<div class=\"footer-divider\"></div>
<div class=\"footer-bottom d-flex justify-content-center align-items-center flex-wrap\">
<p class=\"footer-text m-0\">
Copyright ©<script>document.write(new Date().getFullYear());</script>
Tous droits réservés | Ce site a été fait avec <i class=\"fa fa-heart-o\" aria-hidden=\"true\" style=\"color: #dc3545;\"></i> par <a
href=\"https://tech.foulgor.com\" target=\"_blank\" style=\"color: #ffa200;\">Foulgor Tech</a>
</p>
</div>
</div>
</footer>
<style>
/* ============================================
FOOTER MODERNE - Design amélioré
============================================ */
.footer-area {
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
position: relative;
overflow: hidden;
padding: 50px 0 20px;
}
.footer-pattern {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image:
radial-gradient(circle at 20% 50%, rgba(255, 162, 0, 0.1) 0%, transparent 50%),
radial-gradient(circle at 80% 80%, rgba(255, 162, 0, 0.08) 0%, transparent 50%);
pointer-events: none;
}
.footer-area .container {
position: relative;
z-index: 1;
}
/* Widgets */
.single-footer-widget {
color: rgba(255, 255, 255, 0.9);
}
.footer-brand {
font-size: 1.6rem;
font-weight: 700;
background: linear-gradient(135deg, #ffa200 0%, #e8910a 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 12px;
display: inline-block;
}
.footer-widget-title {
color: #fff;
font-size: 1rem;
font-weight: 600;
margin-bottom: 18px;
position: relative;
padding-bottom: 8px;
}
.footer-widget-title::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 40px;
height: 3px;
background: linear-gradient(135deg, #ffa200 0%, #e8910a 100%);
border-radius: 2px;
}
.footer-description {
color: rgba(255, 255, 255, 0.7);
line-height: 1.6;
font-size: 0.9rem;
margin-bottom: 0;
}
/* Liste de liens */
.footer-list {
list-style: none;
padding: 0;
margin: 0;
}
.footer-list li {
margin-bottom: 10px;
}
.footer-list li a {
color: rgba(255, 255, 255, 0.7);
text-decoration: none;
transition: all 0.3s ease;
font-size: 0.9rem;
display: inline-flex;
align-items: center;
}
.footer-list li a i {
font-size: 0.8rem;
opacity: 0.6;
transition: all 0.3s ease;
}
.footer-list li a:hover {
color: #ffa200;
transform: translateX(5px);
}
.footer-list li a:hover i {
opacity: 1;
color: #ffa200;
}
/* Newsletter */
.footer-newsletter-text {
color: rgba(255, 255, 255, 0.7);
font-size: 0.85rem;
margin-bottom: 15px;
line-height: 1.5;
}
.footer-newsletter-wrapper {
margin-bottom: 15px;
}
.newsletter-input-group {
display: flex;
align-items: center;
background: rgba(255, 255, 255, 0.08);
border-radius: 30px;
padding: 4px 4px 4px 15px;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.15);
transition: all 0.3s ease;
gap: 8px;
}
.newsletter-input-group:focus-within {
background: rgba(255, 255, 255, 0.12);
border-color: rgba(255, 162, 0, 0.6);
box-shadow: 0 0 0 2px rgba(255, 162, 0, 0.15);
}
.newsletter-icon {
color: rgba(255, 255, 255, 0.5);
font-size: 0.9rem;
flex-shrink: 0;
}
.newsletter-input-group:focus-within .newsletter-icon {
color: #ffa200;
}
.newsletter-input {
flex: 1;
background: transparent;
border: none;
color: #fff;
padding: 10px 8px;
font-size: 0.9rem;
min-width: 0;
}
.newsletter-input::placeholder {
color: rgba(255, 255, 255, 0.4);
font-size: 0.85rem;
}
.newsletter-input:focus {
outline: none;
box-shadow: none;
}
.newsletter-btn {
background: linear-gradient(135deg, #ffa200 0%, #e8910a 100%);
border: none;
color: white;
width: 42px;
height: 42px;
min-width: 42px;
min-height: 42px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
flex-shrink: 0;
box-shadow: 0 4px 15px rgba(255, 162, 0, 0.4),
0 0 0 0 rgba(255, 162, 0, 0.4);
font-size: 0.9rem;
position: relative;
overflow: hidden;
}
.newsletter-btn::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
border-radius: 50%;
background: rgba(255, 255, 255, 0.3);
transform: translate(-50%, -50%);
transition: width 0.6s ease, height 0.6s ease;
}
.newsletter-btn:hover::before {
width: 100%;
height: 100%;
}
.newsletter-btn:hover {
transform: translateX(3px) scale(1.05);
box-shadow: 0 6px 20px rgba(255, 162, 0, 0.5),
0 0 0 8px rgba(255, 162, 0, 0.1);
background: linear-gradient(135deg, #e8910a 0%, #ffa200 100%);
}
.newsletter-btn:active {
transform: translateX(3px) scale(0.98);
box-shadow: 0 3px 10px rgba(255, 162, 0, 0.4);
}
.newsletter-btn:focus {
outline: none;
box-shadow: 0 4px 15px rgba(255, 162, 0, 0.4),
0 0 0 3px rgba(255, 162, 0, 0.3);
}
.newsletter-btn-icon,
.newsletter-btn-loader {
position: relative;
z-index: 2;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
}
.newsletter-btn:hover .newsletter-btn-icon {
transform: translateX(2px) rotate(-10deg);
}
.newsletter-btn.loading .newsletter-btn-icon {
opacity: 0;
transform: scale(0);
}
.newsletter-btn.loading .newsletter-btn-loader {
display: flex !important;
}
.newsletter-btn.success {
background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
box-shadow: 0 4px 15px rgba(40, 167, 69, 0.4);
}
.newsletter-btn.success .newsletter-btn-icon i::before {
content: \"\\f00c\";
}
/* Trust badges */
.footer-trust-badges {
display: flex;
flex-direction: row;
gap: 15px;
flex-wrap: wrap;
}
.trust-item {
display: flex;
align-items: center;
gap: 6px;
color: rgba(255, 255, 255, 0.6);
font-size: 0.8rem;
}
.trust-item i {
color: #ffa200;
font-size: 0.9rem;
}
/* Social icons */
.footer-social {
margin-top: 0 !important;
position: relative !important;
width: 100% !important;
clear: both !important;
float: none !important;
}
.footer-social h6 {
color: #fff;
font-size: 0.95rem;
font-weight: 600;
margin-bottom: 12px !important;
display: block !important;
width: 100% !important;
position: relative !important;
clear: both !important;
float: none !important;
}
.footer-social-icons {
display: flex !important;
gap: 12px !important;
flex-wrap: wrap !important;
align-items: center !important;
justify-content: flex-start !important;
width: 100% !important;
position: relative !important;
clear: both !important;
float: none !important;
margin: 0 !important;
padding: 0 !important;
}
.social-icon {
width: 38px !important;
height: 38px !important;
min-width: 38px !important;
min-height: 38px !important;
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
background: rgba(255, 255, 255, 0.1) !important;
border-radius: 50% !important;
color: rgba(255, 255, 255, 0.8) !important;
text-decoration: none !important;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
font-size: 16px !important;
line-height: 1 !important;
backdrop-filter: blur(10px) !important;
border: 1px solid rgba(255, 255, 255, 0.1) !important;
flex-shrink: 0 !important;
position: relative !important;
float: none !important;
margin: 0 !important;
padding: 0 !important;
vertical-align: middle !important;
}
.social-icon i {
font-size: 16px !important;
line-height: 1 !important;
display: inline-block !important;
transition: transform 0.3s ease !important;
position: relative !important;
z-index: 1 !important;
margin: 0 !important;
padding: 0 !important;
}
.social-icon:hover {
background: linear-gradient(135deg, #ffa200 0%, #e8910a 100%) !important;
transform: translateY(-5px) scale(1.1) !important;
color: white !important;
border-color: transparent !important;
box-shadow: 0 8px 20px rgba(255, 162, 0, 0.4) !important;
}
.social-icon:hover i {
transform: scale(1.1) !important;
}
/* Footer divider */
.footer-divider {
height: 1px;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
margin: 30px 0 20px;
}
/* Footer bottom */
.footer-bottom {
padding-top: 15px;
}
.footer-text {
color: rgba(255, 255, 255, 0.6);
font-size: 0.9rem;
margin: 0;
text-align: center;
}
/* Responsive */
@media(max-width: 991.98px) {
.footer-area {
padding: 40px 0 20px;
}
.single-footer-widget {
margin-bottom: 30px;
}
.footer-social {
margin-top: 15px;
}
}
@media(max-width: 767.98px) {
.footer-area {
padding: 35px 0 18px;
}
.footer-brand {
font-size: 1.4rem;
}
.footer-widget-title {
font-size: 0.95rem;
}
.newsletter-input-group {
padding: 3px 3px 3px 12px;
}
.newsletter-input {
padding: 8px 6px;
font-size: 0.85rem;
}
.newsletter-btn {
width: 38px;
height: 38px;
min-width: 38px;
min-height: 38px;
font-size: 0.85rem;
}
.footer-trust-badges {
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
gap: 12px;
}
}
@media(max-width: 575.98px) {
.footer-area {
padding: 40px 0 20px;
}
.footer-brand {
font-size: 1.3rem;
}
.social-icon {
width: 38px;
height: 38px;
font-size: 16px;
}
.social-icon i {
font-size: 16px;
}
}
</style>
<script>
// Debounced autocomplete for header search
(function(){
const input = document.getElementById('search_input');
const box = document.getElementById('search_suggestions');
if (!input || !box) return;
let t = null;
input.addEventListener('input', function(){
const q = input.value.trim();
clearTimeout(t);
if (q.length === 0) { box.style.display = 'none'; box.innerHTML=''; return; }
t = setTimeout(() => fetchSuggestions(q), 200);
});
function fetchSuggestions(q){
const url = '{{ path('ui_api_search_suggest') }}' + '?q=' + encodeURIComponent(q);
fetch(url).then(r => r.json()).then(data => {
if (!data.success) { box.style.display='none'; return; }
renderSuggestions(data.results || []);
}).catch(() => { box.style.display='none'; });
}
function renderSuggestions(items){
if (!items.length) { box.style.display='none'; box.innerHTML=''; return; }
box.innerHTML = items.map(it => suggestionItem(it)).join('');
box.style.display = 'block';
}
function suggestionItem(it){
const icon = it.type === 'product' ? 'ti-package' : (it.type === 'shop' ? 'ti-briefcase' : (it.type === 'category' ? 'ti-layers' : 'ti-tag'));
return '<a href=\"' + it.url + '\" class=\"list-group-item list-group-item-action d-flex align-items-center\">'
+ '<i class=\"' + icon + ' me-4\"></i>'
+ '<span class=\"ml-2\">' + escapeHtml(it.label) + '</span>'
+ '<span class=\"badge bg-light text-dark ms-auto\">' + it.type + '</span>'
+ '</a>';
}
function escapeHtml(s){
return s.replace(/[&<>\"]+/g, c => ({'&':'&','<':'<','>':'>','\"':'"'}[c]));
}
document.addEventListener('click', function(e){
if (!box.contains(e.target) && e.target !== input) {
box.style.display='none';
}
});
window.handleSearchSubmit = function(e){
if (e) e.preventDefault();
const first = box.querySelector('a');
if (first) { window.location.href = first.getAttribute('href'); return false; }
// fallback to listing page search by name
const q = input.value.trim();
if (q.length) {
window.location.href = '{{ path('ui_listing') }}' + '?q=' + encodeURIComponent(q);
}
return false;
}
})();
// Gestion des mega-menus avec clic (comme la barre de recherche)
document.addEventListener('DOMContentLoaded', function() {
const dropdownItems = document.querySelectorAll('.nav-item.dropdown');
dropdownItems.forEach(function(item) {
const dropdownToggle = item.querySelector('.dropdown-toggle');
const dropdownMenu = item.querySelector('.mega-menu');
if (!dropdownToggle || !dropdownMenu) return;
// Fermer les autres menus quand on ouvre un nouveau
function closeAllMenus() {
dropdownItems.forEach(function(otherItem) {
const otherMenu = otherItem.querySelector('.mega-menu');
if (otherMenu && otherMenu !== dropdownMenu) {
\$(otherMenu).slideUp(300);
otherMenu.classList.remove('active');
}
});
}
// Toggle au clic (comme la barre de recherche)
dropdownToggle.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
closeAllMenus();
if (dropdownMenu.classList.contains('active')) {
// Fermer le menu
dropdownMenu.style.opacity = '0';
dropdownMenu.style.visibility = 'hidden';
dropdownMenu.style.transform = 'translateX(-50%) translateY(-10px)';
setTimeout(() => {
dropdownMenu.classList.remove('active');
dropdownMenu.style.display = 'none';
}, 300);
} else {
// Ouvrir le menu
dropdownMenu.style.display = 'block';
setTimeout(() => {
dropdownMenu.classList.add('active');
dropdownMenu.style.opacity = '1';
dropdownMenu.style.visibility = 'visible';
dropdownMenu.style.transform = 'translateX(-50%) translateY(0)';
}, 10);
}
});
// Fermer au clic en dehors
document.addEventListener('click', function(e) {
if (!item.contains(e.target) && dropdownMenu.classList.contains('active')) {
dropdownMenu.style.opacity = '0';
dropdownMenu.style.visibility = 'hidden';
dropdownMenu.style.transform = 'translateX(-50%) translateY(-10px)';
setTimeout(() => {
dropdownMenu.classList.remove('active');
dropdownMenu.style.display = 'none';
}, 300);
}
});
// Animation des éléments du menu
const menuItems = dropdownMenu.querySelectorAll('.dropdown-item a');
menuItems.forEach(function(menuItem, index) {
menuItem.style.animationDelay = (index * 0.05) + 's';
});
});
// Gestion des clics sur mobile
if (window.innerWidth <= 768) {
dropdownItems.forEach(function(item) {
const dropdownToggle = item.querySelector('.dropdown-toggle');
const dropdownMenu = item.querySelector('.mega-menu');
dropdownToggle.addEventListener('click', function(e) {
e.preventDefault();
// Fermer tous les autres menus
dropdownItems.forEach(function(otherItem) {
if (otherItem !== item) {
const otherMenu = otherItem.querySelector('.mega-menu');
otherMenu.style.opacity = '0';
otherMenu.style.visibility = 'hidden';
otherMenu.style.transform = 'translateY(-10px)';
}
});
// Toggle le menu actuel
if (dropdownMenu.style.opacity === '1') {
dropdownMenu.style.opacity = '0';
dropdownMenu.style.visibility = 'hidden';
dropdownMenu.style.transform = 'translateY(-10px)';
} else {
dropdownMenu.style.opacity = '1';
dropdownMenu.style.visibility = 'visible';
dropdownMenu.style.transform = 'translateY(0)';
}
});
});
}
// Fermer les menus quand on clique ailleurs
document.addEventListener('click', function(e) {
if (!e.target.closest('.nav-item.dropdown')) {
dropdownItems.forEach(function(item) {
const dropdownMenu = item.querySelector('.mega-menu');
dropdownMenu.style.opacity = '0';
dropdownMenu.style.visibility = 'hidden';
dropdownMenu.style.transform = 'translateY(-10px)';
});
}
});
});
</script>
<!-- End footer Area -->
<script src=\"{{ asset('ui/js/vendor/jquery-2.2.4.min.js') }}\"></script>
<script src=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js\"></script>
<script>
// Initialiser le collapse Bootstrap 5 pour le menu hamburger après chargement de Bootstrap
document.addEventListener('DOMContentLoaded', function() {
// Attendre que Bootstrap soit complètement chargé
if (typeof bootstrap !== 'undefined') {
const navbarToggler = document.querySelector('.navbar-toggler');
const navbarCollapse = document.getElementById('navbarSupportedContent');
if (navbarToggler && navbarCollapse) {
// Bootstrap 5 devrait gérer automatiquement avec data-bs-toggle
// Mais on s'assure que ça fonctionne en écoutant les événements
navbarCollapse.addEventListener('show.bs.collapse', function() {
navbarToggler.setAttribute('aria-expanded', 'true');
navbarToggler.classList.add('active');
});
navbarCollapse.addEventListener('hide.bs.collapse', function() {
navbarToggler.setAttribute('aria-expanded', 'false');
navbarToggler.classList.remove('active');
});
}
}
});
</script>
<script src=\"https://unpkg.com/dropzone@5/dist/min/dropzone.min.js\"></script>
<script src=\"{{ asset('ui/js/jquery.ajaxchimp.min.js') }}\"></script>
<script src=\"{{ asset('ui/js/jquery.nice-select.min.js') }}\"></script>
<script src=\"{{ asset('ui/js/jquery.sticky.js') }}\"></script>
<script src=\"{{ asset('ui/js/nouislider.min.js') }}\"></script>
<script src=\"{{ asset('ui/js/countdown.js') }}\"></script>
<script src=\"{{ asset('ui/js/jquery.magnific-popup.min.js') }}\"></script>
<script src=\"{{ asset('ui/js/owl.carousel.min.js') }}\"></script>
<script src=\"https://maps.googleapis.com/maps/api/js?key=AIzaSyCjCGmQ0Uq4exrzdcL6rvxywDDOvfAu6eE\"></script>
<script src=\"{{ asset('ui/js/gmaps.min.js') }}\"></script>
<script src=\"{{ asset('ui/js/main.js') }}\"></script>
<script>
window.maketouConfig = {
themeStorageKey: 'maketou-theme',
comparison: {
assetBase: '{{ asset('')|e('js') }}',
addUrlTemplate: '{{ path('ui_api_comparison_add', {'id': '__ID__'})|e('js') }}',
removeUrlTemplate: '{{ path('ui_api_comparison_remove', {'id': '__ID__'})|e('js') }}',
clearUrl: '{{ path('ui_api_comparison_clear')|e('js') }}',
countUrl: '{{ path('ui_api_comparison_count')|e('js') }}',
dataUrl: '{{ path('ui_api_comparison_data')|e('js') }}',
pageUrl: '{{ path('ui_product_comparison')|e('js') }}'
}
};
</script>
<script src=\"{{ asset('ui/js/theme-public.js') }}\"></script>
<script src=\"{{ asset('ui/js/comparison-v2.js') }}\"></script>
{{ encore_entry_script_tags('app') }}
<!-- PWA Service Worker Registration -->
<script>
// Enregistrement du Service Worker
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('{{ asset('sw.js') }}')
.then((registration) => {
console.log('Service Worker enregistré avec succès:', registration.scope);
// Vérifie les mises à jour du service worker
registration.addEventListener('updatefound', () => {
const newWorker = registration.installing;
newWorker.addEventListener('statechange', () => {
if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
// Nouveau service worker disponible
if (confirm('Une nouvelle version de MaketOu est disponible. Voulez-vous l\\'installer maintenant ?')) {
newWorker.postMessage({ type: 'SKIP_WAITING' });
window.location.reload();
}
}
});
});
})
.catch((error) => {
console.log('Échec de l\\'enregistrement du Service Worker:', error);
});
// Écoute les messages du service worker
navigator.serviceWorker.addEventListener('message', (event) => {
console.log('Message du Service Worker:', event.data);
});
});
}
</script>
<!-- PWA Install Script -->
<script src=\"{{ asset('js/pwa-install.js') }}\"></script>
<script>
// Charger les compteurs au chargement de la page
document.addEventListener('DOMContentLoaded', function() {
{% if app.user %}
loadNotificationCount();
// Délai pour s'assurer que la session est bien établie après connexion
setTimeout(function() {
loadComparisonCount();
}, 500);
{% endif %}
// Gérer le bouton de recherche mobile
const searchMobileBtn = document.getElementById('searchMobileBtn');
if (searchMobileBtn) {
searchMobileBtn.addEventListener('click', function(e) {
e.preventDefault();
// Utiliser le même comportement que le bouton desktop
const searchBox = document.getElementById('search_input_box');
if (searchBox) {
searchBox.style.display = 'block';
const searchInput = document.getElementById('search_input');
if (searchInput) {
setTimeout(() => searchInput.focus(), 100);
}
}
});
}
});
function loadNotificationCount() {
{% if app.user %}
fetch('{{ path(\"api_notifications_count\") }}')
.then(response => {
if (!response.ok) {
throw new Error('Erreur HTTP: ' + response.status);
}
return response.json();
})
.then(data => {
const count = data.count || 0;
// Mettre à jour tous les badges de notification
const badges = [
document.getElementById('notificationBadge'),
document.getElementById('notificationBadgeMobile'),
document.querySelector('.notification-badge')
].filter(badge => badge !== null);
badges.forEach(badge => {
if (count > 0) {
badge.textContent = count;
badge.style.display = 'flex';
badge.style.color = 'white';
badge.style.backgroundColor = '#dc3545';
} else {
badge.style.display = 'none';
}
});
// Si on est sur la page des notifications, mettre à jour aussi le contenu de la page
if (typeof updateNotificationPageContent === 'function') {
updateNotificationPageContent(count);
}
})
.catch(error => {
console.error('Erreur lors du chargement du compteur de notifications:', error);
});
{% endif %}
}
// Exposer la fonction globalement pour qu'elle puisse être appelée depuis d'autres pages
window.loadNotificationCount = loadNotificationCount;
// Recharger le compteur toutes les 30 secondes pour garder les données à jour
{% if app.user %}
setInterval(function() {
loadNotificationCount();
}, 30000);
{% endif %}
function loadComparisonCount() {
// Ne pas appeler l'API si on est sur une page d'erreur ou de redirection
if (window.location.pathname.includes('/api/') || window.location.pathname.includes('/login')) {
return;
}
// Utiliser un try-catch pour éviter toute redirection
try {
fetch('{{ path(\"ui_api_comparison_count\") }}', {
method: 'GET',
headers: {
'X-Requested-With': 'XMLHttpRequest',
'Accept': 'application/json'
},
credentials: 'same-origin',
redirect: 'error' // Empêcher les redirections automatiques
})
.then(response => {
// Vérifier si la réponse est OK
if (!response.ok) {
// Si c'est une redirection (301, 302, etc.) ou une erreur d'authentification, ignorer silencieusement
if (response.status >= 300 && response.status < 400) {
console.warn('Redirection détectée, arrêt de la requête');
return null;
}
if (response.status === 401 || response.status === 403) {
console.warn('Utilisateur non authentifié pour la comparaison');
return null;
}
// Pour les autres erreurs, throw pour être capturé par catch
throw new Error('Erreur HTTP: ' + response.status);
}
// Vérifier que c'est bien du JSON
const contentType = response.headers.get('content-type');
if (!contentType || !contentType.includes('application/json')) {
// Si ce n'est pas du JSON, c'est probablement une redirection HTML
console.warn('La réponse n\\'est pas du JSON, probable redirection');
return null;
}
return response.json();
})
.then(data => {
// Si data est null (redirection ou erreur), ne rien faire
if (!data || typeof data.count === 'undefined') {
return;
}
// Mettre à jour les badges desktop et mobile
const badges = [
document.getElementById('comparisonBadge'),
document.getElementById('comparisonBadgeMobile')
];
badges.forEach(badge => {
if (badge) {
if (data.count > 0) {
badge.textContent = data.count;
badge.style.display = 'flex';
} else {
badge.style.display = 'none';
}
}
});
})
.catch(error => {
// Ne pas afficher d'erreur si c'est juste une absence d'authentification ou une redirection
if (error.message && !error.message.includes('401') && !error.message.includes('403') && !error.message.includes('redirect')) {
console.error('Erreur lors du chargement du compteur de comparaison:', error);
}
// Empêcher toute redirection vers l'URL de l'API
return false;
});
} catch (e) {
// Capturer toute erreur qui pourrait causer une redirection
console.warn('Erreur lors de l\\'appel à l\\'API de comparaison:', e);
}
}
// Fonction globale pour gérer la comparaison
function toggleComparison(productId, element) {
if (!element) {
element = document.querySelector(`.comparison-btn[data-product-id=\"\${productId}\"]`);
}
if (!element) {
console.error('Bouton de comparaison non trouvé pour le produit', productId);
return;
}
const originalHtml = element.innerHTML;
// Désactiver le bouton/lien
if (element.tagName === 'BUTTON') {
element.disabled = true;
} else {
element.style.pointerEvents = 'none';
element.style.opacity = '0.6';
}
element.innerHTML = '<span class=\"spinner-border spinner-border-sm\"></span>';
// Vérifier d'abord si le produit est déjà en comparaison
let isInComparison = false;
fetch(`/api/comparison/status/\${productId}`)
.then(response => {
const contentType = response.headers.get('content-type');
if (contentType && contentType.includes('text/html')) {
window.location.href = '{{ path(\"ui_app_login\") }}';
throw new Error('Not authenticated');
}
return response.json();
})
.then(data => {
isInComparison = data.inComparison;
const url = isInComparison ? `/api/comparison/remove/\${productId}` : `/api/comparison/add/\${productId}`;
return fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
}
});
})
.then(response => {
const contentType = response.headers.get('content-type');
if (contentType && contentType.includes('text/html')) {
window.location.href = '{{ path(\"ui_app_login\") }}';
throw new Error('Not authenticated');
}
return response.json();
})
.then(data => {
if (data.success) {
// Mettre à jour le compteur
loadComparisonCount();
// Mettre à jour l'apparence du bouton
if (element) {
// Inverser l'état (car on vient de le changer)
const newState = !isInComparison;
// Restaurer le HTML original puis mettre à jour
element.innerHTML = originalHtml;
if (newState) {
element.classList.add('active');
// Mettre à jour le texte pour les deux types de boutons
const textEl = element.querySelector('.comparison-text') || element.querySelector('.hover-text') || element.querySelector('p.hover-text');
if (textEl) textEl.textContent = 'En comparaison';
// Mettre à jour l'icône si nécessaire (chercher dans span ou i)
const iconEl = element.querySelector('.lnr-sync, span.lnr-sync, [class*=\"sync\"], i[class*=\"sync\"]');
if (iconEl) {
iconEl.style.color = '#28a745';
iconEl.classList.add('active');
}
} else {
element.classList.remove('active');
const textEl = element.querySelector('.comparison-text') || element.querySelector('.hover-text') || element.querySelector('p.hover-text');
if (textEl) textEl.textContent = 'Comparer';
// Restaurer la couleur de l'icône
const iconEl = element.querySelector('.lnr-sync, span.lnr-sync, [class*=\"sync\"], i[class*=\"sync\"]');
if (iconEl) {
iconEl.style.color = '';
iconEl.classList.remove('active');
}
}
}
// Afficher une notification
showNotification(data.message, 'success');
} else {
showNotification(data.message, 'error');
if (element) {
element.innerHTML = originalHtml;
}
}
})
.catch(error => {
console.error('Erreur:', error);
showNotification('Une erreur est survenue', 'error');
if (element) {
element.innerHTML = originalHtml;
}
})
.finally(() => {
if (element) {
if (element.tagName === 'BUTTON') {
element.disabled = false;
} else {
element.style.pointerEvents = '';
element.style.opacity = '';
}
}
});
}
// Fonction globale pour gérer les favoris
function toggleWishlist(productId, element) {
if (!element) {
element = document.querySelector(`.wishlist-btn[data-product-id=\"\${productId}\"]`);
}
if (!element) {
console.error('Bouton de wishlist non trouvé pour le produit', productId);
return;
}
const originalHtml = element.innerHTML;
// Désactiver le bouton/lien
if (element.tagName === 'BUTTON') {
element.disabled = true;
} else {
element.style.pointerEvents = 'none';
element.style.opacity = '0.6';
}
element.innerHTML = '<span class=\"spinner-border spinner-border-sm\"></span>';
// Vérifier d'abord si le produit est déjà en favoris
let isInWishlist = false;
fetch(`/api/wishlist/status/\${productId}`)
.then(response => {
const contentType = response.headers.get('content-type');
if (contentType && contentType.includes('text/html')) {
window.location.href = '{{ path(\"ui_app_login\") }}';
throw new Error('Not authenticated');
}
return response.json();
})
.then(data => {
isInWishlist = data.inWishlist;
const url = isInWishlist ? `/api/wishlist/remove/\${productId}` : `/api/wishlist/add/\${productId}`;
return fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
}
});
})
.then(response => {
const contentType = response.headers.get('content-type');
if (contentType && contentType.includes('text/html')) {
window.location.href = '{{ path(\"ui_app_login\") }}';
throw new Error('Not authenticated');
}
return response.json();
})
.then(data => {
if (data.success) {
// Mettre à jour l'apparence du bouton
if (element) {
// Inverser l'état (car on vient de le changer)
const newState = !isInWishlist;
// Restaurer le HTML original puis mettre à jour
element.innerHTML = originalHtml;
// Chercher l'icône dans span ou i
const icon = element.querySelector('span.lnr-heart, i.lnr-heart, [class*=\"lnr-heart\"]');
const text = element.querySelector('.wishlist-text') || element.querySelector('.hover-text') || element.querySelector('p.hover-text');
if (newState) {
if (icon) {
// Pour les icônes linr, on change la classe
if (icon.classList.contains('lnr-heart')) {
icon.classList.remove('lnr-heart');
}
if (!icon.classList.contains('lnr-heart-filled')) {
icon.classList.add('lnr-heart-filled');
}
icon.style.color = '#dc3545';
}
element.classList.add('active');
if (text) text.textContent = 'Dans favoris';
} else {
if (icon) {
// Restaurer l'icône originale
if (icon.classList.contains('lnr-heart-filled')) {
icon.classList.remove('lnr-heart-filled');
}
if (!icon.classList.contains('lnr-heart')) {
icon.classList.add('lnr-heart');
}
icon.style.color = '';
}
element.classList.remove('active');
if (text) text.textContent = 'Favoris';
}
}
// Afficher une notification
showNotification(data.message, 'success');
// Si on est sur la page wishlist, recharger la page
if (window.location.pathname.includes('/account/wishlist')) {
setTimeout(() => location.reload(), 1000);
}
} else {
showNotification(data.message, 'error');
if (element) {
element.innerHTML = originalHtml;
}
}
})
.catch(error => {
console.error('Erreur:', error);
showNotification('Une erreur est survenue', 'error');
if (element) {
element.innerHTML = originalHtml;
}
})
.finally(() => {
if (element) {
if (element.tagName === 'BUTTON') {
element.disabled = false;
} else {
element.style.pointerEvents = '';
element.style.opacity = '';
}
}
});
}
// Fonction pour afficher des notifications
function showNotification(message, type = 'success') {
// Créer l'élément de notification
const notification = document.createElement('div');
notification.className = `alert alert-\${type === 'success' ? 'success' : 'danger'} alert-dismissible fade show position-fixed`;
notification.style.cssText = 'top: 20px; right: 20px; z-index: 9999; min-width: 300px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);';
notification.innerHTML = `
\${message}
<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\"></button>
`;
document.body.appendChild(notification);
// Supprimer automatiquement après 3 secondes
setTimeout(() => {
notification.remove();
}, 3000);
}
// Initialiser les alertes Bootstrap 5 pour la fermeture
document.addEventListener('DOMContentLoaded', function() {
// S'assurer que les alertes peuvent être fermées
const alertCloseButtons = document.querySelectorAll('.flash-message .btn-close');
alertCloseButtons.forEach(function(button) {
button.addEventListener('click', function() {
const alert = this.closest('.alert');
if (alert) {
alert.classList.remove('show');
setTimeout(function() {
alert.remove();
}, 150);
}
});
});
// Charger les statuts initiaux des produits
{% if app.user %}
// Charger les statuts de comparaison pour tous les produits visibles
document.querySelectorAll('.comparison-btn[data-product-id]').forEach(btn => {
const productId = btn.dataset.productId;
fetch(`/api/comparison/status/\${productId}`)
.then(response => response.json())
.then(data => {
if (data.inComparison) {
btn.classList.add('active');
// Mettre à jour le texte pour les deux types de boutons
const textEl = btn.querySelector('.comparison-text') || btn.querySelector('.hover-text') || btn.querySelector('p.hover-text');
if (textEl) textEl.textContent = 'En comparaison';
// Mettre à jour l'icône si nécessaire
const iconEl = btn.querySelector('.lnr-sync, [class*=\"sync\"]');
if (iconEl) iconEl.style.color = '#28a745';
}
})
.catch(() => {});
});
// Charger les statuts de wishlist pour tous les produits visibles
document.querySelectorAll('.wishlist-btn[data-product-id]').forEach(btn => {
const productId = btn.dataset.productId;
fetch(`/api/wishlist/status/\${productId}`)
.then(response => response.json())
.then(data => {
if (data.inWishlist) {
btn.classList.add('active');
// Chercher l'icône dans span ou i
const icon = btn.querySelector('span.lnr-heart, i.lnr-heart, [class*=\"lnr-heart\"]');
if (icon) {
icon.classList.remove('lnr-heart');
icon.classList.add('lnr-heart-filled');
icon.style.color = '#dc3545';
}
// Mettre à jour le texte pour les deux types de boutons
const textEl = btn.querySelector('.wishlist-text') || btn.querySelector('.hover-text') || btn.querySelector('p.hover-text');
if (textEl) textEl.textContent = 'Dans favoris';
}
})
.catch(() => {});
});
// Charger le compteur de comparaison
loadComparisonCount();
{% endif %}
});
</script>
<script>
// Loader global pour tous les boutons de formulaire
document.addEventListener('DOMContentLoaded', function() {
// Intercepter tous les formulaires
const forms = document.querySelectorAll('form');
forms.forEach(function(form) {
form.addEventListener('submit', function(e) {
const submitButtons = form.querySelectorAll('button[type=\"submit\"], input[type=\"submit\"], button:not([type])');
submitButtons.forEach(function(button) {
// Vérifier si le bouton n'est pas déjà désactivé
if (!button.disabled && !button.classList.contains('loading')) {
button.classList.add('loading');
button.disabled = true;
// Sauvegarder le texte original
const originalText = button.innerHTML;
button.setAttribute('data-original-text', originalText);
// Ajouter le loader
button.innerHTML = '<span class=\"spinner-border spinner-border-sm me-2\" role=\"status\" aria-hidden=\"true\"></span>Envoi...';
// Si le formulaire n'est pas valide, réactiver le bouton après 1 seconde
setTimeout(function() {
if (!form.checkValidity()) {
button.classList.remove('loading');
button.disabled = false;
button.innerHTML = originalText;
}
}, 1000);
}
});
});
});
// Pour les boutons qui déclenchent des actions AJAX
const ajaxButtons = document.querySelectorAll('[data-ajax], .ajax-submit, button[data-submit]');
ajaxButtons.forEach(function(button) {
button.addEventListener('click', function(e) {
if (this.disabled || this.classList.contains('loading')) {
e.preventDefault();
return false;
}
this.classList.add('loading');
this.disabled = true;
const originalText = this.innerHTML;
this.setAttribute('data-original-text', originalText);
this.innerHTML = '<span class=\"spinner-border spinner-border-sm me-2\" role=\"status\" aria-hidden=\"true\"></span>Chargement...';
});
});
// Gestionnaire spécifique pour le formulaire de newsletter
const newsletterForm = document.querySelector('.footer-newsletter-form');
if (newsletterForm) {
newsletterForm.addEventListener('submit', function(e) {
const submitBtn = this.querySelector('.newsletter-btn');
if (submitBtn && !submitBtn.disabled) {
submitBtn.classList.add('loading');
submitBtn.disabled = true;
// Afficher le loader et masquer l'icône
const icon = submitBtn.querySelector('.newsletter-btn-icon');
const loader = submitBtn.querySelector('.newsletter-btn-loader');
if (icon) icon.style.display = 'none';
if (loader) loader.style.display = 'flex';
// Réactiver le bouton après 5 secondes au cas où la requête échoue silencieusement
setTimeout(function() {
if (submitBtn.classList.contains('loading')) {
submitBtn.classList.remove('loading');
submitBtn.disabled = false;
if (icon) icon.style.display = 'flex';
if (loader) loader.style.display = 'none';
}
}, 5000);
}
});
// Gérer la réponse du formulaire (si AJAX)
newsletterForm.addEventListener('submit', function(e) {
// Si le formulaire est soumis normalement (non-AJAX), le navigateur gère la réponse
// Sinon, on peut intercepter pour gérer la réponse AJAX ici
});
}
});
// CSS pour le spinner
const style = document.createElement('style');
style.textContent = `
.spinner-border-sm {
width: 1rem;
height: 1rem;
border-width: 0.15em;
}
.spinner-border {
display: inline-block;
width: 1rem;
height: 1rem;
vertical-align: text-bottom;
border: 0.15em solid currentColor;
border-right-color: transparent;
border-radius: 50%;
animation: spinner-border 0.75s linear infinite;
}
@keyframes spinner-border {
to { transform: rotate(360deg); }
}
button.loading {
opacity: 0.7;
cursor: not-allowed !important;
}
`;
document.head.appendChild(style);
</script>
\t<!-- Modal Global Custom Alert -->
\t<div class=\"modal fade custom-alert-modal\" id=\"customAlertModal\" tabindex=\"-1\" aria-labelledby=\"customAlertModalLabel\" aria-hidden=\"true\">
\t\t<div class=\"modal-dialog modal-dialog-centered\">
\t\t\t<div class=\"modal-content\">
\t\t\t\t<div class=\"modal-header\">
\t\t\t\t\t<h5 class=\"modal-title text-white\" id=\"customAlertModalLabel\">Notification</h5>
\t\t\t\t\t<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Close\"></button>
\t\t\t\t</div>
\t\t\t\t<div class=\"modal-body\">
\t\t\t\t\t<div class=\"alert-icon\" id=\"alertIcon\">
\t\t\t\t\t\t<i class=\"lnr lnr-info-circle\"></i>
\t\t\t\t\t</div>
\t\t\t\t\t<p class=\"alert-message\" id=\"alertMessage\"></p>
\t\t\t\t</div>
\t\t\t\t<div class=\"modal-footer\">
\t\t\t\t\t<button type=\"button\" class=\"btn btn-primary\" data-bs-dismiss=\"modal\">OK</button>
\t\t\t\t</div>
\t\t\t</div>
\t\t</div>
\t</div>
\t<script>
\t\t// Fonction globale pour remplacer alert() ou afficher des messages
\t\tfunction showCustomAlert(message, type = 'info') {
\t\t\tconst modalEl = document.getElementById('customAlertModal');
\t\t\tif (!modalEl) {
\t\t\t\t// Fallback sur showNotification
\t\t\t\tlet notifyType = type === 'error' || type === 'danger' ? 'error' : (type === 'success' ? 'success' : 'warning');
\t\t\t\tif (typeof showNotification === 'function') {
\t\t\t\t\tshowNotification(message, notifyType);
\t\t\t\t} else {
\t\t\t\t\talert(message);
\t\t\t\t}
\t\t\t\treturn;
\t\t\t}
\t\t\t
\t\t\tconst modal = new bootstrap.Modal(modalEl);
\t\t\tconst alertMessage = document.getElementById('alertMessage');
\t\t\tconst alertIcon = document.getElementById('alertIcon');
\t\t\tconst modalTitle = document.getElementById('customAlertModalLabel');
\t\t\talertMessage.textContent = message;
\t\t\t// Définir l'icône et le titre selon le type
\t\t\tlet iconClass = 'lnr lnr-info-circle';
\t\t\tlet title = 'Information';
\t\t\tswitch (type) {
\t\t\t\tcase 'success':
\t\t\t\t\ticonClass = 'lnr lnr-checkmark-circle';
\t\t\t\t\ttitle = 'Succès';
\t\t\t\t\talertIcon.className = 'alert-icon success';
\t\t\t\t\tbreak;
\t\t\t\tcase 'error':
\t\t\t\tcase 'danger':
\t\t\t\t\ticonClass = 'lnr lnr-warning';
\t\t\t\t\ttitle = 'Erreur';
\t\t\t\t\talertIcon.className = 'alert-icon error';
\t\t\t\t\tbreak;
\t\t\t\tcase 'warning':
\t\t\t\t\ticonClass = 'lnr lnr-warning';
\t\t\t\t\ttitle = 'Attention';
\t\t\t\t\talertIcon.className = 'alert-icon warning';
\t\t\t\t\tbreak;
\t\t\t\tdefault:
\t\t\t\t\ticonClass = 'lnr lnr-info-circle';
\t\t\t\t\ttitle = 'Information';
\t\t\t\t\talertIcon.className = 'alert-icon info';
\t\t\t}
\t\t\talertIcon.innerHTML = `<i class=\"\${iconClass}\"></i>`;
\t\t\tmodalTitle.textContent = title;
\t\t\tmodal.show();
\t\t};
\t</script>
{% block javascripts %}
{% endblock %}
</body>
</html>
", "base_home.html.twig", "/home/u540977899/domains/maketou-ht.com/public_html/templates/base_home.html.twig");
}
}