var/cache/dev/twig/7e/7e1eaabe8cf91543b9a61edc82fd2f29.php line 3266

Open in your IDE?
  1. <?php
  2. use Twig\Environment;
  3. use Twig\Error\LoaderError;
  4. use Twig\Error\RuntimeError;
  5. use Twig\Extension\CoreExtension;
  6. use Twig\Extension\SandboxExtension;
  7. use Twig\Markup;
  8. use Twig\Sandbox\SecurityError;
  9. use Twig\Sandbox\SecurityNotAllowedTagError;
  10. use Twig\Sandbox\SecurityNotAllowedFilterError;
  11. use Twig\Sandbox\SecurityNotAllowedFunctionError;
  12. use Twig\Source;
  13. use Twig\Template;
  14. use Twig\TemplateWrapper;
  15. /* base_home.html.twig */
  16. class __TwigTemplate_c86efc76357b73ced93910d382926e56 extends Template
  17. {
  18.     private Source $source;
  19.     /**
  20.      * @var array<string, Template>
  21.      */
  22.     private array $macros = [];
  23.     public function __construct(Environment $env)
  24.     {
  25.         parent::__construct($env);
  26.         $this->source $this->getSourceContext();
  27.         $this->parent false;
  28.         $this->blocks = [
  29.             'title' => [$this'block_title'],
  30.             'stylesheets' => [$this'block_stylesheets'],
  31.             'body' => [$this'block_body'],
  32.             'javascripts' => [$this'block_javascripts'],
  33.         ];
  34.     }
  35.     protected function doDisplay(array $context, array $blocks = []): iterable
  36.     {
  37.         $macros $this->macros;
  38.         $__internal_5a27a8ba21ca79b61932376b2fa922d2 $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  39.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "template""base_home.html.twig"));
  40.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  41.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "template""base_home.html.twig"));
  42.         // line 1
  43.         yield "<!DOCTYPE html>
  44. <html lang=\"fr\" class=\"no-js\">
  45. \t<head>
  46. \t\t<!-- Mobile Specific Meta -->
  47. \t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no\">
  48. \t\t<meta name=\"mobile-web-app-capable\" content=\"yes\">
  49. \t\t<meta name=\"apple-mobile-web-app-capable\" content=\"yes\">
  50. \t\t<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"default\">
  51. \t\t<meta name=\"apple-mobile-web-app-title\" content=\"MaketOu\">
  52. \t\t<meta name=\"theme-color\" content=\"#ffa200\">
  53. \t\t<meta name=\"msapplication-TileColor\" content=\"#ffa200\">
  54. \t\t<meta
  55. \t\tname=\"msapplication-config\" content=\"";
  56.         // line 14
  57.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("favicon/browserconfig.xml"), "html"nulltrue);
  58.         yield "\">
  59. \t\t<!-- Favicon-->
  60. \t\t<link rel=\"shortcut icon\" href=\"";
  61.         // line 17
  62.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("favicon/favicon-16x16.png"), "html"nulltrue);
  63.         yield "\">
  64. \t\t<link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"";
  65.         // line 18
  66.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("favicon/apple-touch-icon.png"), "html"nulltrue);
  67.         yield "\">
  68. \t\t<link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"";
  69.         // line 19
  70.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("favicon/favicon-32x32.png"), "html"nulltrue);
  71.         yield "\">
  72. \t\t<link
  73. \t\trel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"";
  74.         // line 21
  75.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("favicon/favicon-16x16.png"), "html"nulltrue);
  76.         yield "\">
  77. \t\t<!-- PWA Manifest -->
  78. \t\t<link
  79. \t\trel=\"manifest\" href=\"";
  80.         // line 25
  81.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("manifest.json"), "html"nulltrue);
  82.         yield "\">
  83. \t\t<!-- Author Meta -->
  84. \t\t<meta
  85. \t\tname=\"author\" content=\"Foulgor Tech\">
  86. \t\t<!-- Meta Description -->
  87. \t\t<meta
  88. \t\tname=\"description\" content=\"\">
  89. \t\t<!-- Meta Keyword -->
  90. \t\t<meta
  91. \t\tname=\"keywords\" content=\"\">
  92. \t\t<!-- meta character set -->
  93. \t\t<meta
  94. \t\tcharset=\"UTF-8\">
  95. \t\t<!-- Site Title -->
  96. \t\t<title>
  97. \t\t\t";
  98.         // line 40
  99.         yield from $this->unwrap()->yieldBlock('title'$context$blocks);
  100.         // line 42
  101.         yield "\t\t</title>
  102. \t\t<!--
  103. \t\t\t\t\t\t        CSS
  104. \t\t\t\t\t\t        ============================================= -->
  105. \t\t<link rel=\"stylesheet\" href=\"https://unpkg.com/dropzone@5/dist/min/dropzone.min.css\"/>
  106. \t\t<link rel=\"stylesheet\" href=\"";
  107.         // line 47
  108.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/linearicons.css"), "html"nulltrue);
  109.         yield "\">
  110. \t\t<link rel=\"stylesheet\" href=\"";
  111.         // line 48
  112.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/font-awesome.min.css"), "html"nulltrue);
  113.         yield "\">
  114. \t\t<link rel=\"stylesheet\" href=\"";
  115.         // line 49
  116.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/themify-icons.css"), "html"nulltrue);
  117.         yield "\">
  118. \t\t<link rel=\"stylesheet\" href=\"";
  119.         // line 50
  120.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/bootstrap.css"), "html"nulltrue);
  121.         yield "\">
  122. \t\t<link rel=\"stylesheet\" href=\"";
  123.         // line 51
  124.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/owl.carousel.css"), "html"nulltrue);
  125.         yield "\">
  126. \t\t<link rel=\"stylesheet\" href=\"";
  127.         // line 52
  128.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/nice-select.css"), "html"nulltrue);
  129.         yield "\">
  130. \t\t<link rel=\"stylesheet\" href=\"";
  131.         // line 53
  132.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/nouislider.min.css"), "html"nulltrue);
  133.         yield "\">
  134. \t\t<link rel=\"stylesheet\" href=\"";
  135.         // line 54
  136.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/ion.rangeSlider.css"), "html"nulltrue);
  137.         yield "\"/>
  138. \t\t<link rel=\"stylesheet\" href=\"";
  139.         // line 55
  140.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/ion.rangeSlider.skinFlat.css"), "html"nulltrue);
  141.         yield "\"/>
  142. \t\t<link rel=\"stylesheet\" href=\"";
  143.         // line 56
  144.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/magnific-popup.css"), "html"nulltrue);
  145.         yield "\">
  146. \t\t<link rel=\"stylesheet\" href=\"";
  147.         // line 57
  148.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/main.css"), "html"nulltrue);
  149.         yield "\">
  150. \t\t<link rel=\"stylesheet\" href=\"";
  151.         // line 58
  152.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/cart-modal.css"), "html"nulltrue);
  153.         yield "\">
  154. \t\t<link rel=\"stylesheet\" href=\"";
  155.         // line 59
  156.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/css/buttons-unified.css"), "html"nulltrue);
  157.         yield "\">
  158. \t\t<meta
  159. \t\tcharset=\"UTF-8\">
  160. \t\t";
  161.         // line 63
  162.         yield "
  163. \t\t<style>
  164. \t\t\t/* Styles pour l'icône de notification */
  165. \t\t\t.notification-icon {
  166. \t\t\t\tposition: relative;
  167. \t\t\t\tdisplay: inline-block;
  168. \t\t\t\tcolor: #333;
  169. \t\t\t\ttext-decoration: none;
  170. \t\t\t\ttransition: color 0.3s ease;
  171. \t\t\t}
  172. \t\t\t.notification-icon:hover {
  173. \t\t\t\tcolor: #007bff;
  174. \t\t\t}
  175. \t\t\t.notification-badge {
  176. \t\t\t\tposition: absolute;
  177. \t\t\t\ttop: -4px;
  178. \t\t\t\tright: -2px;
  179. \t\t\t\tbackground: #dc3545 !important;
  180. \t\t\t\tcolor: white !important;
  181. \t\t\t\tborder-radius: 50%;
  182. \t\t\t\twidth: 18px;
  183. \t\t\t\theight: 18px;
  184. \t\t\t\tfont-size: 8px !important;
  185. \t\t\t\tdisplay: flex !important;
  186. \t\t\t\talign-items: center !important;
  187. \t\t\t\tjustify-content: center !important;
  188. \t\t\t\tfont-weight: bold !important;
  189. \t\t\t\tanimation: pulse 2s infinite;
  190. \t\t\t\tz-index: 10;
  191. \t\t\t\tline-height: 1 !important;
  192. \t\t\t}
  193. \t\t\t/* Forcer le texte en blanc pour tous les éléments du badge - avec spécificité maximale */
  194. \t\t\t.notification-badge,
  195. \t\t\t.notification-badge.text-white,
  196. \t\t\t.notification-badge *,
  197. \t\t\t#notificationBadge,
  198. \t\t\t#notificationBadge.text-white,
  199. \t\t\t#notificationBadge *,
  200. \t\t\tspan.notification-badge,
  201. \t\t\tspan.notification-badge.text-white,
  202. \t\t\tspan#notificationBadge,
  203. \t\t\tspan#notificationBadge.text-white {
  204. \t\t\t\tcolor: white !important;
  205. \t\t\t\ttext-color: white !important;
  206. \t\t\t\t-webkit-text-fill-color: white !important;
  207. \t\t\t}
  208. \t\t\t/* S'assurer que le contenu texte est bien en blanc */
  209. \t\t\t.notification-badge::before,
  210. \t\t\t.notification-badge::after {
  211. \t\t\t\tcolor: white !important;
  212. \t\t\t}
  213. \t\t\t/* Forcer la couleur pour tous les sélecteurs possibles avec spécificité maximale */
  214. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon .notification-badge,
  215. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon .notification-badge.text-white,
  216. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon span.notification-badge,
  217. \t\t\t.notification-icon .notification-badge,
  218. \t\t\t.notification-icon .notification-badge.text-white,
  219. \t\t\t.notification-icon span.notification-badge,
  220. \t\t\ta.notification-icon .notification-badge,
  221. \t\t\ta.notification-icon span.notification-badge {
  222. \t\t\t\tcolor: white !important;
  223. \t\t\t\ttext-color: white !important;
  224. \t\t\t\t-webkit-text-fill-color: white !important;
  225. \t\t\t}
  226. \t\t\t/* Forcer la couleur pour tous les enfants directs */
  227. \t\t\t.notification-icon > .notification-badge,
  228. \t\t\t.notification-icon > span.notification-badge {
  229. \t\t\t\tcolor: white !important;
  230. \t\t\t}
  231. \t\t\t@keyframes pulse {
  232. \t\t\t\t0% {
  233. \t\t\t\t\ttransform: scale(1);
  234. \t\t\t\t}
  235. \t\t\t\t50% {
  236. \t\t\t\t\ttransform: scale(1.1);
  237. \t\t\t\t}
  238. \t\t\t\t100% {
  239. \t\t\t\t\ttransform: scale(1);
  240. \t\t\t\t}
  241. \t\t\t}
  242. \t\t\t.notification-icon:hover .notification-badge {
  243. \t\t\t\tanimation: none;
  244. \t\t\t}
  245. \t\t\t/* Container pour les icônes - toujours alignées horizontalement */
  246. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper {
  247. \t\t\t\tdisplay: flex !important;
  248. \t\t\t\tflex-direction: row !important;
  249. \t\t\t\talign-items: center !important;
  250. \t\t\t\tjustify-content: center !important;
  251. \t\t\t\tgap: 15px !important;
  252. \t\t\t\tlist-style: none !important;
  253. \t\t\t\tmargin: 0 !important;
  254. \t\t\t\tpadding: 0 !important;
  255. \t\t\t\twidth: auto !important;
  256. \t\t\t}
  257. \t\t\t/* Surcharger les styles existants pour les li contenant le wrapper */
  258. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right li:has(.navbar-icons-wrapper) {
  259. \t\t\t\tmargin-left: 0 !important;
  260. \t\t\t\tmargin-right: 0 !important;
  261. \t\t\t\tdisplay: flex !important;
  262. \t\t\t\talign-items: center !important;
  263. \t\t\t\tjustify-content: center !important;
  264. \t\t\t}
  265. \t\t\t/* Styles pour les icônes */
  266. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .cart,
  267. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon,
  268. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon,
  269. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search {
  270. \t\t\t\tdisplay: flex !important;
  271. \t\t\t\talign-items: center !important;
  272. \t\t\t\tjustify-content: center !important;
  273. \t\t\t\twidth: 40px !important;
  274. \t\t\t\theight: 40px !important;
  275. \t\t\t\tmin-width: 40px !important;
  276. \t\t\t\tmin-height: 40px !important;
  277. \t\t\t\tcolor: #333 !important;
  278. \t\t\t\ttext-decoration: none !important;
  279. \t\t\t\ttransition: all 0.3s ease !important;
  280. \t\t\t\tborder-radius: 50% !important;
  281. \t\t\t\tposition: relative !important;
  282. \t\t\t\tmargin: 0 !important;
  283. \t\t\t\tpadding: 0 !important;
  284. \t\t\t}
  285. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .cart:hover,
  286. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon:hover,
  287. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon:hover,
  288. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search:hover {
  289. \t\t\t\tbackground-color: #f0f0f0 !important;
  290. \t\t\t\tcolor: #ffa200 !important;
  291. \t\t\t\ttransform: scale(1.1) !important;
  292. \t\t\t}
  293. \t\t\t/* Surcharger le line-height de main.css */
  294. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .cart span,
  295. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon span,
  296. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search span {
  297. \t\t\t\tfont-size: 18px !important;
  298. \t\t\t\tline-height: 1 !important;
  299. \t\t\t\tdisplay: flex !important;
  300. \t\t\t\talign-items: center !important;
  301. \t\t\t\tjustify-content: center !important;
  302. \t\t\t\tcolor: inherit !important;
  303. \t\t\t\tfont-weight: normal !important;
  304. \t\t\t}
  305. \t\t\t/* Icône de comparaison en noir comme le panier */
  306. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon {
  307. \t\t\t\tcolor: #333 !important;
  308. \t\t\t}
  309. \t\t\t/* L'icône elle-même (lnr-sync) doit être noire, mais pas le badge */
  310. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon > span.lnr-sync,
  311. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon span:not(.comparison-badge) {
  312. \t\t\t\tcolor: #333 !important;
  313. \t\t\t\tfont-size: 18px !important;
  314. \t\t\t\tline-height: 1 !important;
  315. \t\t\t\tdisplay: flex !important;
  316. \t\t\t\talign-items: center !important;
  317. \t\t\t\tjustify-content: center !important;
  318. \t\t\t\tfont-weight: normal !important;
  319. \t\t\t}
  320. \t\t\t/* Le badge doit rester blanc */
  321. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon .comparison-badge {
  322. \t\t\t\tcolor: white !important;
  323. \t\t\t}
  324. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search {
  325. \t\t\t\tbackground: transparent !important;
  326. \t\t\t\tborder: 0 !important;
  327. \t\t\t\tcursor: pointer !important;
  328. \t\t\t\tpadding: 0 !important;
  329. \t\t\t}
  330. \t\t\t/* Alignement des icônes navbar sur mobile */
  331. \t\t\t@media(max-width: 991.98px) {
  332. \t\t\t\t/* Container navbar-right en colonne sur mobile */
  333. \t\t\t\t.header_area .navbar .nav.navbar-nav.navbar-right {
  334. \t\t\t\t\tdisplay: flex !important;
  335. \t\t\t\t\tflex-direction: column !important;
  336. \t\t\t\t\talign-items: center !important;
  337. \t\t\t\t\tjustify-content: center !important;
  338. \t\t\t\t\twidth: 100% !important;
  339. \t\t\t\t\tgap: 0 !important;
  340. \t\t\t\t\tmargin: 0 !important;
  341. \t\t\t\t\tpadding: 10px 0 !important;
  342. \t\t\t\t}
  343. \t\t\t\t/* Le container d'icônes reste horizontal */
  344. \t\t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper {
  345. \t\t\t\t\twidth: 100% !important;
  346. \t\t\t\t\tjustify-content: center !important;
  347. \t\t\t\t\tdisplay: flex !important;
  348. \t\t\t\t\tflex-direction: row !important;
  349. \t\t\t\t}
  350. \t\t\t\t/* Le bouton compte en bas - pleine largeur */
  351. \t\t\t\t.header_area .navbar .nav.navbar-nav.navbar-right li:last-child {
  352. \t\t\t\t\twidth: 100% !important;
  353. \t\t\t\t\tdisplay: flex !important;
  354. \t\t\t\t\tjustify-content: center !important;
  355. \t\t\t\t\tmargin-top: 12px !important;
  356. \t\t\t\t\tpadding-top: 12px !important;
  357. \t\t\t\t\tborder-top: 1px solid #e0e0e0 !important;
  358. \t\t\t\t}
  359. \t\t\t\t/* Bouton compte responsive */
  360. \t\t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .btn-account {
  361. \t\t\t\t\twidth: 100%;
  362. \t\t\t\t\tmax-width: 200px;
  363. \t\t\t\t\tpadding: 10px 20px;
  364. \t\t\t\t\tfont-size: 14px;
  365. \t\t\t\t}
  366. \t\t\t}
  367. \t\t\t/* Styles pour les messages flash - Design moderne */
  368. \t\t\t.flash-message {
  369. \t\t\t\tanimation: slideInDownFlash 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  370. \t\t\t\tposition: relative;
  371. \t\t\t\toverflow: visible !important;
  372. \t\t\t\tborder: none !important;
  373. \t\t\t\tpadding: 16px 20px !important;
  374. \t\t\t\tborder-radius: 12px !important;
  375. \t\t\t\tbox-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
  376. \t\t\t\tdisplay: flex !important;
  377. \t\t\t\talign-items: center;
  378. \t\t\t\tgap: 12px;
  379. \t\t\t\tmargin-bottom: 15px;
  380. \t\t\t\tbackdrop-filter: blur(10px);
  381. \t\t\t\ttransition: all 0.3s ease;
  382. \t\t\t}
  383. \t\t\t/* S'assurer que les icônes Font Awesome sont visibles */
  384. \t\t\t.flash-message i.fa {
  385. \t\t\t\tdisplay: inline-block !important;
  386. \t\t\t\tvisibility: visible !important;
  387. \t\t\t\topacity: 1 !important;
  388. \t\t\t\twidth: auto !important;
  389. \t\t\t\theight: auto !important;
  390. \t\t\t\tfont-family: \"FontAwesome\" !important;
  391. \t\t\t\tfont-style: normal !important;
  392. \t\t\t\tfont-weight: normal !important;
  393. \t\t\t\ttext-rendering: auto !important;
  394. \t\t\t\t-webkit-font-smoothing: antialiased !important;
  395. \t\t\t\t-moz-osx-font-smoothing: grayscale !important;
  396. \t\t\t\tline-height: 1 !important;
  397. \t\t\t\tflex-shrink: 0 !important;
  398. \t\t\t}
  399. \t\t\t/* Forcer l'affichage des pseudo-éléments Font Awesome */
  400. \t\t\t.flash-message i.fa::before {
  401. \t\t\t\tdisplay: inline-block !important;
  402. \t\t\t\tvisibility: visible !important;
  403. \t\t\t\topacity: 1 !important;
  404. \t\t\t\tcontent: attr(data-icon) !important;
  405. \t\t\t}
  406. \t\t\t/* Styles spécifiques pour chaque icône */
  407. \t\t\t.flash-message i.fa-check-circle::before {
  408. \t\t\t\tcontent: \"\\f058\" !important;
  409. \t\t\t}
  410. \t\t\t.flash-message i.fa-exclamation-circle::before {
  411. \t\t\t\tcontent: \"\\f06a\" !important;
  412. \t\t\t}
  413. \t\t\t.flash-message i.fa-exclamation-triangle::before {
  414. \t\t\t\tcontent: \"\\f071\" !important;
  415. \t\t\t}
  416. \t\t\t.flash-message i.fa-info-circle::before {
  417. \t\t\t\tcontent: \"\\f05a\" !important;
  418. \t\t\t}
  419. \t\t\t.flash-message:hover {
  420. \t\t\t\tbox-shadow: 0 6px 20px rgba(0, 0, 0, 0.2) !important;
  421. \t\t\t\ttransform: translateY(-2px);
  422. \t\t\t}
  423. \t\t\t.flash-message::before {
  424. \t\t\t\tcontent: '';
  425. \t\t\t\tposition: absolute;
  426. \t\t\t\tleft: 0;
  427. \t\t\t\ttop: 0;
  428. \t\t\t\tbottom: 0;
  429. \t\t\t\twidth: 5px;
  430. \t\t\t\tbackground: linear-gradient(180deg, currentColor 0%, rgba(255,255,255,0.3) 100%);
  431. \t\t\t\tborder-radius: 12px 0 0 12px;
  432. \t\t\t}
  433. \t\t\t.flash-message.alert-success {
  434. \t\t\t\tbackground: linear-gradient(135deg, #d4edda 0%, #c3e6cb 100%) !important;
  435. \t\t\t\tcolor: #155724 !important;
  436. \t\t\t\tborder-left: 5px solid #28a745 !important;
  437. \t\t\t}
  438. \t\t\t.flash-message.alert-success i.fa {
  439. \t\t\t\tcolor: #28a745 !important;
  440. \t\t\t\tfont-size: 1.3rem !important;
  441. \t\t\t\tdisplay: inline-block !important;
  442. \t\t\t\tmargin-right: 8px;
  443. \t\t\t\tvertical-align: middle;
  444. \t\t\t}
  445. \t\t\t.flash-message.alert-danger {
  446. \t\t\t\tbackground: linear-gradient(135deg, #f8d7da 0%, #f5c6cb 100%) !important;
  447. \t\t\t\tcolor: #721c24 !important;
  448. \t\t\t\tborder-left: 5px solid #dc3545 !important;
  449. \t\t\t}
  450. \t\t\t.flash-message.alert-danger i.fa {
  451. \t\t\t\tcolor: #dc3545 !important;
  452. \t\t\t\tfont-size: 1.3rem !important;
  453. \t\t\t\tdisplay: inline-block !important;
  454. \t\t\t\tmargin-right: 8px;
  455. \t\t\t\tvertical-align: middle;
  456. \t\t\t}
  457. \t\t\t.flash-message.alert-warning {
  458. \t\t\t\tbackground: linear-gradient(135deg, #fff3cd 0%, #ffeaa7 100%) !important;
  459. \t\t\t\tcolor: #856404 !important;
  460. \t\t\t\tborder-left: 5px solid #ffc107 !important;
  461. \t\t\t}
  462. \t\t\t.flash-message.alert-warning i.fa {
  463. \t\t\t\tcolor: #ffa200 !important;
  464. \t\t\t\tfont-size: 1.3rem !important;
  465. \t\t\t\tdisplay: inline-block !important;
  466. \t\t\t\tmargin-right: 8px;
  467. \t\t\t\tvertical-align: middle;
  468. \t\t\t}
  469. \t\t\t.flash-message.alert-info {
  470. \t\t\t\tbackground: linear-gradient(135deg, #d1ecf1 0%, #bee5eb 100%) !important;
  471. \t\t\t\tcolor: #0c5460 !important;
  472. \t\t\t\tborder-left: 5px solid #17a2b8 !important;
  473. \t\t\t}
  474. \t\t\t.flash-message.alert-info i.fa {
  475. \t\t\t\tcolor: #17a2b8 !important;
  476. \t\t\t\tfont-size: 1.3rem !important;
  477. \t\t\t\tdisplay: inline-block !important;
  478. \t\t\t\tmargin-right: 8px;
  479. \t\t\t\tvertical-align: middle;
  480. \t\t\t}
  481. \t\t\t.flash-message strong {
  482. \t\t\t\tflex: 1;
  483. \t\t\t\tfont-weight: 600;
  484. \t\t\t\tfont-size: 0.95rem;
  485. \t\t\t\tline-height: 1.5;
  486. \t\t\t}
  487. \t\t\t.flash-message .btn-close {
  488. \t\t\t\topacity: 0.7;
  489. \t\t\t\tpadding: 8px !important;
  490. \t\t\t\tmargin: -8px -8px -8px auto !important;
  491. \t\t\t\ttransition: all 0.2s ease;
  492. \t\t\t\tborder-radius: 50% !important;
  493. \t\t\t\tbackground: rgba(0, 0, 0, 0.05) !important;
  494. \t\t\t\twidth: 32px !important;
  495. \t\t\t\theight: 32px !important;
  496. \t\t\t\tdisplay: flex !important;
  497. \t\t\t\talign-items: center !important;
  498. \t\t\t\tjustify-content: center !important;
  499. \t\t\t\tborder: none !important;
  500. \t\t\t\tcursor: pointer !important;
  501. \t\t\t\tposition: relative !important;
  502. \t\t\t}
  503. \t\t\t/* Ajouter une icône X visible dans le bouton */
  504. \t\t\t.flash-message .btn-close::before {
  505. \t\t\t\tcontent: '×' !important;
  506. \t\t\t\tfont-size: 24px !important;
  507. \t\t\t\tline-height: 1 !important;
  508. \t\t\t\tcolor: currentColor !important;
  509. \t\t\t\tfont-weight: bold !important;
  510. \t\t\t\tdisplay: block !important;
  511. \t\t\t\tposition: absolute !important;
  512. \t\t\t\ttop: 50% !important;
  513. \t\t\t\tleft: 50% !important;
  514. \t\t\t\ttransform: translate(-50%, -50%) !important;
  515. \t\t\t}
  516. \t\t\t.flash-message .btn-close:hover {
  517. \t\t\t\topacity: 1 !important;
  518. \t\t\t\tbackground: rgba(0, 0, 0, 0.15) !important;
  519. \t\t\t\ttransform: rotate(90deg) !important;
  520. \t\t\t}
  521. \t\t\t.flash-message .btn-close:hover::before {
  522. \t\t\t\ttransform: translate(-50%, -50%) rotate(-90deg) !important;
  523. \t\t\t}
  524. \t\t\t@keyframes slideInDownFlash {
  525. \t\t\t\tfrom {
  526. \t\t\t\t\topacity: 0;
  527. \t\t\t\t\ttransform: translateY(-30px) scale(0.95);
  528. \t\t\t\t}
  529. \t\t\t\tto {
  530. \t\t\t\t\topacity: 1;
  531. \t\t\t\t\ttransform: translateY(0) scale(1);
  532. \t\t\t\t}
  533. \t\t\t}
  534. \t\t\t#flash-messages-container {
  535. \t\t\t\tmargin-top: 20px;
  536. \t\t\t\tmargin-bottom: 0;
  537. \t\t\t}
  538. \t\t\t@media(max-width: 768px) {
  539. \t\t\t\t.flash-message {
  540. \t\t\t\t\tpadding: 14px 16px !important;
  541. \t\t\t\t\tfont-size: 0.9rem;
  542. \t\t\t\t}
  543. \t\t\t\t.flash-message i {
  544. \t\t\t\t\tfont-size: 1.2rem !important;
  545. \t\t\t\t}
  546. \t\t\t}
  547. \t\t\t/* Styles pour l'icône de comparaison */
  548. \t\t\t.comparison-icon {
  549. \t\t\t\tposition: relative;
  550. \t\t\t\tdisplay: inline-block;
  551. \t\t\t\tcolor: #333;
  552. \t\t\t\ttext-decoration: none;
  553. \t\t\t\ttransition: all 0.3s ease;
  554. \t\t\t}
  555. \t\t\t.comparison-icon:hover {
  556. \t\t\t\tcolor: #ffa200;
  557. \t\t\t}
  558. \t\t\t.comparison-badge {
  559. \t\t\t\tposition: absolute;
  560. \t\t\t\ttop: -4px;
  561. \t\t\t\tright: -2px;
  562. \t\t\t\tbackground: #095ad3 !important;
  563. \t\t\t\tcolor: white !important;
  564. \t\t\t\tborder-radius: 50%;
  565. \t\t\t\twidth: 18px;
  566. \t\t\t\theight: 18px;
  567. \t\t\t\tfont-size: 8px !important;
  568. \t\t\t\tdisplay: flex !important;
  569. \t\t\t\talign-items: center !important;
  570. \t\t\t\tjustify-content: center !important;
  571. \t\t\t\tfont-weight: bold !important;
  572. \t\t\t\tanimation: pulse 2s infinite;
  573. \t\t\t\tz-index: 10;
  574. \t\t\t\tline-height: 1 !important;
  575. \t\t\t}
  576. \t\t\t/* Correction de l'alignement des boutons actifs dans prd-bottom */
  577. \t\t\t/* Ne s'applique qu'aux boutons actifs pour éviter de casser le comportement hover */
  578. \t\t\t.single-product .product-details .prd-bottom .social-info.active {
  579. \t\t\t\tvertical-align: middle !important;
  580. \t\t\t\tposition: relative !important;
  581. \t\t\t\ttop: 0 !important;
  582. \t\t\t\ttransform: none !important;
  583. \t\t\t\tmargin: 0 !important;
  584. \t\t\t\tpadding: 0 !important;
  585. \t\t\t\tline-height: normal !important;
  586. \t\t\t\twidth: 35px !important;
  587. \t\t\t\theight: auto !important;
  588. \t\t\t\tmin-height: auto !important;
  589. \t\t\t\tmax-height: none !important;
  590. \t\t\t}
  591. \t\t\t.single-product .product-details .prd-bottom .social-info.wishlist-btn.active,
  592. \t\t\t.single-product .product-details .prd-bottom .social-info.comparison-btn.active {
  593. \t\t\t\tvertical-align: middle !important;
  594. \t\t\t\tposition: relative !important;
  595. \t\t\t\ttop: 0 !important;
  596. \t\t\t\ttransform: none !important;
  597. \t\t\t\tmargin: 0 !important;
  598. \t\t\t\tpadding: 0 !important;
  599. \t\t\t\tline-height: normal !important;
  600. \t\t\t\twidth: 35px !important;
  601. \t\t\t\theight: auto !important;
  602. \t\t\t\tmin-height: auto !important;
  603. \t\t\t\tmax-height: none !important;
  604. \t\t\t}
  605. \t\t\t.single-product .product-details .prd-bottom .social-info.active .hover-text {
  606. \t\t\t\tmargin: 0 !important;
  607. \t\t\t\tpadding: 0 !important;
  608. \t\t\t\tline-height: normal !important;
  609. \t\t\t\tposition: absolute !important;
  610. \t\t\t\ttop: 0 !important;
  611. \t\t\t\tbackground: #ffa200 !important;
  612. \t\t\t\tleft: -40px !important;
  613. \t\t\t}
  614. \t\t\t/* S'assurer qu'aucune marge supplémentaire n'est ajoutée quand un bouton est actif */
  615. \t\t\t.single-product .product-details .prd-bottom .social-info.active span,
  616. \t\t\t.single-product .product-details .prd-bottom .social-info.active p {
  617. \t\t\t\tmargin: 0 !important;
  618. \t\t\t\tpadding: 0 !important;
  619. \t\t\t}
  620. \t\t\t/* Empêcher le hover de changer la largeur quand le bouton est actif */
  621. \t\t\t.single-product .product-details .prd-bottom .social-info.active:hover {
  622. \t\t\t\twidth: 35px !important;
  623. \t\t\t}
  624. \t\t\t.comparison-icon:hover .comparison-badge {
  625. \t\t\t\tanimation: none;
  626. \t\t\t}
  627. \t\t\t/* Styles pour les mega-menus - style comme la barre de recherche */
  628. \t\t\t.mega-menu {
  629. \t\t\t\twidth: 100%;
  630. \t\t\t\tmax-width: 1200px;
  631. \t\t\t\tleft: 50%;
  632. \t\t\t\ttransform: translateX(-50%);
  633. \t\t\t\tpadding: 25px;
  634. \t\t\t\tborder-radius: 12px;
  635. \t\t\t\tbox-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
  636. \t\t\t\tborder: none;
  637. \t\t\t\tbackground: white;
  638. \t\t\t\tdisplay: none;
  639. \t\t\t\tposition: absolute;
  640. \t\t\t\ttop: 100%;
  641. \t\t\t\tz-index: 9999 !important;
  642. \t\t\t\tmargin-top: 10px;
  643. \t\t\t\topacity: 0;
  644. \t\t\t\tvisibility: hidden;
  645. \t\t\t\ttransition: opacity 0.3s ease, visibility 0.3s ease, transform 0.3s ease;
  646. \t\t\t}
  647. \t\t\t.mega-menu.active {
  648. \t\t\t\tdisplay: block;
  649. \t\t\t\topacity: 1;
  650. \t\t\t\tvisibility: visible;
  651. \t\t\t\ttransform: translateX(-50%) translateY(0);
  652. \t\t\t}
  653. \t\t\t.nav-item.dropdown {
  654. \t\t\t\tposition: relative !important;
  655. \t\t\t}
  656. \t\t\t@media(min-width: 768px) {
  657. \t\t\t\t.nav-item.dropdown {
  658. \t\t\t\t\tposition: relative !important;
  659. \t\t\t\t}
  660. \t\t\t\t.mega-menu {
  661. \t\t\t\t\tposition: absolute !important;
  662. \t\t\t\t\tleft: 50% !important;
  663. \t\t\t\t\ttransform: translateX(-50%) !important;
  664. \t\t\t\t\twidth: auto !important;
  665. \t\t\t\t\tmin-width: 600px !important;
  666. \t\t\t\t}
  667. \t\t\t}
  668. \t\t\t/* Correction supplémentaire pour l'affichage sur la page d'accueil */
  669. \t\t\tbody.home .nav-item.dropdown,
  670. \t\t\t.nav-item.dropdown {
  671. \t\t\t\tposition: relative !important;
  672. \t\t\t}
  673. \t\t\tbody.home .mega-menu,
  674. \t\t\t.mega-menu {
  675. \t\t\t\tposition: absolute !important;
  676. \t\t\t\tleft: 50% !important;
  677. \t\t\t\ttransform: translateX(-50%) translateY(0) !important;
  678. \t\t\t\twidth: auto !important;
  679. \t\t\t\tmin-width: 600px !important;
  680. \t\t\t\tmax-width: 90% !important;
  681. \t\t\t\ttop: 100% !important;
  682. \t\t\t\tmargin-top: 10px !important;
  683. \t\t\t}
  684. \t\t\t/* Assurer que les mega-menus sont toujours visibles au survol */
  685. \t\t\t.nav-item.dropdown:hover .mega-menu {
  686. \t\t\t\topacity: 1 !important;
  687. \t\t\t\tvisibility: visible !important;
  688. \t\t\t\tdisplay: block !important;
  689. \t\t\t\ttransform: translateX(-50%) translateY(0) !important;
  690. \t\t\t}
  691. \t\t\t.mega-menu .dropdown-item {
  692. \t\t\t\tpadding: 0;
  693. \t\t\t\tborder: none;
  694. \t\t\t}
  695. \t\t\t.mega-menu .dropdown-header {
  696. \t\t\t\tfont-weight: 700;
  697. \t\t\t\tcolor: #2c3e50;
  698. \t\t\t\tmargin-bottom: 18px;
  699. \t\t\t\tpadding-bottom: 10px;
  700. \t\t\t\tborder-bottom: 3px solid #3498db;
  701. \t\t\t\tfont-size: 16px;
  702. \t\t\t\ttext-transform: uppercase;
  703. \t\t\t\tletter-spacing: 0.5px;
  704. \t\t\t}
  705. \t\t\t.mega-menu .dropdown-item a {
  706. \t\t\t\tdisplay: block;
  707. \t\t\t\tpadding: 10px 15px;
  708. \t\t\t\tcolor: #555;
  709. \t\t\t\ttext-decoration: none;
  710. \t\t\t\tborder-radius: 6px;
  711. \t\t\t\ttransition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  712. \t\t\t\tposition: relative;
  713. \t\t\t\toverflow: hidden;
  714. \t\t\t}
  715. \t\t\t.mega-menu .dropdown-item a::before {
  716. \t\t\t\tcontent: '';
  717. \t\t\t\tposition: absolute;
  718. \t\t\t\ttop: 0;
  719. \t\t\t\tleft: -100%;
  720. \t\t\t\twidth: 100%;
  721. \t\t\t\theight: 100%;
  722. \t\t\t\tbackground: linear-gradient(90deg, transparent, rgba(52, 152, 219, 0.1), transparent);
  723. \t\t\t\ttransition: left 0.5s;
  724. \t\t\t}
  725. \t\t\t.mega-menu .dropdown-item a:hover::before {
  726. \t\t\t\tleft: 100%;
  727. \t\t\t}
  728. \t\t\t.mega-menu .dropdown-item a:hover {
  729. \t\t\t\tbackground: linear-gradient(135deg, #f8f9fa, #e3f2fd);
  730. \t\t\t\tcolor: #2980b9;
  731. \t\t\t\ttransform: translateX(8px);
  732. \t\t\t\tbox-shadow: 0 2px 8px rgba(52, 152, 219, 0.2);
  733. \t\t\t}
  734. \t\t\t.mega-menu .dropdown-item a i {
  735. \t\t\t\twidth: 22px;
  736. \t\t\t\ttext-align: center;
  737. \t\t\t\tmargin-right: 8px;
  738. \t\t\t\tcolor: #3498db;
  739. \t\t\t\ttransition: color 0.3s ease;
  740. \t\t\t}
  741. \t\t\t.mega-menu .dropdown-item a:hover i {
  742. \t\t\t\tcolor: #2980b9;
  743. \t\t\t}
  744. \t\t\t/* Animation d'apparition améliorée */
  745. \t\t\t@keyframes slideInDown {
  746. \t\t\t\tfrom {
  747. \t\t\t\t\topacity: 0;
  748. \t\t\t\t\ttransform: translateY(-20px);
  749. \t\t\t\t}
  750. \t\t\t\tto {
  751. \t\t\t\t\topacity: 1;
  752. \t\t\t\t\ttransform: translateY(0);
  753. \t\t\t\t}
  754. \t\t\t}
  755. \t\t\t.mega-menu {
  756. \t\t\t\tanimation: slideInDown 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  757. \t\t\t}
  758. \t\t\t/* Effet de survol sur le lien principal */
  759. \t\t\t.nav-item.dropdown .nav-link {
  760. \t\t\t\tposition: relative;
  761. \t\t\t\ttransition: all 0.3s ease;
  762. \t\t\t}
  763. \t\t\t.nav-item.dropdown .nav-link::after {
  764. \t\t\t\tcontent: '';
  765. \t\t\t\tposition: absolute;
  766. \t\t\t\tbottom: -2px;
  767. \t\t\t\tleft: 50%;
  768. \t\t\t\twidth: 0;
  769. \t\t\t\theight: 2px;
  770. \t\t\t\tbackground: linear-gradient(90deg, #3498db, #2980b9);
  771. \t\t\t\ttransition: all 0.3s ease;
  772. \t\t\t\ttransform: translateX(-50%);
  773. \t\t\t}
  774. \t\t\t.nav-item.dropdown:hover .nav-link::after {
  775. \t\t\t\twidth: 100%;
  776. \t\t\t}
  777. \t\t\t.nav-item.dropdown:hover .nav-link {
  778. \t\t\t\tcolor: #2980b9;
  779. \t\t\t}
  780. \t\t\t@keyframes fadeInDown {
  781. \t\t\t\tfrom {
  782. \t\t\t\t\topacity: 0;
  783. \t\t\t\t\ttransform: translateY(-10px);
  784. \t\t\t\t}
  785. \t\t\t\tto {
  786. \t\t\t\t\topacity: 1;
  787. \t\t\t\t\ttransform: translateY(0);
  788. \t\t\t\t}
  789. \t\t\t}
  790. \t\t\t/* Responsive */
  791. \t\t\t@media(max-width: 768px) {
  792. \t\t\t\t.mega-menu {
  793. \t\t\t\t\twidth: 100%;
  794. \t\t\t\t\tleft: 0;
  795. \t\t\t\t\tpadding: 15px;
  796. \t\t\t\t}
  797. \t\t\t\t.mega-menu .row {
  798. \t\t\t\t\tmargin: 0;
  799. \t\t\t\t}
  800. \t\t\t\t.mega-menu .col-md-3 {
  801. \t\t\t\t\tmargin-bottom: 20px;
  802. \t\t\t\t}
  803. \t\t\t}
  804. \t\t\t/* ============================================
  805. \t\t\t.footer-area {
  806. \t\t\t\tbackground: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
  807. \t\t\t\tposition: relative;
  808. \t\t\t\toverflow: hidden;
  809. \t\t\t\tpadding: 50px 0 20px;
  810. \t\t\t}
  811. \t\t\t.footer-pattern {
  812. \t\t\t\tposition: absolute;
  813. \t\t\t\ttop: 0;
  814. \t\t\t\tleft: 0;
  815. \t\t\t\tright: 0;
  816. \t\t\t\tbottom: 0;
  817. \t\t\t\tbackground-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%);
  818. \t\t\t\tpointer-events: none;
  819. \t\t\t}
  820. \t\t\t.footer-area .container {
  821. \t\t\t\tposition: relative;
  822. \t\t\t\tz-index: 1;
  823. \t\t\t}
  824. \t\t\t/* Widgets */
  825. \t\t\t.single-footer-widget {
  826. \t\t\t\tcolor: rgba(255, 255, 255, 0.9);
  827. \t\t\t}
  828. \t\t\t.footer-brand {
  829. \t\t\t\tfont-size: 1.6rem;
  830. \t\t\t\tfont-weight: 700;
  831. \t\t\t\tbackground: linear-gradient(135deg, #ffa200 0%, #e8910a 100%);
  832. \t\t\t\t-webkit-background-clip: text;
  833. \t\t\t\t-webkit-text-fill-color: transparent;
  834. \t\t\t\tbackground-clip: text;
  835. \t\t\t\tmargin-bottom: 12px;
  836. \t\t\t\tdisplay: inline-block;
  837. \t\t\t}
  838. \t\t\t.footer-widget-title {
  839. \t\t\t\tcolor: #fff;
  840. \t\t\t\tfont-size: 1rem;
  841. \t\t\t\tfont-weight: 600;
  842. \t\t\t\tmargin-bottom: 18px;
  843. \t\t\t\tposition: relative;
  844. \t\t\t\tpadding-bottom: 8px;
  845. \t\t\t}
  846. \t\t\t.footer-widget-title::after {
  847. \t\t\t\tcontent: '';
  848. \t\t\t\tposition: absolute;
  849. \t\t\t\tbottom: 0;
  850. \t\t\t\tleft: 0;
  851. \t\t\t\twidth: 40px;
  852. \t\t\t\theight: 3px;
  853. \t\t\t\tbackground: linear-gradient(135deg, #ffa200 0%, #e8910a 100%);
  854. \t\t\t\tborder-radius: 2px;
  855. \t\t\t}
  856. \t\t\t.footer-description {
  857. \t\t\t\tcolor: rgba(255, 255, 255, 0.7);
  858. \t\t\t\tline-height: 1.6;
  859. \t\t\t\tfont-size: 0.9rem;
  860. \t\t\t\tmargin-bottom: 0;
  861. \t\t\t}
  862. \t\t\t/* Liste de liens */
  863. \t\t\t.footer-list {
  864. \t\t\t\tlist-style: none;
  865. \t\t\t\tpadding: 0;
  866. \t\t\t\tmargin: 0;
  867. \t\t\t}
  868. \t\t\t.footer-list li {
  869. \t\t\t\tmargin-bottom: 10px;
  870. \t\t\t}
  871. \t\t\t.footer-list li a {
  872. \t\t\t\tcolor: rgba(255, 255, 255, 0.7);
  873. \t\t\t\ttext-decoration: none;
  874. \t\t\t\ttransition: all 0.3s ease;
  875. \t\t\t\tfont-size: 0.9rem;
  876. \t\t\t\tdisplay: inline-flex;
  877. \t\t\t\talign-items: center;
  878. \t\t\t}
  879. \t\t\t.footer-list li a i {
  880. \t\t\t\tfont-size: 0.8rem;
  881. \t\t\t\topacity: 0.6;
  882. \t\t\t\ttransition: all 0.3s ease;
  883. \t\t\t}
  884. \t\t\t.footer-list li a:hover {
  885. \t\t\t\tcolor: #ffa200;
  886. \t\t\t\ttransform: translateX(5px);
  887. \t\t\t}
  888. \t\t\t.footer-list li a:hover i {
  889. \t\t\t\topacity: 1;
  890. \t\t\t\tcolor: #ffa200;
  891. \t\t\t}
  892. \t\t\t/* Newsletter */
  893. \t\t\t.footer-newsletter-text {
  894. \t\t\t\tcolor: rgba(255, 255, 255, 0.7);
  895. \t\t\t\tfont-size: 0.85rem;
  896. \t\t\t\tmargin-bottom: 15px;
  897. \t\t\t\tline-height: 1.5;
  898. \t\t\t}
  899. \t\t\t.footer-newsletter-wrapper {
  900. \t\t\t\tmargin-bottom: 15px;
  901. \t\t\t}
  902. \t\t\t.newsletter-input-group {
  903. \t\t\t\tdisplay: flex;
  904. \t\t\t\talign-items: center;
  905. \t\t\t\tbackground: rgba(255, 255, 255, 0.08);
  906. \t\t\t\tborder-radius: 30px;
  907. \t\t\t\tpadding: 4px 4px 4px 15px;
  908. \t\t\t\tbackdrop-filter: blur(10px);
  909. \t\t\t\tborder: 1px solid rgba(255, 255, 255, 0.15);
  910. \t\t\t\ttransition: all 0.3s ease;
  911. \t\t\t\tgap: 8px;
  912. \t\t\t}
  913. \t\t\t.newsletter-input-group:focus-within {
  914. \t\t\t\tbackground: rgba(255, 255, 255, 0.12);
  915. \t\t\t\tborder-color: rgba(255, 162, 0, 0.6);
  916. \t\t\t\tbox-shadow: 0 0 0 2px rgba(255, 162, 0, 0.15);
  917. \t\t\t}
  918. \t\t\t.newsletter-icon {
  919. \t\t\t\tcolor: rgba(255, 255, 255, 0.5);
  920. \t\t\t\tfont-size: 0.9rem;
  921. \t\t\t\tflex-shrink: 0;
  922. \t\t\t}
  923. \t\t\t.newsletter-input-group:focus-within .newsletter-icon {
  924. \t\t\t\tcolor: #ffa200;
  925. \t\t\t}
  926. \t\t\t.newsletter-input {
  927. \t\t\t\tflex: 1;
  928. \t\t\t\tbackground: transparent;
  929. \t\t\t\tborder: none;
  930. \t\t\t\tcolor: #fff;
  931. \t\t\t\tpadding: 10px 8px;
  932. \t\t\t\tfont-size: 0.9rem;
  933. \t\t\t\tmin-width: 0;
  934. \t\t\t}
  935. \t\t\t.newsletter-input::placeholder {
  936. \t\t\t\tcolor: rgba(255, 255, 255, 0.4);
  937. \t\t\t\tfont-size: 0.85rem;
  938. \t\t\t}
  939. \t\t\t.newsletter-input:focus {
  940. \t\t\t\toutline: none;
  941. \t\t\t\tbox-shadow: none;
  942. \t\t\t}
  943. \t\t\t.newsletter-btn {
  944. \t\t\t\tbackground: linear-gradient(135deg, #ffa200 0%, #e8910a 100%);
  945. \t\t\t\tborder: none;
  946. \t\t\t\tcolor: white;
  947. \t\t\t\twidth: 42px;
  948. \t\t\t\theight: 42px;
  949. \t\t\t\tmin-width: 42px;
  950. \t\t\t\tmin-height: 42px;
  951. \t\t\t\tborder-radius: 50%;
  952. \t\t\t\tdisplay: flex;
  953. \t\t\t\talign-items: center;
  954. \t\t\t\tjustify-content: center;
  955. \t\t\t\tcursor: pointer;
  956. \t\t\t\ttransition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  957. \t\t\t\tflex-shrink: 0;
  958. \t\t\t\tbox-shadow: 0 4px 15px rgba(255, 162, 0, 0.4), 0 0 0 0 rgba(255, 162, 0, 0.4);
  959. \t\t\t\tfont-size: 0.9rem;
  960. \t\t\t\tposition: relative;
  961. \t\t\t\toverflow: hidden;
  962. \t\t\t}
  963. \t\t\t.newsletter-btn::before {
  964. \t\t\t\tcontent: '';
  965. \t\t\t\tposition: absolute;
  966. \t\t\t\ttop: 50%;
  967. \t\t\t\tleft: 50%;
  968. \t\t\t\twidth: 0;
  969. \t\t\t\theight: 0;
  970. \t\t\t\tborder-radius: 50%;
  971. \t\t\t\tbackground: rgba(255, 255, 255, 0.3);
  972. \t\t\t\ttransform: translate(-50%, -50%);
  973. \t\t\t\ttransition: width 0.6s ease, height 0.6s ease;
  974. \t\t\t}
  975. \t\t\t.newsletter-btn:hover::before {
  976. \t\t\t\twidth: 100%;
  977. \t\t\t\theight: 100%;
  978. \t\t\t}
  979. \t\t\t.newsletter-btn:hover {
  980. \t\t\t\ttransform: translateX(3px) scale(1.05);
  981. \t\t\t\tbox-shadow: 0 6px 20px rgba(255, 162, 0, 0.5), 0 0 0 8px rgba(255, 162, 0, 0.1);
  982. \t\t\t\tbackground: linear-gradient(135deg, #e8910a 0%, #ffa200 100%);
  983. \t\t\t}
  984. \t\t\t.newsletter-btn:active {
  985. \t\t\t\ttransform: translateX(3px) scale(0.98);
  986. \t\t\t\tbox-shadow: 0 3px 10px rgba(255, 162, 0, 0.4);
  987. \t\t\t}
  988. \t\t\t.newsletter-btn:focus {
  989. \t\t\t\toutline: none;
  990. \t\t\t\tbox-shadow: 0 4px 15px rgba(255, 162, 0, 0.4), 0 0 0 3px rgba(255, 162, 0, 0.3);
  991. \t\t\t}
  992. \t\t\t.newsletter-btn-icon,
  993. \t\t\t.newsletter-btn-loader {
  994. \t\t\t\tposition: relative;
  995. \t\t\t\tz-index: 2;
  996. \t\t\t\tdisplay: flex;
  997. \t\t\t\talign-items: center;
  998. \t\t\t\tjustify-content: center;
  999. \t\t\t\ttransition: all 0.3s ease;
  1000. \t\t\t}
  1001. \t\t\t.newsletter-btn:hover .newsletter-btn-icon {
  1002. \t\t\t\ttransform: translateX(2px) rotate(-10deg);
  1003. \t\t\t}
  1004. \t\t\t.newsletter-btn.loading .newsletter-btn-icon {
  1005. \t\t\t\topacity: 0;
  1006. \t\t\t\ttransform: scale(0);
  1007. \t\t\t}
  1008. \t\t\t.newsletter-btn.loading .newsletter-btn-loader {
  1009. \t\t\t\tdisplay: flex !important;
  1010. \t\t\t}
  1011. \t\t\t.newsletter-btn.success {
  1012. \t\t\t\tbackground: linear-gradient(135deg, #28a745 0%, #20c997 100%);
  1013. \t\t\t\tbox-shadow: 0 4px 15px rgba(40, 167, 69, 0.4);
  1014. \t\t\t}
  1015. \t\t\t.newsletter-btn.success .newsletter-btn-icon i::before {
  1016. \t\t\t\tcontent: \"\\f00c\";
  1017. \t\t\t}
  1018. \t\t\t/* Trust badges */
  1019. \t\t\t.footer-trust-badges {
  1020. \t\t\t\tdisplay: flex;
  1021. \t\t\t\tflex-direction: row;
  1022. \t\t\t\tgap: 15px;
  1023. \t\t\t\tflex-wrap: wrap;
  1024. \t\t\t}
  1025. \t\t\t.trust-item {
  1026. \t\t\t\tdisplay: flex;
  1027. \t\t\t\talign-items: center;
  1028. \t\t\t\tgap: 6px;
  1029. \t\t\t\tcolor: rgba(255, 255, 255, 0.6);
  1030. \t\t\t\tfont-size: 0.8rem;
  1031. \t\t\t}
  1032. \t\t\t.trust-item i {
  1033. \t\t\t\tcolor: #ffa200;
  1034. \t\t\t\tfont-size: 0.9rem;
  1035. \t\t\t}
  1036. \t\t\t/* Social icons */
  1037. \t\t\t.footer-social {
  1038. \t\t\t\tmargin-top: 0 !important;
  1039. \t\t\t\tposition: relative !important;
  1040. \t\t\t\twidth: 100% !important;
  1041. \t\t\t\tclear: both !important;
  1042. \t\t\t\tfloat: none !important;
  1043. \t\t\t}
  1044. \t\t\t.footer-social h6 {
  1045. \t\t\t\tcolor: #fff;
  1046. \t\t\t\tfont-size: 0.95rem;
  1047. \t\t\t\tfont-weight: 600;
  1048. \t\t\t\tmargin-bottom: 12px !important;
  1049. \t\t\t\tdisplay: block !important;
  1050. \t\t\t\twidth: 100% !important;
  1051. \t\t\t\tposition: relative !important;
  1052. \t\t\t\tclear: both !important;
  1053. \t\t\t\tfloat: none !important;
  1054. \t\t\t}
  1055. \t\t\t.footer-social-icons {
  1056. \t\t\t\tdisplay: flex !important;
  1057. \t\t\t\tgap: 12px !important;
  1058. \t\t\t\tflex-wrap: wrap !important;
  1059. \t\t\t\talign-items: center !important;
  1060. \t\t\t\tjustify-content: flex-start !important;
  1061. \t\t\t\twidth: 100% !important;
  1062. \t\t\t\tposition: relative !important;
  1063. \t\t\t\tclear: both !important;
  1064. \t\t\t\tfloat: none !important;
  1065. \t\t\t\tmargin: 0 !important;
  1066. \t\t\t\tpadding: 0 !important;
  1067. \t\t\t}
  1068. \t\t\t.social-icon {
  1069. \t\t\t\twidth: 38px !important;
  1070. \t\t\t\theight: 38px !important;
  1071. \t\t\t\tmin-width: 38px !important;
  1072. \t\t\t\tmin-height: 38px !important;
  1073. \t\t\t\tdisplay: inline-flex !important;
  1074. \t\t\t\talign-items: center !important;
  1075. \t\t\t\tjustify-content: center !important;
  1076. \t\t\t\tbackground: rgba(255, 255, 255, 0.1) !important;
  1077. \t\t\t\tborder-radius: 50% !important;
  1078. \t\t\t\tcolor: rgba(255, 255, 255, 0.8) !important;
  1079. \t\t\t\ttext-decoration: none !important;
  1080. \t\t\t\ttransition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
  1081. \t\t\t\tfont-size: 16px !important;
  1082. \t\t\t\tline-height: 1 !important;
  1083. \t\t\t\tbackdrop-filter: blur(10px) !important;
  1084. \t\t\t\tborder: 1px solid rgba(255, 255, 255, 0.1) !important;
  1085. \t\t\t\tflex-shrink: 0 !important;
  1086. \t\t\t\tposition: relative !important;
  1087. \t\t\t\tfloat: none !important;
  1088. \t\t\t\tmargin: 0 !important;
  1089. \t\t\t\tpadding: 0 !important;
  1090. \t\t\t\tvertical-align: middle !important;
  1091. \t\t\t}
  1092. \t\t\t.social-icon i {
  1093. \t\t\t\tfont-size: 16px !important;
  1094. \t\t\t\tline-height: 1 !important;
  1095. \t\t\t\tdisplay: inline-block !important;
  1096. \t\t\t\ttransition: transform 0.3s ease !important;
  1097. \t\t\t\tposition: relative !important;
  1098. \t\t\t\tz-index: 1 !important;
  1099. \t\t\t\tmargin: 0 !important;
  1100. \t\t\t\tpadding: 0 !important;
  1101. \t\t\t}
  1102. \t\t\t.social-icon:hover {
  1103. \t\t\t\tbackground: linear-gradient(135deg, #ffa200 0%, #e8910a 100%) !important;
  1104. \t\t\t\ttransform: translateY(-5px) scale(1.1) !important;
  1105. \t\t\t\tcolor: white !important;
  1106. \t\t\t\tborder-color: transparent !important;
  1107. \t\t\t\tbox-shadow: 0 8px 20px rgba(255, 162, 0, 0.4) !important;
  1108. \t\t\t}
  1109. \t\t\t.social-icon:hover i {
  1110. \t\t\t\ttransform: scale(1.1) !important;
  1111. \t\t\t}
  1112. \t\t\t/* Footer divider */
  1113. \t\t\t.footer-divider {
  1114. \t\t\t\theight: 1px;
  1115. \t\t\t\tbackground: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
  1116. \t\t\t\tmargin: 30px 0 20px;
  1117. \t\t\t}
  1118. \t\t\t/* Footer bottom */
  1119. \t\t\t.footer-bottom {
  1120. \t\t\t\tpadding-top: 15px;
  1121. \t\t\t}
  1122. \t\t\t.footer-text {
  1123. \t\t\t\tcolor: rgba(255, 255, 255, 0.6);
  1124. \t\t\t\tfont-size: 0.9rem;
  1125. \t\t\t\tmargin: 0;
  1126. \t\t\t\ttext-align: center;
  1127. \t\t\t}
  1128. \t\t\t/* Responsive */
  1129. \t\t\t@media(max-width: 991.98px) {
  1130. \t\t\t\t.footer-area {
  1131. \t\t\t\t\tpadding: 40px 0 20px;
  1132. \t\t\t\t}
  1133. \t\t\t\t.single-footer-widget {
  1134. \t\t\t\t\tmargin-bottom: 30px;
  1135. \t\t\t\t}
  1136. \t\t\t\t.footer-social {
  1137. \t\t\t\t\tmargin-top: 15px;
  1138. \t\t\t\t}
  1139. \t\t\t}
  1140. \t\t\t@media(max-width: 767.98px) {
  1141. \t\t\t\t.footer-area {
  1142. \t\t\t\t\tpadding: 35px 0 18px;
  1143. \t\t\t\t}
  1144. \t\t\t\t.footer-brand {
  1145. \t\t\t\t\tfont-size: 1.4rem;
  1146. \t\t\t\t}
  1147. \t\t\t\t.footer-widget-title {
  1148. \t\t\t\t\tfont-size: 0.95rem;
  1149. \t\t\t\t}
  1150. \t\t\t\t.newsletter-input-group {
  1151. \t\t\t\t\tpadding: 3px 3px 3px 12px;
  1152. \t\t\t\t}
  1153. \t\t\t\t.newsletter-input {
  1154. \t\t\t\t\tpadding: 8px 6px;
  1155. \t\t\t\t\tfont-size: 0.85rem;
  1156. \t\t\t\t}
  1157. \t\t\t\t.newsletter-btn {
  1158. \t\t\t\t\twidth: 38px;
  1159. \t\t\t\t\theight: 38px;
  1160. \t\t\t\t\tmin-width: 38px;
  1161. \t\t\t\t\tmin-height: 38px;
  1162. \t\t\t\t\tfont-size: 0.85rem;
  1163. \t\t\t\t}
  1164. \t\t\t\t.footer-trust-badges {
  1165. \t\t\t\t\tflex-direction: row;
  1166. \t\t\t\t\tflex-wrap: wrap;
  1167. \t\t\t\t\tjustify-content: flex-start;
  1168. \t\t\t\t\tgap: 12px;
  1169. \t\t\t\t}
  1170. \t\t\t}
  1171. \t\t\t@media(max-width: 575.98px) {
  1172. \t\t\t\t.footer-area {
  1173. \t\t\t\t\tpadding: 40px 0 20px;
  1174. \t\t\t\t}
  1175. \t\t\t\t.footer-brand {
  1176. \t\t\t\t\tfont-size: 1.3rem;
  1177. \t\t\t\t}
  1178. \t\t\t\t.social-icon {
  1179. \t\t\t\t\twidth: 38px;
  1180. \t\t\t\t\theight: 38px;
  1181. \t\t\t\t\tfont-size: 16px;
  1182. \t\t\t\t}
  1183. \t\t\t\t.social-icon i {
  1184. \t\t\t\t\tfont-size: 16px;
  1185. \t\t\t\t}
  1186. \t\t\t}
  1187. \t\t</style>
  1188. \t\t";
  1189.         // line 1236
  1190.         yield from $this->unwrap()->yieldBlock('stylesheets'$context$blocks);
  1191.         // line 1239
  1192.         yield "
  1193. \t\t<!-- Script pour forcer l'application des styles CSS après chargement -->
  1194. \t\t<script>
  1195. \t\t\tdocument.addEventListener('DOMContentLoaded', function () { // Forcer le masquage du toggle sur grands écrans
  1196. if (window.innerWidth >= 992) {
  1197. const togglers = document.querySelectorAll('.navbar-toggler, .header_area .navbar .navbar-toggler');
  1198. togglers.forEach(function (toggler) {
  1199. if (toggler) {
  1200. toggler.style.display = 'none';
  1201. toggler.style.visibility = 'hidden';
  1202. toggler.style.opacity = '0';
  1203. toggler.style.width = '0';
  1204. toggler.style.height = '0';
  1205. toggler.style.padding = '0';
  1206. toggler.style.margin = '0';
  1207. toggler.style.border = 'none';
  1208. toggler.style.position = 'absolute';
  1209. toggler.style.left = '-9999px';
  1210. }
  1211. });
  1212. const iconBars = document.querySelectorAll('.navbar-toggler .icon-bar, .header_area .navbar .navbar-toggler .icon-bar, .navbar-toggler-icon');
  1213. iconBars.forEach(function (bar) {
  1214. if (bar) {
  1215. bar.style.display = 'none';
  1216. bar.style.visibility = 'hidden';
  1217. }
  1218. });
  1219. }
  1220. // Alignement des icônes navbar sur mobile
  1221. const navbarRight = document.querySelectorAll('.navbar-right, .header_area .navbar .nav.navbar-nav.navbar-right');
  1222. navbarRight.forEach(function (nav) {
  1223. if (nav && window.innerWidth<= 991.98) {
  1224.                     // Mobile: colonne avec icônes alignées horizontalement
  1225.                     nav.style.display = 'flex';
  1226.                     nav.style.flexDirection = 'column';
  1227.                     nav.style.alignItems = 'center';
  1228.                     nav.style.textAlign = 'center';
  1229.                     
  1230.                     // Le container d'icônes reste horizontal
  1231.                     const iconsContainer = nav.querySelector('.navbar-icons-wrapper');
  1232.                     if (iconsContainer) {
  1233.                         iconsContainer.style.display = 'flex';
  1234.                         iconsContainer.style.flexDirection = 'row';
  1235.                         iconsContainer.style.justifyContent = 'center';
  1236.                     }
  1237.                     
  1238.                     // Le bouton compte en bas
  1239.                     const accountBtn = nav.querySelector('li:last-child');
  1240.                     if (accountBtn) {
  1241.                         accountBtn.style.width = '100%';
  1242.                         accountBtn.style.display = 'flex';
  1243.                         accountBtn.style.justifyContent = 'center';
  1244.                         accountBtn.style.marginTop = '12px';
  1245.                         accountBtn.style.paddingTop = '12px';
  1246.                         accountBtn.style.borderTop = '1px solid #e0e0e0';
  1247.                     }
  1248.                 } else if (nav && window.innerWidth> 991.98) { // Desktop: alignement horizontal normal
  1249. nav.style.display = 'flex';
  1250. nav.style.flexDirection = 'row';
  1251. nav.style.alignItems = 'center';
  1252. nav.style.justifyContent = 'flex-end';
  1253. }
  1254. });
  1255. });
  1256. // Réappliquer lors du redimensionnement
  1257. window.addEventListener('resize', function () {
  1258. if (window.innerWidth >= 992) {
  1259. const togglers = document.querySelectorAll('.navbar-toggler, .header_area .navbar .navbar-toggler');
  1260. togglers.forEach(function (toggler) {
  1261. if (toggler) {
  1262. toggler.style.display = 'none';
  1263. toggler.style.visibility = 'hidden';
  1264. }
  1265. });
  1266. }
  1267. // Réappliquer l'alignement des icônes navbar
  1268. const navbarRight = document.querySelectorAll('.navbar-right, .header_area .navbar .nav.navbar-nav.navbar-right');
  1269. navbarRight.forEach(function (nav) {
  1270. if (nav && window.innerWidth<= 991.98) {
  1271.                     // Mobile: colonne avec icônes alignées horizontalement
  1272.                     nav.style.display = 'flex';
  1273.                     nav.style.flexDirection = 'column';
  1274.                     nav.style.alignItems = 'center';
  1275.                     nav.style.textAlign = 'center';
  1276.                     
  1277.                     // Le container d'icônes reste horizontal
  1278.                     const iconsContainer = nav.querySelector('.navbar-icons-wrapper');
  1279.                     if (iconsContainer) {
  1280.                         iconsContainer.style.display = 'flex';
  1281.                         iconsContainer.style.flexDirection = 'row';
  1282.                         iconsContainer.style.justifyContent = 'center';
  1283.                     }
  1284.                     
  1285.                     const accountBtn = nav.querySelector('li:last-child');
  1286.                     if (accountBtn) {
  1287.                         accountBtn.style.width = '100%';
  1288.                         accountBtn.style.display = 'flex';
  1289.                         accountBtn.style.justifyContent = 'center';
  1290.                         accountBtn.style.marginTop = '12px';
  1291.                         accountBtn.style.paddingTop = '12px';
  1292.                         accountBtn.style.borderTop = '1px solid #e0e0e0';
  1293.                     }
  1294.                 } else if (nav && window.innerWidth> 991.98) { // Desktop: alignement horizontal normal
  1295. nav.style.display = 'flex';
  1296. nav.style.flexDirection = 'row';
  1297. nav.style.alignItems = 'center';
  1298. nav.style.justifyContent = 'flex-end';
  1299. }
  1300. });
  1301. });
  1302. \t\t</script>
  1303. \t</head>
  1304. \t<body
  1305. \t\t";
  1306.         // line 1357
  1307.         if ((array_key_exists("current_menu"$context) && (($context["current_menu"] ?? null) == "listing"))) {
  1308.             yield " id=\"category\" ";
  1309.         }
  1310.         yield ">
  1311. \t\t<!-- Start Header Area -->
  1312. \t\t<header class=\"header_area sticky-header\">
  1313. \t\t\t<div class=\"main_menu\">
  1314. \t\t\t\t<nav class=\"navbar navbar-expand-lg navbar-light main_box\">
  1315. \t\t\t\t\t<div
  1316. \t\t\t\t\t\tclass=\"container\">
  1317. \t\t\t\t\t\t<!-- Brand and toggle get grouped for better mobile display -->
  1318. \t\t\t\t\t\t<a class=\"navbar-brand logo_h\" href=\"";
  1319.         // line 1366
  1320.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_home");
  1321.         yield "\"><img style=\"width: auto;height: 60px\" src=\"";
  1322.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("logo.png"), "html"nulltrue);
  1323.         yield "\" alt=\"\"></a>
  1324. \t\t\t\t\t\t<button class=\"navbar-toggler\" type=\"button\" data-bs-toggle=\"collapse\" data-bs-target=\"#navbarSupportedContent\" aria-controls=\"navbarSupportedContent\" aria-expanded=\"false\" aria-label=\"Toggle navigation\">
  1325. \t\t\t\t\t\t\t<span class=\"icon-bar\"></span>
  1326. \t\t\t\t\t\t\t<span class=\"icon-bar\"></span>
  1327. \t\t\t\t\t\t\t<span class=\"icon-bar\"></span>
  1328. \t\t\t\t\t\t</button>
  1329. \t\t\t\t\t\t<!-- Collect the nav links, forms, and other content for toggling -->
  1330. \t\t\t\t\t\t<div class=\"collapse navbar-collapse offset\" id=\"navbarSupportedContent\">
  1331. \t\t\t\t\t\t\t<ul class=\"nav navbar-nav menu_nav ml-auto\">
  1332. \t\t\t\t\t\t\t\t<li class=\"nav-item ";
  1333.         // line 1375
  1334.         if ((array_key_exists("current_menu"$context) && (($context["current_menu"] ?? null) == " home"))) {
  1335.             yield "active";
  1336.         }
  1337.         yield "\">
  1338. \t\t\t\t\t\t\t\t\t<a class=\"nav-link\" href=\"";
  1339.         // line 1376
  1340.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_home");
  1341.         yield "\">Accueil</a>
  1342. \t\t\t\t\t\t\t\t</li>
  1343. \t\t\t\t\t\t\t\t<li class=\"nav-item ";
  1344.         // line 1378
  1345.         if ((array_key_exists("current_menu"$context) && (($context["current_menu"] ?? null) == " shops"))) {
  1346.             yield "active";
  1347.         }
  1348.         yield "\">
  1349. \t\t\t\t\t\t\t\t\t<a class=\"nav-link\" href=\"";
  1350.         // line 1379
  1351.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_shops_list");
  1352.         yield "\">Boutiques</a>
  1353. \t\t\t\t\t\t\t\t</li>
  1354. \t\t\t\t\t\t\t\t<li class=\"nav-item ";
  1355.         // line 1381
  1356.         if ((array_key_exists("current_menu"$context) && (($context["current_menu"] ?? null) == " listing"))) {
  1357.             yield "active";
  1358.         }
  1359.         yield "\">
  1360. \t\t\t\t\t\t\t\t\t<a class=\"nav-link\" href=\"";
  1361.         // line 1382
  1362.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
  1363.         yield "\">Produits</a>
  1364. \t\t\t\t\t\t\t\t</li>
  1365. \t\t\t\t\t\t\t\t<li class=\"nav-item ";
  1366.         // line 1384
  1367.         if ((array_key_exists("current_menu"$context) && (($context["current_menu"] ?? null) == " contact"))) {
  1368.             yield "active";
  1369.         }
  1370.         yield "\">
  1371. \t\t\t\t\t\t\t\t\t<a class=\"nav-link\" href=\"";
  1372.         // line 1385
  1373.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_contact");
  1374.         yield "\">Contact</a>
  1375. \t\t\t\t\t\t\t\t</li>
  1376. \t\t\t\t\t\t\t</ul>
  1377. \t\t\t\t\t\t\t<ul class=\"nav navbar-nav navbar-right\">
  1378. \t\t\t\t\t\t\t\t<li class=\"nav-item\">
  1379. \t\t\t\t\t\t\t\t\t<div class=\"navbar-icons-wrapper\">
  1380. \t\t\t\t\t\t\t\t\t\t<a href=\"";
  1381.         // line 1391
  1382.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_cart");
  1383.         yield "\" class=\"cart ";
  1384.         if ((array_key_exists("current_menu"$context) && (($context["current_menu"] ?? null) == " cart"))) {
  1385.             yield "active";
  1386.         }
  1387.         yield "\" aria-label=\"Panier\">
  1388. \t\t\t\t\t\t\t\t\t\t\t<span class=\"ti-bag\"></span>
  1389. \t\t\t\t\t\t\t\t\t\t</a>
  1390. \t\t\t\t\t\t\t\t\t\t";
  1391.         // line 1394
  1392.         if ((($tmp CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "user", [], "any"falsefalsefalse1394)) && $tmp instanceof Markup ? (string) $tmp $tmp)) {
  1393.             // line 1395
  1394.             yield "\t\t\t\t\t\t\t\t\t\t\t<a href=\"";
  1395.             yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("notifications_list");
  1396.             yield "\" class=\"notification-icon\" title=\"Notifications\" aria-label=\"Notifications\">
  1397. \t\t\t\t\t\t\t\t\t\t\t\t<span class=\"ti-bell\"></span>
  1398. \t\t\t\t\t\t\t\t\t\t\t\t<span class=\"notification-badge text-white\" id=\"notificationBadge\" style=\"display: none;color: white;\">0</span>
  1399. \t\t\t\t\t\t\t\t\t\t\t</a>
  1400. \t\t\t\t\t\t\t\t\t\t\t<a href=\"";
  1401.             // line 1399
  1402.             yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_product_comparison");
  1403.             yield "\" class=\"comparison-icon\" title=\"Comparaison\" aria-label=\"Comparaison\">
  1404. \t\t\t\t\t\t\t\t\t\t\t\t<span class=\"lnr lnr-sync\"></span>
  1405. \t\t\t\t\t\t\t\t\t\t\t\t<span class=\"comparison-badge text-white\" id=\"comparisonBadge\" style=\"display: none;color: white;\">0</span>
  1406. \t\t\t\t\t\t\t\t\t\t\t</a>
  1407. \t\t\t\t\t\t\t\t\t\t";
  1408.         }
  1409.         // line 1404
  1410.         yield "\t\t\t\t\t\t\t\t\t\t<button class=\"search\" type=\"button\" aria-label=\"Recherche\">
  1411. \t\t\t\t\t\t\t\t\t\t\t<span class=\"lnr lnr-magnifier\" id=\"search\"></span>
  1412. \t\t\t\t\t\t\t\t\t\t</button>
  1413. \t\t\t\t\t\t\t\t\t</div>
  1414. \t\t\t\t\t\t\t\t</li>
  1415. \t\t\t\t\t\t\t\t<li class=\"nav-item\">
  1416. \t\t\t\t\t\t\t\t\t";
  1417.         // line 1410
  1418.         if ((($tmp CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "user", [], "any"falsefalsefalse1410)) && $tmp instanceof Markup ? (string) $tmp $tmp)) {
  1419.             // line 1411
  1420.             yield "\t\t\t\t\t\t\t\t\t\t<a class=\"nav-link btn btn-primary btn-account text-white\" href=\"";
  1421.             yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_account_index");
  1422.             yield "\">
  1423. \t\t\t\t\t\t\t\t\t\t\t<i class=\"ti-user\"></i>
  1424. \t\t\t\t\t\t\t\t\t\t\tMon compte
  1425. \t\t\t\t\t\t\t\t\t\t</a>
  1426. \t\t\t\t\t\t\t\t\t";
  1427.         } else {
  1428.             // line 1416
  1429.             yield "\t\t\t\t\t\t\t\t\t\t<a class=\"nav-link btn btn-primary btn-account text-white\" href=\"";
  1430.             yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_app_login");
  1431.             yield "\">
  1432. \t\t\t\t\t\t\t\t\t\t\t<i class=\"ti-lock\"></i>
  1433. \t\t\t\t\t\t\t\t\t\t\tSe connecter
  1434. \t\t\t\t\t\t\t\t\t\t</a>
  1435. \t\t\t\t\t\t\t\t\t";
  1436.         }
  1437.         // line 1421
  1438.         yield "\t\t\t\t\t\t\t\t</li>
  1439. \t\t\t\t\t\t\t</ul>
  1440. \t\t\t\t\t\t</div>
  1441. \t\t\t\t\t</div>
  1442. \t\t\t\t</nav>
  1443. \t\t\t</div>
  1444. \t\t\t<div class=\"search_input\" id=\"search_input_box\">
  1445. \t\t\t\t<div class=\"container\">
  1446. \t\t\t\t\t<form class=\"d-flex justify-content-between\" id=\"search_form\" action=\"";
  1447.         // line 1429
  1448.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
  1449.         yield "\" method=\"get\">
  1450. \t\t\t\t\t\t<input type=\"text\" class=\"form-control\" id=\"search_input\" name=\"q\" placeholder=\"Rechercher un produit, une boutique, une catégorie...\" autocomplete=\"off\" value=\"";
  1451.         // line 1430
  1452.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env$this->sourceCoreExtension::getAttribute($this->env$this->sourceCoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "request", [], "any"falsefalsefalse1430), "query", [], "any"falsefalsefalse1430), "get", ["q"""], "method"falsefalsefalse1430), "html"nulltrue);
  1453.         yield "\">
  1454. \t\t\t\t\t\t<button type=\"button\" class=\"btn\" id=\"search_submit_btn\">
  1455. \t\t\t\t\t\t\t<i class=\"lnr lnr-magnifier\"></i>
  1456. \t\t\t\t\t\t</button>
  1457. \t\t\t\t\t\t";
  1458.         // line 1434
  1459.         if ((($tmp CoreExtension::getAttribute($this->env$this->sourceCoreExtension::getAttribute($this->env$this->sourceCoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "request", [], "any"falsefalsefalse1434), "query", [], "any"falsefalsefalse1434), "get", ["q"], "method"falsefalsefalse1434)) && $tmp instanceof Markup ? (string) $tmp $tmp)) {
  1460.             // line 1435
  1461.             yield "\t\t\t\t\t\t\t<button type=\"button\" class=\"btn btn-clear-search\" id=\"clear_search_btn\" title=\"Effacer la recherche\">
  1462. \t\t\t\t\t\t\t\t<i class=\"lnr lnr-cross\"></i>
  1463. \t\t\t\t\t\t\t</button>
  1464. \t\t\t\t\t\t";
  1465.         }
  1466.         // line 1439
  1467.         yield "\t\t\t\t\t\t<span class=\"lnr lnr-cross\" id=\"close_search\" title=\"Fermer la recherche\"></span>
  1468. \t\t\t\t\t</form>
  1469. \t\t\t\t\t<div id=\"search_results\" class=\"search-results-container\"></div>
  1470. \t\t\t\t</div>
  1471. \t\t\t</div>
  1472. \t\t</header>
  1473. \t\t<!-- End Header Area -->
  1474. \t\t<!-- Flash Messages -->
  1475. \t\t<div class=\"container mt-3\" id=\"flash-messages-container\" style=\"position: relative; z-index: 1050;\">
  1476. \t\t\t<div class=\"row\">
  1477. \t\t\t\t<div class=\"col-12\">
  1478. \t\t\t\t\t";
  1479.         // line 1451
  1480.         $context['_parent'] = $context;
  1481.         $context['_seq'] = CoreExtension::ensureTraversable(CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "flashes", ["success"], "method"falsefalsefalse1451));
  1482.         foreach ($context['_seq'] as $context["_key"] => $context["message"]) {
  1483.             // line 1452
  1484.             yield "\t\t\t\t\t\t<div class=\"alert alert-success alert-dismissible fade show flash-message\" role=\"alert\">
  1485. \t\t\t\t\t\t\t<i class=\"fa fa-check-circle\"></i>
  1486. \t\t\t\t\t\t\t<strong>";
  1487.             // line 1454
  1488.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($context["message"], "html"nulltrue);
  1489.             yield "</strong>
  1490. \t\t\t\t\t\t\t<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
  1491. \t\t\t\t\t\t</div>
  1492. \t\t\t\t\t";
  1493.         }
  1494.         $_parent $context['_parent'];
  1495.         unset($context['_seq'], $context['_key'], $context['message'], $context['_parent']);
  1496.         $context array_intersect_key($context$_parent) + $_parent;
  1497.         // line 1458
  1498.         yield "
  1499. \t\t\t\t\t";
  1500.         // line 1459
  1501.         $context['_parent'] = $context;
  1502.         $context['_seq'] = CoreExtension::ensureTraversable(CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "flashes", ["error"], "method"falsefalsefalse1459));
  1503.         foreach ($context['_seq'] as $context["_key"] => $context["message"]) {
  1504.             // line 1460
  1505.             yield "\t\t\t\t\t\t<div class=\"alert alert-danger alert-dismissible fade show flash-message\" role=\"alert\">
  1506. \t\t\t\t\t\t\t<i class=\"fa fa-exclamation-circle\"></i>
  1507. \t\t\t\t\t\t\t<strong>";
  1508.             // line 1462
  1509.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($context["message"], "html"nulltrue);
  1510.             yield "</strong>
  1511. \t\t\t\t\t\t\t<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
  1512. \t\t\t\t\t\t</div>
  1513. \t\t\t\t\t";
  1514.         }
  1515.         $_parent $context['_parent'];
  1516.         unset($context['_seq'], $context['_key'], $context['message'], $context['_parent']);
  1517.         $context array_intersect_key($context$_parent) + $_parent;
  1518.         // line 1466
  1519.         yield "
  1520. \t\t\t\t\t";
  1521.         // line 1467
  1522.         $context['_parent'] = $context;
  1523.         $context['_seq'] = CoreExtension::ensureTraversable(CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "flashes", ["warning"], "method"falsefalsefalse1467));
  1524.         foreach ($context['_seq'] as $context["_key"] => $context["message"]) {
  1525.             // line 1468
  1526.             yield "\t\t\t\t\t\t<div class=\"alert alert-warning alert-dismissible fade show flash-message\" role=\"alert\">
  1527. \t\t\t\t\t\t\t<i class=\"fa fa-exclamation-triangle\"></i>
  1528. \t\t\t\t\t\t\t<strong>";
  1529.             // line 1470
  1530.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($context["message"], "html"nulltrue);
  1531.             yield "</strong>
  1532. \t\t\t\t\t\t\t<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
  1533. \t\t\t\t\t\t</div>
  1534. \t\t\t\t\t";
  1535.         }
  1536.         $_parent $context['_parent'];
  1537.         unset($context['_seq'], $context['_key'], $context['message'], $context['_parent']);
  1538.         $context array_intersect_key($context$_parent) + $_parent;
  1539.         // line 1474
  1540.         yield "
  1541. \t\t\t\t\t";
  1542.         // line 1475
  1543.         $context['_parent'] = $context;
  1544.         $context['_seq'] = CoreExtension::ensureTraversable(CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "flashes", ["info"], "method"falsefalsefalse1475));
  1545.         foreach ($context['_seq'] as $context["_key"] => $context["message"]) {
  1546.             // line 1476
  1547.             yield "\t\t\t\t\t\t<div class=\"alert alert-info alert-dismissible fade show flash-message\" role=\"alert\">
  1548. \t\t\t\t\t\t\t<i class=\"fa fa-info-circle\"></i>
  1549. \t\t\t\t\t\t\t<strong>";
  1550.             // line 1478
  1551.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($context["message"], "html"nulltrue);
  1552.             yield "</strong>
  1553. \t\t\t\t\t\t\t<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
  1554. \t\t\t\t\t\t</div>
  1555. \t\t\t\t\t";
  1556.         }
  1557.         $_parent $context['_parent'];
  1558.         unset($context['_seq'], $context['_key'], $context['message'], $context['_parent']);
  1559.         $context array_intersect_key($context$_parent) + $_parent;
  1560.         // line 1482
  1561.         yield "\t\t\t\t</div>
  1562. \t\t\t</div>
  1563. \t\t</div>
  1564. \t\t";
  1565.         // line 1486
  1566.         yield from $this->unwrap()->yieldBlock('body'$context$blocks);
  1567.         // line 1487
  1568.         yield "
  1569. \t\t<!-- start footer Area -->
  1570. \t\t<footer class=\"footer-area section_gap\">
  1571. \t\t\t<div class=\"footer-pattern\"></div>
  1572. \t\t\t<div class=\"container\">
  1573. \t\t\t\t<div class=\"row\">
  1574. \t\t\t\t\t<div class=\"col-lg-3 col-md-6 col-sm-6 mb-4 mb-lg-0\">
  1575. \t\t\t\t\t\t<div class=\"single-footer-widget\">
  1576. \t\t\t\t\t\t\t<div class=\"footer-logo mb-3\">
  1577. \t\t\t\t\t\t\t\t<h4 class=\"footer-brand\">MaketOu</h4>
  1578. \t\t\t\t\t\t\t</div>
  1579. \t\t\t\t\t\t\t<p class=\"footer-description\">
  1580. \t\t\t\t\t\t\t\tMaketOu est la première marketplace haïtienne qui connecte les acheteurs et les vendeurs. 
  1581. \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t                        Nous offrons une plateforme sécurisée et moderne pour le commerce en ligne en Haïti.
  1582. \t\t\t\t\t\t\t</p>
  1583. \t\t\t\t\t\t\t<div class=\"footer-social mt-3\">
  1584. \t\t\t\t\t\t\t\t<h6 class=\"mb-2\">Suivez-nous</h6>
  1585. \t\t\t\t\t\t\t\t<div class=\"footer-social-icons\">
  1586. \t\t\t\t\t\t\t\t\t<a href=\"#\" class=\"social-icon\" aria-label=\"Facebook\" title=\"Facebook\">
  1587. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-facebook\"></i>
  1588. \t\t\t\t\t\t\t\t\t</a>
  1589. \t\t\t\t\t\t\t\t\t<a href=\"#\" class=\"social-icon\" aria-label=\"Twitter\" title=\"Twitter\">
  1590. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-twitter\"></i>
  1591. \t\t\t\t\t\t\t\t\t</a>
  1592. \t\t\t\t\t\t\t\t\t<a href=\"#\" class=\"social-icon\" aria-label=\"Instagram\" title=\"Instagram\">
  1593. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-instagram\"></i>
  1594. \t\t\t\t\t\t\t\t\t</a>
  1595. \t\t\t\t\t\t\t\t\t<a href=\"#\" class=\"social-icon\" aria-label=\"LinkedIn\" title=\"LinkedIn\">
  1596. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-linkedin\"></i>
  1597. \t\t\t\t\t\t\t\t\t</a>
  1598. \t\t\t\t\t\t\t\t</div>
  1599. \t\t\t\t\t\t\t</div>
  1600. \t\t\t\t\t\t</div>
  1601. \t\t\t\t\t</div>
  1602. \t\t\t\t\t<div class=\"col-lg-2 col-md-6 col-sm-6 mb-4 mb-lg-0\">
  1603. \t\t\t\t\t\t<div class=\"single-footer-widget\">
  1604. \t\t\t\t\t\t\t<h6 class=\"footer-widget-title\">Liens rapides</h6>
  1605. \t\t\t\t\t\t\t<ul class=\"footer-list\">
  1606. \t\t\t\t\t\t\t\t<li>
  1607. \t\t\t\t\t\t\t\t\t<a href=\"";
  1608.         // line 1526
  1609.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_home");
  1610.         yield "\">
  1611. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Accueil</a>
  1612. \t\t\t\t\t\t\t\t</li>
  1613. \t\t\t\t\t\t\t\t<li>
  1614. \t\t\t\t\t\t\t\t\t<a href=\"";
  1615.         // line 1530
  1616.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
  1617.         yield "\">
  1618. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Produits</a>
  1619. \t\t\t\t\t\t\t\t</li>
  1620. \t\t\t\t\t\t\t\t<li>
  1621. \t\t\t\t\t\t\t\t\t<a href=\"";
  1622.         // line 1534
  1623.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_shops_list");
  1624.         yield "\">
  1625. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Boutiques</a>
  1626. \t\t\t\t\t\t\t\t</li>
  1627. \t\t\t\t\t\t\t\t";
  1628.         // line 1537
  1629.         if ((($tmp CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "user", [], "any"falsefalsefalse1537)) && $tmp instanceof Markup ? (string) $tmp $tmp)) {
  1630.             // line 1538
  1631.             yield "\t\t\t\t\t\t\t\t\t<li>
  1632. \t\t\t\t\t\t\t\t\t\t<a href=\"";
  1633.             // line 1539
  1634.             yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_account_index");
  1635.             yield "\">
  1636. \t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Mon compte</a>
  1637. \t\t\t\t\t\t\t\t\t</li>
  1638. \t\t\t\t\t\t\t\t";
  1639.         } else {
  1640.             // line 1543
  1641.             yield "\t\t\t\t\t\t\t\t\t<li>
  1642. \t\t\t\t\t\t\t\t\t\t<a href=\"";
  1643.             // line 1544
  1644.             yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_app_login");
  1645.             yield "\">
  1646. \t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Se connecter</a>
  1647. \t\t\t\t\t\t\t\t\t</li>
  1648. \t\t\t\t\t\t\t\t\t<li>
  1649. \t\t\t\t\t\t\t\t\t\t<a href=\"";
  1650.             // line 1548
  1651.             yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_app_register");
  1652.             yield "\">
  1653. \t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;S'inscrire</a>
  1654. \t\t\t\t\t\t\t\t\t</li>
  1655. \t\t\t\t\t\t\t\t";
  1656.         }
  1657.         // line 1552
  1658.         yield "\t\t\t\t\t\t\t</ul>
  1659. \t\t\t\t\t\t</div>
  1660. \t\t\t\t\t</div>
  1661. \t\t\t\t\t<div class=\"col-lg-2 col-md-6 col-sm-6 mb-4 mb-lg-0\">
  1662. \t\t\t\t\t\t<div class=\"single-footer-widget\">
  1663. \t\t\t\t\t\t\t<h6 class=\"footer-widget-title\">Pour les vendeurs</h6>
  1664. \t\t\t\t\t\t\t<ul class=\"footer-list\">
  1665. \t\t\t\t\t\t\t\t<li>
  1666. \t\t\t\t\t\t\t\t\t<a href=\"";
  1667.         // line 1560
  1668.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("seller_index");
  1669.         yield "\">
  1670. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Ouvrir une boutique</a>
  1671. \t\t\t\t\t\t\t\t</li>
  1672. \t\t\t\t\t\t\t\t<li>
  1673. \t\t\t\t\t\t\t\t\t<a href=\"";
  1674.         // line 1564
  1675.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("seller_help_how_to_sell");
  1676.         yield "\">
  1677. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Comment vendre</a>
  1678. \t\t\t\t\t\t\t\t</li>
  1679. \t\t\t\t\t\t\t\t<li>
  1680. \t\t\t\t\t\t\t\t\t<a href=\"";
  1681.         // line 1568
  1682.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("seller_help_pricing");
  1683.         yield "\">
  1684. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Tarifs</a>
  1685. \t\t\t\t\t\t\t\t</li>
  1686. \t\t\t\t\t\t\t\t<li>
  1687. \t\t\t\t\t\t\t\t\t<a href=\"";
  1688.         // line 1572
  1689.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("seller_help_support");
  1690.         yield "\">
  1691. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Support vendeur</a>
  1692. \t\t\t\t\t\t\t\t</li>
  1693. \t\t\t\t\t\t\t</ul>
  1694. \t\t\t\t\t\t</div>
  1695. \t\t\t\t\t</div>
  1696. \t\t\t\t\t<div class=\"col-lg-2 col-md-6 col-sm-6 mb-4 mb-lg-0\">
  1697. \t\t\t\t\t\t<div class=\"single-footer-widget\">
  1698. \t\t\t\t\t\t\t<h6 class=\"footer-widget-title\">Support</h6>
  1699. \t\t\t\t\t\t\t<ul class=\"footer-list\">
  1700. \t\t\t\t\t\t\t\t<li>
  1701. \t\t\t\t\t\t\t\t\t<a href=\"";
  1702.         // line 1583
  1703.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_help");
  1704.         yield "\">
  1705. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Centre d'Aide</a>
  1706. \t\t\t\t\t\t\t\t</li>
  1707. \t\t\t\t\t\t\t\t<li>
  1708. \t\t\t\t\t\t\t\t\t<a href=\"";
  1709.         // line 1587
  1710.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_contact");
  1711.         yield "\">
  1712. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Contactez-nous</a>
  1713. \t\t\t\t\t\t\t\t</li>
  1714. \t\t\t\t\t\t\t\t<li>
  1715. \t\t\t\t\t\t\t\t\t<a href=\"";
  1716.         // line 1591
  1717.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_faq");
  1718.         yield "\">
  1719. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;FAQ</a>
  1720. \t\t\t\t\t\t\t\t</li>
  1721. \t\t\t\t\t\t\t\t<li>
  1722. \t\t\t\t\t\t\t\t\t<a href=\"";
  1723.         // line 1595
  1724.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_privacy");
  1725.         yield "\">
  1726. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Politique de Confidentialité</a>
  1727. \t\t\t\t\t\t\t\t</li>
  1728. \t\t\t\t\t\t\t\t<li>
  1729. \t\t\t\t\t\t\t\t\t<a href=\"";
  1730.         // line 1599
  1731.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_terms");
  1732.         yield "\">
  1733. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Conditions d'Utilisation</a>
  1734. \t\t\t\t\t\t\t\t</li>
  1735. \t\t\t\t\t\t\t</ul>
  1736. \t\t\t\t\t\t</div>
  1737. \t\t\t\t\t</div>
  1738. \t\t\t\t\t<div class=\"col-lg-3 col-md-6 col-sm-6\">
  1739. \t\t\t\t\t\t<div class=\"single-footer-widget\">
  1740. \t\t\t\t\t\t\t<h6 class=\"footer-widget-title\">Newsletter</h6>
  1741. \t\t\t\t\t\t\t<p class=\"footer-newsletter-text\">Restez informé des dernières nouveautés</p>
  1742. \t\t\t\t\t\t\t<div class=\"footer-newsletter-wrapper\" id=\"mc_embed_signup\">
  1743. \t\t\t\t\t\t\t\t<form action=\"";
  1744.         // line 1610
  1745.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_newsletter_subscribe");
  1746.         yield "\" method=\"post\" class=\"footer-newsletter-form\">
  1747. \t\t\t\t\t\t\t\t\t<div class=\"newsletter-input-group\">
  1748. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-envelope newsletter-icon\"></i>
  1749. \t\t\t\t\t\t\t\t\t\t<input class=\"form-control newsletter-input\" name=\"email\" placeholder=\"Votre email\" required type=\"email\">
  1750. \t\t\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"newsletter-btn\" aria-label=\"S'abonner\">
  1751. \t\t\t\t\t\t\t\t\t\t\t<span class=\"newsletter-btn-icon\">
  1752. \t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-paper-plane\" aria-hidden=\"true\"></i>
  1753. \t\t\t\t\t\t\t\t\t\t\t</span>
  1754. \t\t\t\t\t\t\t\t\t\t\t<span class=\"newsletter-btn-loader\" style=\"display: none;\">
  1755. \t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-spinner fa-spin\" aria-hidden=\"true\"></i>
  1756. \t\t\t\t\t\t\t\t\t\t\t</span>
  1757. \t\t\t\t\t\t\t\t\t\t</button>
  1758. \t\t\t\t\t\t\t\t\t</div>
  1759. \t\t\t\t\t\t\t\t</form>
  1760. \t\t\t\t\t\t\t</div>
  1761. \t\t\t\t\t\t\t<div class=\"footer-trust-badges mt-3\">
  1762. \t\t\t\t\t\t\t\t<div class=\"trust-item\">
  1763. \t\t\t\t\t\t\t\t\t<i class=\"fa fa-shield\"></i>
  1764. \t\t\t\t\t\t\t\t\t<span>Paiement sécurisé</span>
  1765. \t\t\t\t\t\t\t\t</div>
  1766. \t\t\t\t\t\t\t\t<div class=\"trust-item\">
  1767. \t\t\t\t\t\t\t\t\t<i class=\"fa fa-truck\"></i>
  1768. \t\t\t\t\t\t\t\t\t<span>Livraison rapide</span>
  1769. \t\t\t\t\t\t\t\t</div>
  1770. \t\t\t\t\t\t\t</div>
  1771. \t\t\t\t\t\t</div>
  1772. \t\t\t\t\t</div>
  1773. \t\t\t\t</div>
  1774. \t\t\t\t<div class=\"footer-divider\"></div>
  1775. \t\t\t\t<div class=\"footer-bottom d-flex justify-content-center align-items-center flex-wrap\">
  1776. \t\t\t\t\t<p class=\"footer-text m-0\">
  1777. \t\t\t\t\t\tCopyright &copy;<script>
  1778. \t\t\t\t\t\t\tdocument.write(new Date().getFullYear());
  1779. \t\t\t\t\t\t</script>
  1780. \t\t\t\t\t\tTous droits réservés | Ce site a été fait avec
  1781. \t\t\t\t\t\t<i class=\"fa fa-heart-o\" aria-hidden=\"true\" style=\"color: #dc3545;\"></i>
  1782. \t\t\t\t\t\tpar
  1783. \t\t\t\t\t\t<a href=\"https://tech.foulgor.com\" target=\"_blank\" style=\"color: #ffa200;\">Foulgor Tech</a>
  1784. \t\t\t\t\t</p>
  1785. \t\t\t\t</div>
  1786. \t\t\t</div>
  1787. \t\t</footer>
  1788. \t\t<style>
  1789. \t\t\t.search-results-container {
  1790. \t\t\t\tposition: absolute;
  1791. \t\t\t\ttop: 100%;
  1792. \t\t\t\tleft: 15px;
  1793. \t\t\t\tright: 15px;
  1794. \t\t\t\tbackground: #fff;
  1795. \t\t\t\tborder: 1px solid #ddd;
  1796. \t\t\t\tborder-top: none;
  1797. \t\t\t\tz-index: 9999;
  1798. \t\t\t\tbox-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  1799. \t\t\t\tmax-height: 400px;
  1800. \t\t\t\toverflow-y: auto;
  1801. \t\t\t\tdisplay: none;
  1802. \t\t\t\tborder-radius: 0 0 4px 4px;
  1803. \t\t\t}
  1804. \t\t\t.search-results-container .list-group-item {
  1805. \t\t\t\tborder-left: none;
  1806. \t\t\t\tborder-right: none;
  1807. \t\t\t\tborder-radius: 0;
  1808. \t\t\t\tcursor: pointer;
  1809. \t\t\t\tpadding: 12px 15px;
  1810. \t\t\t\ttransition: background-color 0.2s ease;
  1811. \t\t\t}
  1812. \t\t\t.search-results-container .list-group-item:hover {
  1813. \t\t\t\tbackground-color: #f8f9fa;
  1814. \t\t\t}
  1815. \t\t\t.search-results-container .list-group-item i {
  1816. \t\t\t\tcolor: #777;
  1817. \t\t\t\tfont-size: 1.2rem;
  1818. \t\t\t}
  1819. \t\t\t/* Ensure container is relative for absolute positioning of results */
  1820. \t\t\t#search_input_box .container {
  1821. \t\t\t\tposition: relative;
  1822. \t\t\t}
  1823. \t\t\t#search_input_box .form-control {
  1824. \t\t\t\tflex: 1;
  1825. \t\t\t\tpadding-right: 10px;
  1826. \t\t\t}
  1827. \t\t\t#search_input_box #search_submit_btn {
  1828. \t\t\t\tbackground: transparent;
  1829. \t\t\t\tborder: 0;
  1830. \t\t\t\tcolor: #fff;
  1831. \t\t\t\tpadding: 0 15px;
  1832. \t\t\t\tcursor: pointer;
  1833. \t\t\t\ttransition: opacity 0.3s ease;
  1834. \t\t\t}
  1835. \t\t\t#search_input_box #search_submit_btn:hover {
  1836. \t\t\t\topacity: 0.8;
  1837. \t\t\t}
  1838. \t\t\t#search_input_box .btn-clear-search {
  1839. \t\t\t\tbackground: transparent;
  1840. \t\t\t\tborder: 0;
  1841. \t\t\t\tcolor: #fff;
  1842. \t\t\t\tpadding: 0 10px;
  1843. \t\t\t\tcursor: pointer;
  1844. \t\t\t\ttransition: opacity 0.3s ease;
  1845. \t\t\t\tdisplay: none;
  1846. \t\t\t}
  1847. \t\t\t#search_input_box .btn-clear-search:hover {
  1848. \t\t\t\topacity: 0.8;
  1849. \t\t\t}
  1850. \t\t\t#search_input_box .btn-clear-search i {
  1851. \t\t\t\tfont-size: 1.1rem;
  1852. \t\t\t}
  1853. \t\t\t#search_input_box form {
  1854. \t\t\t\tposition: relative;
  1855. \t\t\t\talign-items: center;
  1856. \t\t\t}
  1857. \t\t</style>
  1858. \t\t<script>
  1859. \t\t\t// Debounced autocomplete for header search
  1860. (function () {
  1861. const input = document.getElementById('search_input');
  1862. const box = document.getElementById('search_results');
  1863. const searchForm = document.getElementById('search_form');
  1864. const clearSearchBtn = document.getElementById('clear_search_btn');
  1865. const closeSearchBtn = document.getElementById('close_search');
  1866. if (! input || ! box) 
  1867. return;
  1868. // Fonction pour effacer la recherche
  1869. function clearSearch() {
  1870. input.value = '';
  1871. box.style.display = 'none';
  1872. box.innerHTML = '';
  1873. if (clearSearchBtn) {
  1874. clearSearchBtn.style.display = 'none';
  1875. }
  1876. // Si on est sur la page listing, utiliser AJAX pour mettre à jour
  1877. if (typeof currentFilters !== 'undefined') {
  1878. currentFilters.q = '';
  1879. currentFilters.page = 1;
  1880. if (typeof applyFilters === 'function') {
  1881. applyFilters();
  1882. }
  1883. if (typeof updateActiveFilters === 'function') {
  1884. updateActiveFilters();
  1885. }
  1886. } else { // Sinon, rediriger vers la page listing sans recherche
  1887. window.location.href = '";
  1888.         // line 1755
  1889.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
  1890.         yield "';
  1891. }
  1892. }
  1893. // Bouton pour effacer la recherche
  1894. if (clearSearchBtn) {
  1895. clearSearchBtn.addEventListener('click', function (e) {
  1896. e.preventDefault();
  1897. e.stopPropagation();
  1898. clearSearch();
  1899. });
  1900. }
  1901. // Bouton de soumission de recherche
  1902. var searchSubmitBtn = document.getElementById('search_submit_btn');
  1903. if (searchSubmitBtn) {
  1904. searchSubmitBtn.addEventListener('click', function (e) {
  1905. e.preventDefault();
  1906. e.stopPropagation();
  1907. const q = input.value.trim();
  1908. if (q.length === 0) {
  1909. clearSearch();
  1910. return false;
  1911. }
  1912. // Si on est sur la page listing, utiliser AJAX
  1913. if (typeof currentFilters !== 'undefined' && typeof applyFilters === 'function') {
  1914. currentFilters.q = q;
  1915. currentFilters.page = 1;
  1916. applyFilters();
  1917. if (typeof updateActiveFilters === 'function') {
  1918. updateActiveFilters();
  1919. }
  1920. // Fermer la boîte de recherche
  1921. if (closeSearchBtn) {
  1922. closeSearchBtn.click();
  1923. }
  1924. } else { // Sinon, rediriger vers la page listing avec la recherche
  1925. const listingUrl = '";
  1926.         // line 1793
  1927.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
  1928.         yield "' + '?q=' + encodeURIComponent(q);
  1929. window.location.href = listingUrl;
  1930. }
  1931. return false;
  1932. });
  1933. }
  1934. // Gestion du formulaire de recherche
  1935. if (searchForm) {
  1936. searchForm.addEventListener('submit', function (e) {
  1937. e.preventDefault();
  1938. e.stopPropagation();
  1939. const q = input.value.trim();
  1940. if (q.length === 0) {
  1941. clearSearch();
  1942. return;
  1943. }
  1944. // Si on est sur la page listing, utiliser AJAX
  1945. if (typeof currentFilters !== 'undefined' && typeof applyFilters === 'function') {
  1946. currentFilters.q = q;
  1947. currentFilters.page = 1;
  1948. applyFilters();
  1949. if (typeof updateActiveFilters === 'function') {
  1950. updateActiveFilters();
  1951. }
  1952. // Fermer la boîte de recherche
  1953. if (closeSearchBtn) {
  1954. closeSearchBtn.click();
  1955. }
  1956. } else { // Sinon, rediriger vers la page listing avec la recherche
  1957. const listingUrl = '";
  1958.         // line 1824
  1959.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
  1960.         yield "' + '?q=' + encodeURIComponent(q);
  1961. window.location.href = listingUrl;
  1962. }
  1963. return false;
  1964. });
  1965. }
  1966. let t = null;
  1967. input.addEventListener('input', function () {
  1968. const q = input.value.trim();
  1969. clearTimeout(t);
  1970. if (q.length === 0) {
  1971. box.style.display = 'none';
  1972. box.innerHTML = '';
  1973. // Afficher/masquer le bouton clear
  1974. if (clearSearchBtn) {
  1975. clearSearchBtn.style.display = 'none';
  1976. }
  1977. return;
  1978. }
  1979. // Afficher le bouton clear
  1980. if (clearSearchBtn) {
  1981. clearSearchBtn.style.display = 'block';
  1982. }
  1983. t = setTimeout(() => fetchSuggestions(q), 300);
  1984. });
  1985. function fetchSuggestions(q) {
  1986. const url = '";
  1987.         // line 1852
  1988.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_api_search_suggest");
  1989.         yield "' + '?q=' + encodeURIComponent(q);
  1990. fetch(url).then(r => r.json()).then(data => {
  1991. if (!data.success) {
  1992. box.style.display = 'none';
  1993. return;
  1994. }
  1995. renderSuggestions(data.results || []);
  1996. }).catch(() => {
  1997. box.style.display = 'none';
  1998. });
  1999. }
  2000. function renderSuggestions(items) {
  2001. if (! items.length) {
  2002. box.style.display = 'none';
  2003. box.innerHTML = '';
  2004. return;
  2005. }
  2006. box.innerHTML = items.map(it => suggestionItem(it)).join('');
  2007. box.style.display = 'block';
  2008. }
  2009. function suggestionItem(it) {
  2010. const icon = it.type === 'product' ? 'ti-package' : (it.type === 'shop' ? 'ti-briefcase' : (it.type === 'category' ? 'ti-layers' : 'ti-tag'));
  2011. const typeLabel = it.type === 'product' ? 'Produit' : (it.type === 'shop' ? 'Boutique' : (it.type === 'category' ? 'Catégorie' : 'Tag'));
  2012. return '<a href=\"' + it.url + '\" class=\"list-group-item list-group-item-action d-flex align-items-center\">' + '<i class=\"' + icon + ' me-3\"></i>' + '<span class=\"flex-grow-1\">' + escapeHtml(it.label) + '</span>' + '<span class=\"badge bg-light text-dark ms-2\">' + typeLabel + '</span>' + '</a>';
  2013. }
  2014. function escapeHtml(s) {
  2015. return s.replace(/[&<>\"]+/g, c => ({'&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;'}[c]));
  2016. }
  2017. document.addEventListener('click', function (e) {
  2018. if (! box.contains(e.target) && e.target !== input) {
  2019. box.style.display = 'none';
  2020. }
  2021. });
  2022. window.handleSearchSubmit = function (e) {
  2023. if (e) 
  2024. e.preventDefault();
  2025. const first = box.querySelector('a');
  2026. if (first) {
  2027. window.location.href = first.getAttribute('href');
  2028. return false;
  2029. }
  2030. // fallback to listing page search by name
  2031. const q = input.value.trim();
  2032. if (q.length) { // Si on est sur la page listing, utiliser AJAX
  2033. if (typeof currentFilters !== 'undefined') {
  2034. currentFilters.q = q;
  2035. currentFilters.page = 1;
  2036. if (typeof applyFilters === 'function') {
  2037. applyFilters();
  2038. }
  2039. if (typeof updateActiveFilters === 'function') {
  2040. updateActiveFilters();
  2041. }
  2042. } else {
  2043. window.location.href = '";
  2044.         // line 1913
  2045.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
  2046.         yield "' + '?q=' + encodeURIComponent(q);
  2047. }
  2048. }
  2049. return false;
  2050. }
  2051. // Gestion de la touche Enter dans le champ de recherche
  2052. if (input) {
  2053. input.addEventListener('keydown', function (e) {
  2054. if (e.key === 'Enter' || e.keyCode === 13) {
  2055. e.preventDefault();
  2056. e.stopPropagation();
  2057. const q = input.value.trim();
  2058. if (q.length === 0) {
  2059. clearSearch();
  2060. return false;
  2061. }
  2062. // Si on est sur la page listing, utiliser AJAX
  2063. if (typeof currentFilters !== 'undefined' && typeof applyFilters === 'function') {
  2064. currentFilters.q = q;
  2065. currentFilters.page = 1;
  2066. applyFilters();
  2067. if (typeof updateActiveFilters === 'function') {
  2068. updateActiveFilters();
  2069. }
  2070. // Fermer la boîte de recherche
  2071. if (closeSearchBtn) {
  2072. closeSearchBtn.click();
  2073. }
  2074. } else { // Sinon, rediriger vers la page listing avec la recherche
  2075. const listingUrl = '";
  2076.         // line 1944
  2077.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
  2078.         yield "' + '?q=' + encodeURIComponent(q);
  2079. window.location.href = listingUrl;
  2080. }
  2081. return false;
  2082. }
  2083. });
  2084. }
  2085. // Ajouter un event listener au bouton de soumission (réutiliser la variable si elle existe déjà)
  2086. if (!searchSubmitBtn) {
  2087.     searchSubmitBtn = document.getElementById('search_submit_btn');
  2088. }
  2089. if (searchSubmitBtn) {
  2090. searchSubmitBtn.addEventListener('click', function (e) {
  2091. e.preventDefault();
  2092. e.stopPropagation();
  2093. const q = input.value.trim();
  2094. if (q.length === 0) {
  2095. clearSearch();
  2096. return false;
  2097. }
  2098. // Si on est sur la page listing, utiliser AJAX
  2099. if (typeof currentFilters !== 'undefined' && typeof applyFilters === 'function') {
  2100. currentFilters.q = q;
  2101. currentFilters.page = 1;
  2102. applyFilters();
  2103. if (typeof updateActiveFilters === 'function') {
  2104. updateActiveFilters();
  2105. }
  2106. // Fermer la boîte de recherche
  2107. if (closeSearchBtn) {
  2108. closeSearchBtn.click();
  2109. }
  2110. } else { // Sinon, rediriger vers la page listing avec la recherche
  2111. const listingUrl = '";
  2112.         // line 1979
  2113.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
  2114.         yield "' + '?q=' + encodeURIComponent(q);
  2115. window.location.href = listingUrl;
  2116. }
  2117. return false;
  2118. });
  2119. }
  2120. // Afficher le bouton clear au chargement si une recherche est active
  2121. document.addEventListener('DOMContentLoaded', function () {
  2122. const q = input.value.trim();
  2123. if (q.length > 0 && clearSearchBtn) {
  2124. clearSearchBtn.style.display = 'block';
  2125. }
  2126. });
  2127. })();
  2128. // Gestion des mega-menus avec clic (comme la barre de recherche)
  2129. document.addEventListener('DOMContentLoaded', function () {
  2130. const dropdownItems = document.querySelectorAll('.nav-item.dropdown');
  2131. dropdownItems.forEach(function (item) {
  2132. const dropdownToggle = item.querySelector('.dropdown-toggle');
  2133. const dropdownMenu = item.querySelector('.mega-menu');
  2134. if (! dropdownToggle || ! dropdownMenu) 
  2135. return;
  2136. // Fermer les autres menus quand on ouvre un nouveau
  2137. function closeAllMenus() {
  2138. dropdownItems.forEach(function (otherItem) {
  2139. const otherMenu = otherItem.querySelector('.mega-menu');
  2140. if (otherMenu && otherMenu !== dropdownMenu) {
  2141. \$(otherMenu).slideUp(300);
  2142. otherMenu.classList.remove('active');
  2143. }
  2144. });
  2145. }
  2146. // Toggle au clic (comme la barre de recherche)
  2147. dropdownToggle.addEventListener('click', function (e) {
  2148. e.preventDefault();
  2149. e.stopPropagation();
  2150. closeAllMenus();
  2151. if (dropdownMenu.classList.contains('active')) { // Fermer le menu
  2152. dropdownMenu.style.opacity = '0';
  2153. dropdownMenu.style.visibility = 'hidden';
  2154. dropdownMenu.style.transform = 'translateX(-50%) translateY(-10px)';
  2155. setTimeout(() => {
  2156. dropdownMenu.classList.remove('active');
  2157. dropdownMenu.style.display = 'none';
  2158. }, 300);
  2159. } else { // Ouvrir le menu
  2160. dropdownMenu.style.display = 'block';
  2161. setTimeout(() => {
  2162. dropdownMenu.classList.add('active');
  2163. dropdownMenu.style.opacity = '1';
  2164. dropdownMenu.style.visibility = 'visible';
  2165. dropdownMenu.style.transform = 'translateX(-50%) translateY(0)';
  2166. }, 10);
  2167. }
  2168. });
  2169. // Fermer au clic en dehors
  2170. document.addEventListener('click', function (e) {
  2171. if (! item.contains(e.target) && dropdownMenu.classList.contains('active')) {
  2172. dropdownMenu.style.opacity = '0';
  2173. dropdownMenu.style.visibility = 'hidden';
  2174. dropdownMenu.style.transform = 'translateX(-50%) translateY(-10px)';
  2175. setTimeout(() => {
  2176. dropdownMenu.classList.remove('active');
  2177. dropdownMenu.style.display = 'none';
  2178. }, 300);
  2179. }
  2180. });
  2181. // Animation des éléments du menu
  2182. const menuItems = dropdownMenu.querySelectorAll('.dropdown-item a');
  2183. menuItems.forEach(function (menuItem, index) {
  2184. menuItem.style.animationDelay = (index * 0.05) + 's';
  2185. });
  2186. });
  2187. // Gestion des clics sur mobile
  2188. if (window.innerWidth <= 768) {
  2189. dropdownItems.forEach(function (item) {
  2190. const dropdownToggle = item.querySelector('.dropdown-toggle');
  2191. const dropdownMenu = item.querySelector('.mega-menu');
  2192. dropdownToggle.addEventListener('click', function (e) {
  2193. e.preventDefault();
  2194. // Fermer tous les autres menus
  2195. dropdownItems.forEach(function (otherItem) {
  2196. if (otherItem !== item) {
  2197. const otherMenu = otherItem.querySelector('.mega-menu');
  2198. otherMenu.style.opacity = '0';
  2199. otherMenu.style.visibility = 'hidden';
  2200. otherMenu.style.transform = 'translateY(-10px)';
  2201. }
  2202. });
  2203. // Toggle le menu actuel
  2204. if (dropdownMenu.style.opacity === '1') {
  2205. dropdownMenu.style.opacity = '0';
  2206. dropdownMenu.style.visibility = 'hidden';
  2207. dropdownMenu.style.transform = 'translateY(-10px)';
  2208. } else {
  2209. dropdownMenu.style.opacity = '1';
  2210. dropdownMenu.style.visibility = 'visible';
  2211. dropdownMenu.style.transform = 'translateY(0)';
  2212. }
  2213. });
  2214. });
  2215. }
  2216. // Fermer les menus quand on clique ailleurs
  2217. document.addEventListener('click', function (e) {
  2218. if (! e.target.closest('.nav-item.dropdown')) {
  2219. dropdownItems.forEach(function (item) {
  2220. const dropdownMenu = item.querySelector('.mega-menu');
  2221. dropdownMenu.style.opacity = '0';
  2222. dropdownMenu.style.visibility = 'hidden';
  2223. dropdownMenu.style.transform = 'translateY(-10px)';
  2224. });
  2225. }
  2226. });
  2227. });
  2228. \t\t</script>
  2229. \t\t<!-- End footer Area -->
  2230. \t\t<script src=\"";
  2231.         // line 2113
  2232.         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"nulltrue);
  2233.         yield "\"></script>
  2234. \t\t<script src=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js\"></script>
  2235. \t\t<script>
  2236. \t\t\t// Initialiser le collapse Bootstrap 5 pour le menu hamburger après chargement de Bootstrap
  2237. document.addEventListener('DOMContentLoaded', function () { // Attendre que Bootstrap soit complètement chargé
  2238. if (typeof bootstrap !== 'undefined') {
  2239. const navbarToggler = document.querySelector('.navbar-toggler');
  2240. const navbarCollapse = document.getElementById('navbarSupportedContent');
  2241. if (navbarToggler && navbarCollapse) {
  2242. // Bootstrap 5 devrait gérer automatiquement avec data-bs-toggle
  2243. // Mais on s'assure que ça fonctionne en écoutant les événements
  2244. navbarCollapse.addEventListener('show.bs.collapse', function () {
  2245. navbarToggler.setAttribute('aria-expanded', 'true');
  2246. navbarToggler.classList.add('active');
  2247. });
  2248. navbarCollapse.addEventListener('hide.bs.collapse', function () {
  2249. navbarToggler.setAttribute('aria-expanded', 'false');
  2250. navbarToggler.classList.remove('active');
  2251. });
  2252. }
  2253. }
  2254. });
  2255. \t\t</script>
  2256. \t\t<script src=\"https://unpkg.com/dropzone@5/dist/min/dropzone.min.js\"></script>
  2257. \t\t<script src=\"";
  2258.         // line 2139
  2259.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/jquery.ajaxchimp.min.js"), "html"nulltrue);
  2260.         yield "\"></script>
  2261. \t\t<script src=\"";
  2262.         // line 2140
  2263.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/jquery.nice-select.min.js"), "html"nulltrue);
  2264.         yield "\"></script>
  2265. \t\t<script src=\"";
  2266.         // line 2141
  2267.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/jquery.sticky.js"), "html"nulltrue);
  2268.         yield "\"></script>
  2269. \t\t<script src=\"";
  2270.         // line 2142
  2271.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/nouislider.min.js"), "html"nulltrue);
  2272.         yield "\"></script>
  2273. \t\t<script src=\"";
  2274.         // line 2143
  2275.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/countdown.js"), "html"nulltrue);
  2276.         yield "\"></script>
  2277. \t\t<script src=\"";
  2278.         // line 2144
  2279.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/jquery.magnific-popup.min.js"), "html"nulltrue);
  2280.         yield "\"></script>
  2281. \t\t<script src=\"";
  2282.         // line 2145
  2283.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/owl.carousel.min.js"), "html"nulltrue);
  2284.         yield "\"></script>
  2285. \t\t<script src=\"https://maps.googleapis.com/maps/api/js?key=AIzaSyCjCGmQ0Uq4exrzdcL6rvxywDDOvfAu6eE\"></script>
  2286. \t\t<script src=\"";
  2287.         // line 2147
  2288.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/gmaps.min.js"), "html"nulltrue);
  2289.         yield "\"></script>
  2290. \t\t<script src=\"";
  2291.         // line 2148
  2292.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/main.js"), "html"nulltrue);
  2293.         yield "\"></script>
  2294. \t\t";
  2295.         // line 2150
  2296.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->env->getFunction('encore_entry_script_tags')->getCallable()("app"), "html"nulltrue);
  2297.         yield "
  2298. \t\t<!-- PWA Service Worker Registration -->
  2299. \t\t<script>
  2300. \t\t\t// Enregistrement du Service Worker
  2301. if ('serviceWorker' in navigator) {
  2302. window.addEventListener('load', () => {
  2303. navigator.serviceWorker.register('";
  2304.         // line 2157
  2305.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("sw.js"), "html"nulltrue);
  2306.         yield "').then((registration) => {
  2307. console.log('Service Worker enregistré avec succès:', registration.scope);
  2308. // Vérifie les mises à jour du service worker
  2309. registration.addEventListener('updatefound', () => {
  2310. const newWorker = registration.installing;
  2311. newWorker.addEventListener('statechange', () => {
  2312. if (newWorker.state === 'installed' && navigator.serviceWorker.controller) { // Nouveau service worker disponible
  2313. if (confirm('Une nouvelle version de MaketOu est disponible. Voulez-vous l\\'installer maintenant ?')) {
  2314. newWorker.postMessage({type: 'SKIP_WAITING'});
  2315. window.location.reload();
  2316. }
  2317. }
  2318. });
  2319. });
  2320. }).catch((error) => {
  2321. console.log('Échec de l\\'enregistrement du Service Worker:', error);
  2322. });
  2323. // Écoute les messages du service worker
  2324. navigator.serviceWorker.addEventListener('message', (event) => {
  2325. console.log('Message du Service Worker:', event.data);
  2326. });
  2327. });
  2328. }
  2329. \t\t</script>
  2330. \t\t<!-- PWA Install Script -->
  2331. \t\t<script src=\"";
  2332.         // line 2185
  2333.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("js/pwa-install.js"), "html"nulltrue);
  2334.         yield "\"></script>
  2335. \t\t<script>
  2336. \t\t\t// Charger les compteurs au chargement de la page
  2337. document.addEventListener('DOMContentLoaded', function () {
  2338. ";
  2339.         // line 2190
  2340.         if ((($tmp CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "user", [], "any"falsefalsefalse2190)) && $tmp instanceof Markup ? (string) $tmp $tmp)) {
  2341.             // line 2191
  2342.             yield "loadNotificationCount();
  2343. // Délai pour s'assurer que la session est bien établie après connexion
  2344. setTimeout(function () {
  2345. loadComparisonCount();
  2346. }, 500);";
  2347.         }
  2348.         // line 2196
  2349.         yield "
  2350. // Gérer le bouton de recherche mobile
  2351. const searchMobileBtn = document.getElementById('searchMobileBtn');
  2352. if (searchMobileBtn) {
  2353. searchMobileBtn.addEventListener('click', function (e) {
  2354. e.preventDefault();
  2355. // Utiliser le même comportement que le bouton desktop
  2356. const searchBox = document.getElementById('search_input_box');
  2357. if (searchBox) {
  2358. searchBox.style.display = 'block';
  2359. const searchInput = document.getElementById('search_input');
  2360. if (searchInput) {
  2361. setTimeout(() => searchInput.focus(), 100);
  2362. }
  2363. }
  2364. });
  2365. }
  2366. });
  2367. function loadNotificationCount() {
  2368. ";
  2369.         // line 2216
  2370.         if ((($tmp CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "user", [], "any"falsefalsefalse2216)) && $tmp instanceof Markup ? (string) $tmp $tmp)) {
  2371.             // line 2217
  2372.             yield "fetch('";
  2373.             yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("api_notifications_count");
  2374.             yield "').then(response => {
  2375. if (!response.ok) {
  2376. throw new Error('Erreur HTTP: ' + response.status);
  2377. }
  2378. return response.json();
  2379. }).then(data => {
  2380. const count = data.count || 0;
  2381. // Mettre à jour tous les badges de notification
  2382. const badges = [document.getElementById('notificationBadge'), document.getElementById('notificationBadgeMobile'), document.querySelector('.notification-badge')].filter(badge => badge !== null);
  2383. badges.forEach(badge => {
  2384. if (count > 0) {
  2385. badge.textContent = count;
  2386. badge.style.display = 'flex';
  2387. badge.style.color = 'white';
  2388. badge.style.backgroundColor = '#dc3545';
  2389. } else {
  2390. badge.style.display = 'none';
  2391. }
  2392. });
  2393. // Si on est sur la page des notifications, mettre à jour aussi le contenu de la page
  2394. if (typeof updateNotificationPageContent === 'function') {
  2395. updateNotificationPageContent(count);
  2396. }
  2397. }).catch(error => {
  2398. console.error('Erreur lors du chargement du compteur de notifications:', error);
  2399. });";
  2400.         }
  2401.         // line 2246
  2402.         yield "}
  2403. // Exposer la fonction globalement pour qu'elle puisse être appelée depuis d'autres pages
  2404. window.loadNotificationCount = loadNotificationCount;
  2405. // Recharger le compteur toutes les 30 secondes pour garder les données à jour
  2406. ";
  2407.         // line 2252
  2408.         if ((($tmp CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "user", [], "any"falsefalsefalse2252)) && $tmp instanceof Markup ? (string) $tmp $tmp)) {
  2409.             // line 2253
  2410.             yield "setInterval(function () {
  2411. loadNotificationCount();
  2412. }, 30000);";
  2413.         }
  2414.         // line 2255
  2415.         yield "function loadComparisonCount() {
  2416. ";
  2417.         // line 2256
  2418.         if ((($tmp CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "user", [], "any"falsefalsefalse2256)) && $tmp instanceof Markup ? (string) $tmp $tmp)) {
  2419.             // line 2257
  2420.             yield "// Ne pas appeler l'API si on est sur une page d'erreur ou de redirection
  2421. if (window.location.pathname.includes('/api/') || window.location.pathname.includes('/login')) {
  2422. return;
  2423. }
  2424. // Utiliser un try-catch pour éviter toute redirection
  2425. try {
  2426. fetch('";
  2427.             // line 2264
  2428.             yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_api_comparison_count");
  2429.             yield "', {
  2430. method: 'GET',
  2431. headers: {
  2432. 'X-Requested-With': 'XMLHttpRequest',
  2433. 'Accept': 'application/json'
  2434. },
  2435. credentials: 'same-origin',
  2436. redirect: 'error' // Empêcher les redirections automatiques
  2437. }).then(response => { // Vérifier si la réponse est OK
  2438. if (!response.ok) { // Si c'est une redirection (301, 302, etc.) ou une erreur d'authentification, ignorer silencieusement
  2439. if (response.status >= 300 && response.status < 400) {
  2440. console.warn('Redirection détectée, arrêt de la requête');
  2441. return null;
  2442. }
  2443. if (response.status === 401 || response.status === 403) {
  2444. console.warn('Utilisateur non authentifié pour la comparaison');
  2445. return null;
  2446. }
  2447. // Pour les autres erreurs, throw pour être capturé par catch
  2448. throw new Error('Erreur HTTP: ' + response.status);
  2449. }
  2450. // Vérifier que c'est bien du JSON
  2451. const contentType = response.headers.get('content-type');
  2452. if (! contentType || ! contentType.includes('application/json')) { // Si ce n'est pas du JSON, c'est probablement une redirection HTML
  2453. console.warn('La réponse n\\'est pas du JSON, probable redirection');
  2454. return null;
  2455. }
  2456. return response.json();
  2457. }).then(data => { // Si data est null (redirection ou erreur), ne rien faire
  2458. if (!data || typeof data.count === 'undefined') {
  2459. return;
  2460. }
  2461. // Mettre à jour les badges desktop et mobile
  2462. const badges = [document.getElementById('comparisonBadge'), document.getElementById('comparisonBadgeMobile')];
  2463. badges.forEach(badge => {
  2464. if (badge) {
  2465. if (data.count > 0) {
  2466. badge.textContent = data.count;
  2467. badge.style.display = 'flex';
  2468. } else {
  2469. badge.style.display = 'none';
  2470. }
  2471. }
  2472. });
  2473. }).catch(error => { // Ne pas afficher d'erreur si c'est juste une absence d'authentification ou une redirection
  2474. if (error.message && !error.message.includes('401') && !error.message.includes('403') && !error.message.includes('redirect')) {
  2475. console.error('Erreur lors du chargement du compteur de comparaison:', error);
  2476. }
  2477. // Empêcher toute redirection vers l'URL de l'API
  2478. return false;
  2479. });
  2480. } catch (e) { // Capturer toute erreur qui pourrait causer une redirection
  2481. console.warn('Erreur lors de l\\'appel à l\\'API de comparaison:', e);
  2482. }
  2483. ";
  2484.         }
  2485.         // line 2322
  2486.         yield "}
  2487. // Fonction globale pour gérer la comparaison
  2488. function toggleComparison(productId, element) {
  2489. if (! element) {
  2490. element = document.querySelector(`.comparison-btn[data-product-id=\"\${productId}\"]`);
  2491. }
  2492. if (! element) {
  2493. console.error('Bouton de comparaison non trouvé pour le produit', productId);
  2494. return;
  2495. }
  2496. const originalHtml = element.innerHTML;
  2497. // Désactiver le bouton/lien
  2498. if (element.tagName === 'BUTTON') {
  2499. element.disabled = true;
  2500. } else {
  2501. element.style.pointerEvents = 'none';
  2502. element.style.opacity = '0.6';
  2503. } element.innerHTML = '<span class=\"spinner-border spinner-border-sm\"></span>';
  2504. // Vérifier d'abord si le produit est déjà en comparaison
  2505. let isInComparison = false;
  2506. fetch(`/api/comparison/status/\${productId}`).then(response => response.json()).then(data => {
  2507. isInComparison = data.inComparison;
  2508. const url = isInComparison ? `/api/comparison/remove/\${productId}` : `/api/comparison/add/\${productId}`;
  2509. return fetch(url, {
  2510. method: 'POST',
  2511. headers: {
  2512. 'Content-Type': 'application/json',
  2513. 'X-Requested-With': 'XMLHttpRequest'
  2514. }
  2515. });
  2516. }).then(response => response.json()).then(data => {
  2517. if (data.success) { // Mettre à jour le compteur
  2518. loadComparisonCount();
  2519. // Mettre à jour l'apparence du bouton
  2520. if (element) { // Inverser l'état (car on vient de le changer)
  2521. const newState = ! isInComparison;
  2522. // Restaurer le HTML original puis mettre à jour
  2523. element.innerHTML = originalHtml;
  2524. if (newState) {
  2525. element.classList.add('active');
  2526. // Mettre à jour le texte pour les deux types de boutons
  2527. const textEl = element.querySelector('.comparison-text') || element.querySelector('.hover-text') || element.querySelector('p.hover-text');
  2528. if (textEl) 
  2529. textEl.textContent = 'En comparaison';
  2530. // Mettre à jour l'icône si nécessaire (chercher dans span ou i)
  2531. const iconEl = element.querySelector('.lnr-sync, span.lnr-sync, [class*=\"sync\"], i[class*=\"sync\"]');
  2532. if (iconEl) {
  2533. iconEl.style.color = '#28a745';
  2534. iconEl.classList.add('active');
  2535. }
  2536. } else {
  2537. element.classList.remove('active');
  2538. const textEl = element.querySelector('.comparison-text') || element.querySelector('.hover-text') || element.querySelector('p.hover-text');
  2539. if (textEl) 
  2540. textEl.textContent = 'Comparer';
  2541. // Restaurer la couleur de l'icône
  2542. const iconEl = element.querySelector('.lnr-sync, span.lnr-sync, [class*=\"sync\"], i[class*=\"sync\"]');
  2543. if (iconEl) {
  2544. iconEl.style.color = '';
  2545. iconEl.classList.remove('active');
  2546. }
  2547. }
  2548. }
  2549. // Afficher une notification
  2550. showNotification(data.message, 'success');
  2551. } else {
  2552. showNotification(data.message, 'error');
  2553. if (element) {
  2554. element.innerHTML = originalHtml;
  2555. }
  2556. }
  2557. }).catch(error => {
  2558. console.error('Erreur:', error);
  2559. showNotification('Une erreur est survenue', 'error');
  2560. if (element) {
  2561. element.innerHTML = originalHtml;
  2562. }
  2563. }). finally(() => {
  2564. if (element) {
  2565. if (element.tagName === 'BUTTON') {
  2566. element.disabled = false;
  2567. } else {
  2568. element.style.pointerEvents = '';
  2569. element.style.opacity = '';
  2570. }
  2571. }
  2572. });
  2573. }
  2574. // Fonction globale pour gérer les favoris
  2575. function toggleWishlist(productId, element) {
  2576. if (! element) {
  2577. element = document.querySelector(`.wishlist-btn[data-product-id=\"\${productId}\"]`);
  2578. }
  2579. if (! element) {
  2580. console.error('Bouton de wishlist non trouvé pour le produit', productId);
  2581. return;
  2582. }
  2583. const originalHtml = element.innerHTML;
  2584. // Désactiver le bouton/lien
  2585. if (element.tagName === 'BUTTON') {
  2586. element.disabled = true;
  2587. } else {
  2588. element.style.pointerEvents = 'none';
  2589. element.style.opacity = '0.6';
  2590. } element.innerHTML = '<span class=\"spinner-border spinner-border-sm\"></span>';
  2591. // Vérifier d'abord si le produit est déjà en favoris
  2592. let isInWishlist = false;
  2593. fetch(`/api/wishlist/status/\${productId}`).then(response => response.json()).then(data => {
  2594. isInWishlist = data.inWishlist;
  2595. const url = isInWishlist ? `/api/wishlist/remove/\${productId}` : `/api/wishlist/add/\${productId}`;
  2596. return fetch(url, {
  2597. method: 'POST',
  2598. headers: {
  2599. 'Content-Type': 'application/json',
  2600. 'X-Requested-With': 'XMLHttpRequest'
  2601. }
  2602. });
  2603. }).then(response => response.json()).then(data => {
  2604. if (data.success) { // Mettre à jour l'apparence du bouton
  2605. if (element) { // Inverser l'état (car on vient de le changer)
  2606. const newState = ! isInWishlist;
  2607. // Restaurer le HTML original puis mettre à jour
  2608. element.innerHTML = originalHtml;
  2609. // Chercher l'icône dans span ou i
  2610. const icon = element.querySelector('span.lnr-heart, i.lnr-heart, [class*=\"lnr-heart\"]');
  2611. const text = element.querySelector('.wishlist-text') || element.querySelector('.hover-text') || element.querySelector('p.hover-text');
  2612. if (newState) {
  2613. if (icon) { // Pour les icônes linr, on change la classe
  2614. if (icon.classList.contains('lnr-heart')) {
  2615. icon.classList.remove('lnr-heart');
  2616. }
  2617. if (! icon.classList.contains('lnr-heart-filled')) {
  2618. icon.classList.add('lnr-heart-filled');
  2619. }
  2620. icon.style.color = '#dc3545';
  2621. }
  2622. element.classList.add('active');
  2623. if (text) 
  2624. text.textContent = 'Dans favoris';
  2625. } else {
  2626. if (icon) { // Restaurer l'icône originale
  2627. if (icon.classList.contains('lnr-heart-filled')) {
  2628. icon.classList.remove('lnr-heart-filled');
  2629. }
  2630. if (! icon.classList.contains('lnr-heart')) {
  2631. icon.classList.add('lnr-heart');
  2632. }
  2633. icon.style.color = '';
  2634. }
  2635. element.classList.remove('active');
  2636. if (text) 
  2637. text.textContent = 'Favoris';
  2638. }
  2639. }
  2640. // Afficher une notification
  2641. showNotification(data.message, 'success');
  2642. // Si on est sur la page wishlist, recharger la page
  2643. if (window.location.pathname.includes('/account/wishlist')) {
  2644. setTimeout(() => location.reload(), 1000);
  2645. }
  2646. } else {
  2647. showNotification(data.message, 'error');
  2648. if (element) {
  2649. element.innerHTML = originalHtml;
  2650. }
  2651. }
  2652. }).catch(error => {
  2653. console.error('Erreur:', error);
  2654. showNotification('Une erreur est survenue', 'error');
  2655. if (element) {
  2656. element.innerHTML = originalHtml;
  2657. }
  2658. }). finally(() => {
  2659. if (element) {
  2660. if (element.tagName === 'BUTTON') {
  2661. element.disabled = false;
  2662. } else {
  2663. element.style.pointerEvents = '';
  2664. element.style.opacity = '';
  2665. }
  2666. }
  2667. });
  2668. }
  2669. // Fonction pour afficher des notifications
  2670. function showNotification(message, type = 'success') { // Créer l'élément de notification
  2671. const notification = document.createElement('div');
  2672. notification.className = `alert alert-\${
  2673. type === 'success' ? 'success' : 'danger'
  2674. } alert-dismissible fade show position-fixed`;
  2675. notification.style.cssText = 'top: 20px; right: 20px; z-index: 9999; min-width: 300px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);';
  2676. notification.innerHTML = `
  2677.             \${message}
  2678.             <button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\"></button>
  2679.         `;
  2680. document.body.appendChild(notification);
  2681. // Supprimer automatiquement après 3 secondes
  2682. setTimeout(() => {
  2683. notification.remove();
  2684. }, 3000);
  2685. }
  2686. // Initialiser les alertes Bootstrap 5 pour la fermeture
  2687. document.addEventListener('DOMContentLoaded', function () { // S'assurer que les alertes peuvent être fermées
  2688. const alertCloseButtons = document.querySelectorAll('.flash-message .btn-close');
  2689. alertCloseButtons.forEach(function (button) {
  2690. button.addEventListener('click', function () {
  2691. const alert = this.closest('.alert');
  2692. if (alert) {
  2693. alert.classList.remove('show');
  2694. setTimeout(function () {
  2695. alert.remove();
  2696. }, 150);
  2697. }
  2698. });
  2699. });
  2700. // Charger les statuts initiaux des produits
  2701. ";
  2702.         // line 2573
  2703.         if ((($tmp CoreExtension::getAttribute($this->env$this->source, ($context["app"] ?? null), "user", [], "any"falsefalsefalse2573)) && $tmp instanceof Markup ? (string) $tmp $tmp)) {
  2704.             // line 2574
  2705.             yield "// Charger les statuts de comparaison pour tous les produits visibles
  2706. document.querySelectorAll('.comparison-btn[data-product-id]').forEach(btn => {
  2707. const productId = btn.dataset.productId;
  2708. fetch(`/api/comparison/status/\${productId}`).then(response => response.json()).then(data => {
  2709. if (data.inComparison) {
  2710. btn.classList.add('active');
  2711. // Mettre à jour le texte pour les deux types de boutons
  2712. const textEl = btn.querySelector('.comparison-text') || btn.querySelector('.hover-text') || btn.querySelector('p.hover-text');
  2713. if (textEl) 
  2714. textEl.textContent = 'En comparaison';
  2715. // Mettre à jour l'icône si nécessaire
  2716. const iconEl = btn.querySelector('.lnr-sync, [class*=\"sync\"]');
  2717. if (iconEl) 
  2718. iconEl.style.color = '#28a745';
  2719. }
  2720. }).catch(() => {});
  2721. });
  2722. // Charger les statuts de wishlist pour tous les produits visibles
  2723. document.querySelectorAll('.wishlist-btn[data-product-id]').forEach(btn => {
  2724. const productId = btn.dataset.productId;
  2725. fetch(`/api/wishlist/status/\${productId}`).then(response => response.json()).then(data => {
  2726. if (data.inWishlist) {
  2727. // Chercher l'icône dans span ou i
  2728. const icon = btn.querySelector('span.lnr-heart, i.lnr-heart, [class*=\"lnr-heart\"]');
  2729. if (icon) {
  2730. icon.classList.remove('lnr-heart');
  2731. icon.classList.add('lnr-heart');
  2732. icon.style.color = '#ffa200';
  2733. }
  2734. // Mettre à jour le texte pour les deux types de boutons
  2735. const textEl = btn.querySelector('.wishlist-text') || btn.querySelector('.hover-text') || btn.querySelector('p.hover-text');
  2736. if (textEl) 
  2737. textEl.textContent = 'favoris';
  2738. }
  2739. }).catch(() => {});
  2740. });
  2741. // Charger le compteur de comparaison
  2742. loadComparisonCount();";
  2743.         }
  2744.         // line 2623
  2745.         yield "});
  2746. \t\t</script>
  2747. \t\t<script>
  2748. \t\t\t// Loader global pour tous les boutons de formulaire
  2749. document.addEventListener('DOMContentLoaded', function () { // Intercepter tous les formulaires
  2750. const forms = document.querySelectorAll('form');
  2751. forms.forEach(function (form) {
  2752. form.addEventListener('submit', function (e) {
  2753. const submitButtons = form.querySelectorAll('button[type=\"submit\"], input[type=\"submit\"], button:not([type])');
  2754. submitButtons.forEach(function (button) { // Vérifier si le bouton n'est pas déjà désactivé
  2755. if (! button.disabled && ! button.classList.contains('loading')) {
  2756. button.classList.add('loading');
  2757. button.disabled = true;
  2758. // Sauvegarder le texte original
  2759. const originalText = button.innerHTML;
  2760. button.setAttribute('data-original-text', originalText);
  2761. // Ajouter le loader
  2762. button.innerHTML = '<span class=\"spinner-border spinner-border-sm me-2\" role=\"status\" aria-hidden=\"true\"></span>Envoi...';
  2763. // Si le formulaire n'est pas valide, réactiver le bouton après 1 seconde
  2764. setTimeout(function () {
  2765. if (! form.checkValidity()) {
  2766. button.classList.remove('loading');
  2767. button.disabled = false;
  2768. button.innerHTML = originalText;
  2769. }
  2770. }, 1000);
  2771. }
  2772. });
  2773. });
  2774. });
  2775. // Pour les boutons qui déclenchent des actions AJAX
  2776. const ajaxButtons = document.querySelectorAll('[data-ajax], .ajax-submit, button[data-submit]');
  2777. ajaxButtons.forEach(function (button) {
  2778. button.addEventListener('click', function (e) {
  2779. if (this.disabled || this.classList.contains('loading')) {
  2780. e.preventDefault();
  2781. return false;
  2782. }
  2783. this.classList.add('loading');
  2784. this.disabled = true;
  2785. const originalText = this.innerHTML;
  2786. this.setAttribute('data-original-text', originalText);
  2787. this.innerHTML = '<span class=\"spinner-border spinner-border-sm me-2\" role=\"status\" aria-hidden=\"true\"></span>Chargement...';
  2788. });
  2789. });
  2790. // Gestionnaire spécifique pour le formulaire de newsletter
  2791. const newsletterForm = document.querySelector('.footer-newsletter-form');
  2792. if (newsletterForm) {
  2793. newsletterForm.addEventListener('submit', function (e) {
  2794. const submitBtn = this.querySelector('.newsletter-btn');
  2795. if (submitBtn && ! submitBtn.disabled) {
  2796. submitBtn.classList.add('loading');
  2797. submitBtn.disabled = true;
  2798. // Afficher le loader et masquer l'icône
  2799. const icon = submitBtn.querySelector('.newsletter-btn-icon');
  2800. const loader = submitBtn.querySelector('.newsletter-btn-loader');
  2801. if (icon) 
  2802. icon.style.display = 'none';
  2803. if (loader) 
  2804. loader.style.display = 'flex';
  2805. // Réactiver le bouton après 5 secondes au cas où la requête échoue silencieusement
  2806. setTimeout(function () {
  2807. if (submitBtn.classList.contains('loading')) {
  2808. submitBtn.classList.remove('loading');
  2809. submitBtn.disabled = false;
  2810. if (icon) 
  2811. icon.style.display = 'flex';
  2812. if (loader) 
  2813. loader.style.display = 'none';
  2814. }
  2815. }, 5000);
  2816. }
  2817. });
  2818. // Gérer la réponse du formulaire (si AJAX)
  2819. newsletterForm.addEventListener('submit', function (e) {
  2820. // Si le formulaire est soumis normalement (non-AJAX), le navigateur gère la réponse
  2821. // Sinon, on peut intercepter pour gérer la réponse AJAX ici
  2822. });
  2823. }
  2824. });
  2825. // CSS pour le spinner
  2826. const style = document.createElement('style');
  2827. style.textContent = `
  2828.     .spinner-border-sm {
  2829.         width: 1rem;
  2830.         height: 1rem;
  2831.         border-width: 0.15em;
  2832.     }
  2833.     .spinner-border {
  2834.         display: inline-block;
  2835.         width: 1rem;
  2836.         height: 1rem;
  2837.         vertical-align: text-bottom;
  2838.         border: 0.15em solid currentColor;
  2839.         border-right-color: transparent;
  2840.         border-radius: 50%;
  2841.         animation: spinner-border 0.75s linear infinite;
  2842.     }
  2843.     @keyframes spinner-border {
  2844.         to { transform: rotate(360deg); }
  2845.     }
  2846.     button.loading {
  2847.         opacity: 0.7;
  2848.         cursor: not-allowed !important;
  2849.     }
  2850. `;
  2851. document.head.appendChild(style);
  2852. \t\t</script>
  2853. \t\t<!-- Cart Modal -->
  2854. \t\t<div id=\"ebay-cart-modal\" class=\"ebay-cart-modal-overlay\" style=\"display: none;\" data-url=\"\">
  2855. \t\t\t<div class=\"ebay-cart-modal\">
  2856. \t\t\t\t<div class=\"ebay-modal-header\">
  2857. \t\t\t\t\t<h3>
  2858. \t\t\t\t\t\t<i class=\"lnr lnr-checkmark-circle\"></i>
  2859. \t\t\t\t\t\tAjouté au panier !</h3>
  2860. \t\t\t\t\t<button class=\"ebay-modal-close\" onclick=\"closeEbayCartModal()\">&times;</button>
  2861. \t\t\t\t</div>
  2862. \t\t\t\t<div class=\"ebay-modal-content\">
  2863. \t\t\t\t\t<div class=\"ebay-product-info\">
  2864. \t\t\t\t\t\t<div class=\"ebay-product-image\">
  2865. \t\t\t\t\t\t\t<img id=\"ebay-modal-product-image\" src=\"\" alt=\"Produit\"/>
  2866. \t\t\t\t\t\t</div>
  2867. \t\t\t\t\t\t<div class=\"ebay-product-details\">
  2868. \t\t\t\t\t\t\t<h4 id=\"ebay-modal-product-name\">Nom du produit</h4>
  2869. \t\t\t\t\t\t\t<div class=\"ebay-product-price\" id=\"ebay-modal-product-price\">Prix</div>
  2870. \t\t\t\t\t\t\t<div class=\"ebay-product-quantity\">
  2871. \t\t\t\t\t\t\t\t<span>Quantité:
  2872. \t\t\t\t\t\t\t\t</span>
  2873. \t\t\t\t\t\t\t\t<span id=\"ebay-modal-product-quantity\">1</span>
  2874. \t\t\t\t\t\t\t</div>
  2875. \t\t\t\t\t\t</div>
  2876. \t\t\t\t\t</div>
  2877. \t\t\t\t\t<!-- Recommendations Section -->
  2878. \t\t\t\t\t<div class=\"ebay-recommendations\" style=\"display: none;\">
  2879. \t\t\t\t\t\t<h4>Les clients ont aussi acheté :</h4>
  2880. \t\t\t\t\t\t<div
  2881. \t\t\t\t\t\t\tclass=\"ebay-recommendations-grid\" id=\"ebay-modal-recommendations\"><!-- Recommendations will be injected here -->
  2882. \t\t\t\t\t\t</div>
  2883. \t\t\t\t\t</div>
  2884. \t\t\t\t\t<div class=\"ebay-modal-actions\">
  2885. \t\t\t\t\t\t<button class=\"ebay-btn-continue\" onclick=\"closeEbayCartModal()\">
  2886. \t\t\t\t\t\t\tContinuer mes achats
  2887. \t\t\t\t\t\t</button>
  2888. \t\t\t\t\t\t<a href=\"";
  2889.         // line 2797
  2890.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_cart");
  2891.         yield "\" class=\"ebay-btn-view-cart\">
  2892. \t\t\t\t\t\t\tVoir mon panier
  2893. \t\t\t\t\t\t</a>
  2894. \t\t\t\t\t</div>
  2895. \t\t\t\t</div>
  2896. \t\t\t</div>
  2897. \t\t</div>
  2898. \t\t<script src=\"";
  2899.         // line 2805
  2900.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/cart-modal.js"), "html"nulltrue);
  2901.         yield "\"></script>
  2902. \t\t<script src=\"";
  2903.         // line 2806
  2904.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/js/notification-badge.js"), "html"nulltrue);
  2905.         yield "\"></script>
  2906. \t\t";
  2907.         // line 2808
  2908.         yield from $this->unwrap()->yieldBlock('javascripts'$context$blocks);
  2909.         // line 2809
  2910.         yield "\t</body>
  2911. </html>
  2912. ";
  2913.         
  2914.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  2915.         
  2916.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  2917.         yield from [];
  2918.     }
  2919.     // line 40
  2920.     /**
  2921.      * @return iterable<null|scalar|\Stringable>
  2922.      */
  2923.     public function block_title(array $context, array $blocks = []): iterable
  2924.     {
  2925.         $macros $this->macros;
  2926.         $__internal_5a27a8ba21ca79b61932376b2fa922d2 $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  2927.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""title"));
  2928.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  2929.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""title"));
  2930.         yield "MaketOu
  2931. \t\t\t";
  2932.         
  2933.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  2934.         
  2935.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  2936.         yield from [];
  2937.     }
  2938.     // line 1236
  2939.     /**
  2940.      * @return iterable<null|scalar|\Stringable>
  2941.      */
  2942.     public function block_stylesheets(array $context, array $blocks = []): iterable
  2943.     {
  2944.         $macros $this->macros;
  2945.         $__internal_5a27a8ba21ca79b61932376b2fa922d2 $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  2946.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""stylesheets"));
  2947.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  2948.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""stylesheets"));
  2949.         // line 1237
  2950.         yield "\t\t\t";
  2951.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->env->getFunction('encore_entry_link_tags')->getCallable()("app"), "html"nulltrue);
  2952.         yield "
  2953. \t\t";
  2954.         
  2955.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  2956.         
  2957.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  2958.         yield from [];
  2959.     }
  2960.     // line 1486
  2961.     /**
  2962.      * @return iterable<null|scalar|\Stringable>
  2963.      */
  2964.     public function block_body(array $context, array $blocks = []): iterable
  2965.     {
  2966.         $macros $this->macros;
  2967.         $__internal_5a27a8ba21ca79b61932376b2fa922d2 $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  2968.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""body"));
  2969.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  2970.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""body"));
  2971.         
  2972.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  2973.         
  2974.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  2975.         yield from [];
  2976.     }
  2977.     // line 2808
  2978.     /**
  2979.      * @return iterable<null|scalar|\Stringable>
  2980.      */
  2981.     public function block_javascripts(array $context, array $blocks = []): iterable
  2982.     {
  2983.         $macros $this->macros;
  2984.         $__internal_5a27a8ba21ca79b61932376b2fa922d2 $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  2985.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""javascripts"));
  2986.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  2987.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""javascripts"));
  2988.         
  2989.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  2990.         
  2991.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  2992.         yield from [];
  2993.     }
  2994.     /**
  2995.      * @codeCoverageIgnore
  2996.      */
  2997.     public function getTemplateName(): string
  2998.     {
  2999.         return "base_home.html.twig";
  3000.     }
  3001.     /**
  3002.      * @codeCoverageIgnore
  3003.      */
  3004.     public function isTraitable(): bool
  3005.     {
  3006.         return false;
  3007.     }
  3008.     /**
  3009.      * @codeCoverageIgnore
  3010.      */
  3011.     public function getDebugInfo(): array
  3012.     {
  3013.         return array (  3301 => 2808,  3279 => 1486,  3265 => 1237,  3252 => 1236,  3228 => 40,  3215 => 2809,  3213 => 2808,  3208 => 2806,  3204 => 2805,  3193 => 2797,  3017 => 2623,  2966 => 2574,  2964 => 2573,  2711 => 2322,  2650 => 2264,  2641 => 2257,  2639 => 2256,  2636 => 2255,  2631 => 2253,  2629 => 2252,  2621 => 2246,  2588 => 2217,  2586 => 2216,  2564 => 2196,  2557 => 2191,  2555 => 2190,  2547 => 2185,  2516 => 2157,  2506 => 2150,  2501 => 2148,  2497 => 2147,  2492 => 2145,  2488 => 2144,  2484 => 2143,  2480 => 2142,  2476 => 2141,  2472 => 2140,  2468 => 2139,  2439 => 2113,  2302 => 1979,  2264 => 1944,  2230 => 1913,  2166 => 1852,  2135 => 1824,  2101 => 1793,  2060 => 1755,  1912 => 1610,  1898 => 1599,  1891 => 1595,  1884 => 1591,  1877 => 1587,  1870 => 1583,  1856 => 1572,  1849 => 1568,  1842 => 1564,  1835 => 1560,  1825 => 1552,  1818 => 1548,  1811 => 1544,  1808 => 1543,  1801 => 1539,  1798 => 1538,  1796 => 1537,  1790 => 1534,  1783 => 1530,  1776 => 1526,  1735 => 1487,  1733 => 1486,  1727 => 1482,  1717 => 1478,  1713 => 1476,  1709 => 1475,  1706 => 1474,  1696 => 1470,  1692 => 1468,  1688 => 1467,  1685 => 1466,  1675 => 1462,  1671 => 1460,  1667 => 1459,  1664 => 1458,  1654 => 1454,  1650 => 1452,  1646 => 1451,  1632 => 1439,  1626 => 1435,  1624 => 1434,  1617 => 1430,  1613 => 1429,  1603 => 1421,  1594 => 1416,  1585 => 1411,  1583 => 1410,  1575 => 1404,  1567 => 1399,  1559 => 1395,  1557 => 1394,  1547 => 1391,  1538 => 1385,  1532 => 1384,  1527 => 1382,  1521 => 1381,  1516 => 1379,  1510 => 1378,  1505 => 1376,  1499 => 1375,  1485 => 1366,  1471 => 1357,  1351 => 1239,  1349 => 1236,  174 => 63,  168 => 59,  164 => 58,  160 => 57,  156 => 56,  152 => 55,  148 => 54,  144 => 53,  140 => 52,  136 => 51,  132 => 50,  128 => 49,  124 => 48,  120 => 47,  113 => 42,  111 => 40,  93 => 25,  86 => 21,  81 => 19,  77 => 18,  73 => 17,  67 => 14,  52 => 1,);
  3014.     }
  3015.     public function getSourceContext(): Source
  3016.     {
  3017.         return new Source("<!DOCTYPE html>
  3018. <html lang=\"fr\" class=\"no-js\">
  3019. \t<head>
  3020. \t\t<!-- Mobile Specific Meta -->
  3021. \t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no\">
  3022. \t\t<meta name=\"mobile-web-app-capable\" content=\"yes\">
  3023. \t\t<meta name=\"apple-mobile-web-app-capable\" content=\"yes\">
  3024. \t\t<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"default\">
  3025. \t\t<meta name=\"apple-mobile-web-app-title\" content=\"MaketOu\">
  3026. \t\t<meta name=\"theme-color\" content=\"#ffa200\">
  3027. \t\t<meta name=\"msapplication-TileColor\" content=\"#ffa200\">
  3028. \t\t<meta
  3029. \t\tname=\"msapplication-config\" content=\"{{ asset('favicon/browserconfig.xml') }}\">
  3030. \t\t<!-- Favicon-->
  3031. \t\t<link rel=\"shortcut icon\" href=\"{{ asset('favicon/favicon-16x16.png') }}\">
  3032. \t\t<link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"{{ asset('favicon/apple-touch-icon.png') }}\">
  3033. \t\t<link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"{{ asset('favicon/favicon-32x32.png') }}\">
  3034. \t\t<link
  3035. \t\trel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"{{ asset('favicon/favicon-16x16.png') }}\">
  3036. \t\t<!-- PWA Manifest -->
  3037. \t\t<link
  3038. \t\trel=\"manifest\" href=\"{{ asset('manifest.json') }}\">
  3039. \t\t<!-- Author Meta -->
  3040. \t\t<meta
  3041. \t\tname=\"author\" content=\"Foulgor Tech\">
  3042. \t\t<!-- Meta Description -->
  3043. \t\t<meta
  3044. \t\tname=\"description\" content=\"\">
  3045. \t\t<!-- Meta Keyword -->
  3046. \t\t<meta
  3047. \t\tname=\"keywords\" content=\"\">
  3048. \t\t<!-- meta character set -->
  3049. \t\t<meta
  3050. \t\tcharset=\"UTF-8\">
  3051. \t\t<!-- Site Title -->
  3052. \t\t<title>
  3053. \t\t\t{% block title %}MaketOu
  3054. \t\t\t{% endblock %}
  3055. \t\t</title>
  3056. \t\t<!--
  3057. \t\t\t\t\t\t        CSS
  3058. \t\t\t\t\t\t        ============================================= -->
  3059. \t\t<link rel=\"stylesheet\" href=\"https://unpkg.com/dropzone@5/dist/min/dropzone.min.css\"/>
  3060. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/linearicons.css') }}\">
  3061. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/font-awesome.min.css') }}\">
  3062. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/themify-icons.css') }}\">
  3063. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/bootstrap.css') }}\">
  3064. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/owl.carousel.css') }}\">
  3065. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/nice-select.css') }}\">
  3066. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/nouislider.min.css') }}\">
  3067. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/ion.rangeSlider.css') }}\"/>
  3068. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/ion.rangeSlider.skinFlat.css') }}\"/>
  3069. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/magnific-popup.css') }}\">
  3070. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/main.css') }}\">
  3071. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/cart-modal.css') }}\">
  3072. \t\t<link rel=\"stylesheet\" href=\"{{ asset('ui/css/buttons-unified.css') }}\">
  3073. \t\t<meta
  3074. \t\tcharset=\"UTF-8\">
  3075. \t\t{# Run `composer require symfony/webpack-encore-bundle` to start using Symfony UX #}
  3076. \t\t<style>
  3077. \t\t\t/* Styles pour l'icône de notification */
  3078. \t\t\t.notification-icon {
  3079. \t\t\t\tposition: relative;
  3080. \t\t\t\tdisplay: inline-block;
  3081. \t\t\t\tcolor: #333;
  3082. \t\t\t\ttext-decoration: none;
  3083. \t\t\t\ttransition: color 0.3s ease;
  3084. \t\t\t}
  3085. \t\t\t.notification-icon:hover {
  3086. \t\t\t\tcolor: #007bff;
  3087. \t\t\t}
  3088. \t\t\t.notification-badge {
  3089. \t\t\t\tposition: absolute;
  3090. \t\t\t\ttop: -4px;
  3091. \t\t\t\tright: -2px;
  3092. \t\t\t\tbackground: #dc3545 !important;
  3093. \t\t\t\tcolor: white !important;
  3094. \t\t\t\tborder-radius: 50%;
  3095. \t\t\t\twidth: 18px;
  3096. \t\t\t\theight: 18px;
  3097. \t\t\t\tfont-size: 8px !important;
  3098. \t\t\t\tdisplay: flex !important;
  3099. \t\t\t\talign-items: center !important;
  3100. \t\t\t\tjustify-content: center !important;
  3101. \t\t\t\tfont-weight: bold !important;
  3102. \t\t\t\tanimation: pulse 2s infinite;
  3103. \t\t\t\tz-index: 10;
  3104. \t\t\t\tline-height: 1 !important;
  3105. \t\t\t}
  3106. \t\t\t/* Forcer le texte en blanc pour tous les éléments du badge - avec spécificité maximale */
  3107. \t\t\t.notification-badge,
  3108. \t\t\t.notification-badge.text-white,
  3109. \t\t\t.notification-badge *,
  3110. \t\t\t#notificationBadge,
  3111. \t\t\t#notificationBadge.text-white,
  3112. \t\t\t#notificationBadge *,
  3113. \t\t\tspan.notification-badge,
  3114. \t\t\tspan.notification-badge.text-white,
  3115. \t\t\tspan#notificationBadge,
  3116. \t\t\tspan#notificationBadge.text-white {
  3117. \t\t\t\tcolor: white !important;
  3118. \t\t\t\ttext-color: white !important;
  3119. \t\t\t\t-webkit-text-fill-color: white !important;
  3120. \t\t\t}
  3121. \t\t\t/* S'assurer que le contenu texte est bien en blanc */
  3122. \t\t\t.notification-badge::before,
  3123. \t\t\t.notification-badge::after {
  3124. \t\t\t\tcolor: white !important;
  3125. \t\t\t}
  3126. \t\t\t/* Forcer la couleur pour tous les sélecteurs possibles avec spécificité maximale */
  3127. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon .notification-badge,
  3128. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon .notification-badge.text-white,
  3129. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon span.notification-badge,
  3130. \t\t\t.notification-icon .notification-badge,
  3131. \t\t\t.notification-icon .notification-badge.text-white,
  3132. \t\t\t.notification-icon span.notification-badge,
  3133. \t\t\ta.notification-icon .notification-badge,
  3134. \t\t\ta.notification-icon span.notification-badge {
  3135. \t\t\t\tcolor: white !important;
  3136. \t\t\t\ttext-color: white !important;
  3137. \t\t\t\t-webkit-text-fill-color: white !important;
  3138. \t\t\t}
  3139. \t\t\t/* Forcer la couleur pour tous les enfants directs */
  3140. \t\t\t.notification-icon > .notification-badge,
  3141. \t\t\t.notification-icon > span.notification-badge {
  3142. \t\t\t\tcolor: white !important;
  3143. \t\t\t}
  3144. \t\t\t@keyframes pulse {
  3145. \t\t\t\t0% {
  3146. \t\t\t\t\ttransform: scale(1);
  3147. \t\t\t\t}
  3148. \t\t\t\t50% {
  3149. \t\t\t\t\ttransform: scale(1.1);
  3150. \t\t\t\t}
  3151. \t\t\t\t100% {
  3152. \t\t\t\t\ttransform: scale(1);
  3153. \t\t\t\t}
  3154. \t\t\t}
  3155. \t\t\t.notification-icon:hover .notification-badge {
  3156. \t\t\t\tanimation: none;
  3157. \t\t\t}
  3158. \t\t\t/* Container pour les icônes - toujours alignées horizontalement */
  3159. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper {
  3160. \t\t\t\tdisplay: flex !important;
  3161. \t\t\t\tflex-direction: row !important;
  3162. \t\t\t\talign-items: center !important;
  3163. \t\t\t\tjustify-content: center !important;
  3164. \t\t\t\tgap: 15px !important;
  3165. \t\t\t\tlist-style: none !important;
  3166. \t\t\t\tmargin: 0 !important;
  3167. \t\t\t\tpadding: 0 !important;
  3168. \t\t\t\twidth: auto !important;
  3169. \t\t\t}
  3170. \t\t\t/* Surcharger les styles existants pour les li contenant le wrapper */
  3171. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right li:has(.navbar-icons-wrapper) {
  3172. \t\t\t\tmargin-left: 0 !important;
  3173. \t\t\t\tmargin-right: 0 !important;
  3174. \t\t\t\tdisplay: flex !important;
  3175. \t\t\t\talign-items: center !important;
  3176. \t\t\t\tjustify-content: center !important;
  3177. \t\t\t}
  3178. \t\t\t/* Styles pour les icônes */
  3179. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .cart,
  3180. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon,
  3181. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon,
  3182. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search {
  3183. \t\t\t\tdisplay: flex !important;
  3184. \t\t\t\talign-items: center !important;
  3185. \t\t\t\tjustify-content: center !important;
  3186. \t\t\t\twidth: 40px !important;
  3187. \t\t\t\theight: 40px !important;
  3188. \t\t\t\tmin-width: 40px !important;
  3189. \t\t\t\tmin-height: 40px !important;
  3190. \t\t\t\tcolor: #333 !important;
  3191. \t\t\t\ttext-decoration: none !important;
  3192. \t\t\t\ttransition: all 0.3s ease !important;
  3193. \t\t\t\tborder-radius: 50% !important;
  3194. \t\t\t\tposition: relative !important;
  3195. \t\t\t\tmargin: 0 !important;
  3196. \t\t\t\tpadding: 0 !important;
  3197. \t\t\t}
  3198. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .cart:hover,
  3199. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon:hover,
  3200. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon:hover,
  3201. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search:hover {
  3202. \t\t\t\tbackground-color: #f0f0f0 !important;
  3203. \t\t\t\tcolor: #ffa200 !important;
  3204. \t\t\t\ttransform: scale(1.1) !important;
  3205. \t\t\t}
  3206. \t\t\t/* Surcharger le line-height de main.css */
  3207. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .cart span,
  3208. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .notification-icon span,
  3209. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search span {
  3210. \t\t\t\tfont-size: 18px !important;
  3211. \t\t\t\tline-height: 1 !important;
  3212. \t\t\t\tdisplay: flex !important;
  3213. \t\t\t\talign-items: center !important;
  3214. \t\t\t\tjustify-content: center !important;
  3215. \t\t\t\tcolor: inherit !important;
  3216. \t\t\t\tfont-weight: normal !important;
  3217. \t\t\t}
  3218. \t\t\t/* Icône de comparaison en noir comme le panier */
  3219. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon {
  3220. \t\t\t\tcolor: #333 !important;
  3221. \t\t\t}
  3222. \t\t\t/* L'icône elle-même (lnr-sync) doit être noire, mais pas le badge */
  3223. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon > span.lnr-sync,
  3224. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon span:not(.comparison-badge) {
  3225. \t\t\t\tcolor: #333 !important;
  3226. \t\t\t\tfont-size: 18px !important;
  3227. \t\t\t\tline-height: 1 !important;
  3228. \t\t\t\tdisplay: flex !important;
  3229. \t\t\t\talign-items: center !important;
  3230. \t\t\t\tjustify-content: center !important;
  3231. \t\t\t\tfont-weight: normal !important;
  3232. \t\t\t}
  3233. \t\t\t/* Le badge doit rester blanc */
  3234. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .comparison-icon .comparison-badge {
  3235. \t\t\t\tcolor: white !important;
  3236. \t\t\t}
  3237. \t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper .search {
  3238. \t\t\t\tbackground: transparent !important;
  3239. \t\t\t\tborder: 0 !important;
  3240. \t\t\t\tcursor: pointer !important;
  3241. \t\t\t\tpadding: 0 !important;
  3242. \t\t\t}
  3243. \t\t\t/* Alignement des icônes navbar sur mobile */
  3244. \t\t\t@media(max-width: 991.98px) {
  3245. \t\t\t\t/* Container navbar-right en colonne sur mobile */
  3246. \t\t\t\t.header_area .navbar .nav.navbar-nav.navbar-right {
  3247. \t\t\t\t\tdisplay: flex !important;
  3248. \t\t\t\t\tflex-direction: column !important;
  3249. \t\t\t\t\talign-items: center !important;
  3250. \t\t\t\t\tjustify-content: center !important;
  3251. \t\t\t\t\twidth: 100% !important;
  3252. \t\t\t\t\tgap: 0 !important;
  3253. \t\t\t\t\tmargin: 0 !important;
  3254. \t\t\t\t\tpadding: 10px 0 !important;
  3255. \t\t\t\t}
  3256. \t\t\t\t/* Le container d'icônes reste horizontal */
  3257. \t\t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .navbar-icons-wrapper {
  3258. \t\t\t\t\twidth: 100% !important;
  3259. \t\t\t\t\tjustify-content: center !important;
  3260. \t\t\t\t\tdisplay: flex !important;
  3261. \t\t\t\t\tflex-direction: row !important;
  3262. \t\t\t\t}
  3263. \t\t\t\t/* Le bouton compte en bas - pleine largeur */
  3264. \t\t\t\t.header_area .navbar .nav.navbar-nav.navbar-right li:last-child {
  3265. \t\t\t\t\twidth: 100% !important;
  3266. \t\t\t\t\tdisplay: flex !important;
  3267. \t\t\t\t\tjustify-content: center !important;
  3268. \t\t\t\t\tmargin-top: 12px !important;
  3269. \t\t\t\t\tpadding-top: 12px !important;
  3270. \t\t\t\t\tborder-top: 1px solid #e0e0e0 !important;
  3271. \t\t\t\t}
  3272. \t\t\t\t/* Bouton compte responsive */
  3273. \t\t\t\t.header_area .navbar .nav.navbar-nav.navbar-right .btn-account {
  3274. \t\t\t\t\twidth: 100%;
  3275. \t\t\t\t\tmax-width: 200px;
  3276. \t\t\t\t\tpadding: 10px 20px;
  3277. \t\t\t\t\tfont-size: 14px;
  3278. \t\t\t\t}
  3279. \t\t\t}
  3280. \t\t\t/* Styles pour les messages flash - Design moderne */
  3281. \t\t\t.flash-message {
  3282. \t\t\t\tanimation: slideInDownFlash 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  3283. \t\t\t\tposition: relative;
  3284. \t\t\t\toverflow: visible !important;
  3285. \t\t\t\tborder: none !important;
  3286. \t\t\t\tpadding: 16px 20px !important;
  3287. \t\t\t\tborder-radius: 12px !important;
  3288. \t\t\t\tbox-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
  3289. \t\t\t\tdisplay: flex !important;
  3290. \t\t\t\talign-items: center;
  3291. \t\t\t\tgap: 12px;
  3292. \t\t\t\tmargin-bottom: 15px;
  3293. \t\t\t\tbackdrop-filter: blur(10px);
  3294. \t\t\t\ttransition: all 0.3s ease;
  3295. \t\t\t}
  3296. \t\t\t/* S'assurer que les icônes Font Awesome sont visibles */
  3297. \t\t\t.flash-message i.fa {
  3298. \t\t\t\tdisplay: inline-block !important;
  3299. \t\t\t\tvisibility: visible !important;
  3300. \t\t\t\topacity: 1 !important;
  3301. \t\t\t\twidth: auto !important;
  3302. \t\t\t\theight: auto !important;
  3303. \t\t\t\tfont-family: \"FontAwesome\" !important;
  3304. \t\t\t\tfont-style: normal !important;
  3305. \t\t\t\tfont-weight: normal !important;
  3306. \t\t\t\ttext-rendering: auto !important;
  3307. \t\t\t\t-webkit-font-smoothing: antialiased !important;
  3308. \t\t\t\t-moz-osx-font-smoothing: grayscale !important;
  3309. \t\t\t\tline-height: 1 !important;
  3310. \t\t\t\tflex-shrink: 0 !important;
  3311. \t\t\t}
  3312. \t\t\t/* Forcer l'affichage des pseudo-éléments Font Awesome */
  3313. \t\t\t.flash-message i.fa::before {
  3314. \t\t\t\tdisplay: inline-block !important;
  3315. \t\t\t\tvisibility: visible !important;
  3316. \t\t\t\topacity: 1 !important;
  3317. \t\t\t\tcontent: attr(data-icon) !important;
  3318. \t\t\t}
  3319. \t\t\t/* Styles spécifiques pour chaque icône */
  3320. \t\t\t.flash-message i.fa-check-circle::before {
  3321. \t\t\t\tcontent: \"\\f058\" !important;
  3322. \t\t\t}
  3323. \t\t\t.flash-message i.fa-exclamation-circle::before {
  3324. \t\t\t\tcontent: \"\\f06a\" !important;
  3325. \t\t\t}
  3326. \t\t\t.flash-message i.fa-exclamation-triangle::before {
  3327. \t\t\t\tcontent: \"\\f071\" !important;
  3328. \t\t\t}
  3329. \t\t\t.flash-message i.fa-info-circle::before {
  3330. \t\t\t\tcontent: \"\\f05a\" !important;
  3331. \t\t\t}
  3332. \t\t\t.flash-message:hover {
  3333. \t\t\t\tbox-shadow: 0 6px 20px rgba(0, 0, 0, 0.2) !important;
  3334. \t\t\t\ttransform: translateY(-2px);
  3335. \t\t\t}
  3336. \t\t\t.flash-message::before {
  3337. \t\t\t\tcontent: '';
  3338. \t\t\t\tposition: absolute;
  3339. \t\t\t\tleft: 0;
  3340. \t\t\t\ttop: 0;
  3341. \t\t\t\tbottom: 0;
  3342. \t\t\t\twidth: 5px;
  3343. \t\t\t\tbackground: linear-gradient(180deg, currentColor 0%, rgba(255,255,255,0.3) 100%);
  3344. \t\t\t\tborder-radius: 12px 0 0 12px;
  3345. \t\t\t}
  3346. \t\t\t.flash-message.alert-success {
  3347. \t\t\t\tbackground: linear-gradient(135deg, #d4edda 0%, #c3e6cb 100%) !important;
  3348. \t\t\t\tcolor: #155724 !important;
  3349. \t\t\t\tborder-left: 5px solid #28a745 !important;
  3350. \t\t\t}
  3351. \t\t\t.flash-message.alert-success i.fa {
  3352. \t\t\t\tcolor: #28a745 !important;
  3353. \t\t\t\tfont-size: 1.3rem !important;
  3354. \t\t\t\tdisplay: inline-block !important;
  3355. \t\t\t\tmargin-right: 8px;
  3356. \t\t\t\tvertical-align: middle;
  3357. \t\t\t}
  3358. \t\t\t.flash-message.alert-danger {
  3359. \t\t\t\tbackground: linear-gradient(135deg, #f8d7da 0%, #f5c6cb 100%) !important;
  3360. \t\t\t\tcolor: #721c24 !important;
  3361. \t\t\t\tborder-left: 5px solid #dc3545 !important;
  3362. \t\t\t}
  3363. \t\t\t.flash-message.alert-danger i.fa {
  3364. \t\t\t\tcolor: #dc3545 !important;
  3365. \t\t\t\tfont-size: 1.3rem !important;
  3366. \t\t\t\tdisplay: inline-block !important;
  3367. \t\t\t\tmargin-right: 8px;
  3368. \t\t\t\tvertical-align: middle;
  3369. \t\t\t}
  3370. \t\t\t.flash-message.alert-warning {
  3371. \t\t\t\tbackground: linear-gradient(135deg, #fff3cd 0%, #ffeaa7 100%) !important;
  3372. \t\t\t\tcolor: #856404 !important;
  3373. \t\t\t\tborder-left: 5px solid #ffc107 !important;
  3374. \t\t\t}
  3375. \t\t\t.flash-message.alert-warning i.fa {
  3376. \t\t\t\tcolor: #ffa200 !important;
  3377. \t\t\t\tfont-size: 1.3rem !important;
  3378. \t\t\t\tdisplay: inline-block !important;
  3379. \t\t\t\tmargin-right: 8px;
  3380. \t\t\t\tvertical-align: middle;
  3381. \t\t\t}
  3382. \t\t\t.flash-message.alert-info {
  3383. \t\t\t\tbackground: linear-gradient(135deg, #d1ecf1 0%, #bee5eb 100%) !important;
  3384. \t\t\t\tcolor: #0c5460 !important;
  3385. \t\t\t\tborder-left: 5px solid #17a2b8 !important;
  3386. \t\t\t}
  3387. \t\t\t.flash-message.alert-info i.fa {
  3388. \t\t\t\tcolor: #17a2b8 !important;
  3389. \t\t\t\tfont-size: 1.3rem !important;
  3390. \t\t\t\tdisplay: inline-block !important;
  3391. \t\t\t\tmargin-right: 8px;
  3392. \t\t\t\tvertical-align: middle;
  3393. \t\t\t}
  3394. \t\t\t.flash-message strong {
  3395. \t\t\t\tflex: 1;
  3396. \t\t\t\tfont-weight: 600;
  3397. \t\t\t\tfont-size: 0.95rem;
  3398. \t\t\t\tline-height: 1.5;
  3399. \t\t\t}
  3400. \t\t\t.flash-message .btn-close {
  3401. \t\t\t\topacity: 0.7;
  3402. \t\t\t\tpadding: 8px !important;
  3403. \t\t\t\tmargin: -8px -8px -8px auto !important;
  3404. \t\t\t\ttransition: all 0.2s ease;
  3405. \t\t\t\tborder-radius: 50% !important;
  3406. \t\t\t\tbackground: rgba(0, 0, 0, 0.05) !important;
  3407. \t\t\t\twidth: 32px !important;
  3408. \t\t\t\theight: 32px !important;
  3409. \t\t\t\tdisplay: flex !important;
  3410. \t\t\t\talign-items: center !important;
  3411. \t\t\t\tjustify-content: center !important;
  3412. \t\t\t\tborder: none !important;
  3413. \t\t\t\tcursor: pointer !important;
  3414. \t\t\t\tposition: relative !important;
  3415. \t\t\t}
  3416. \t\t\t/* Ajouter une icône X visible dans le bouton */
  3417. \t\t\t.flash-message .btn-close::before {
  3418. \t\t\t\tcontent: '×' !important;
  3419. \t\t\t\tfont-size: 24px !important;
  3420. \t\t\t\tline-height: 1 !important;
  3421. \t\t\t\tcolor: currentColor !important;
  3422. \t\t\t\tfont-weight: bold !important;
  3423. \t\t\t\tdisplay: block !important;
  3424. \t\t\t\tposition: absolute !important;
  3425. \t\t\t\ttop: 50% !important;
  3426. \t\t\t\tleft: 50% !important;
  3427. \t\t\t\ttransform: translate(-50%, -50%) !important;
  3428. \t\t\t}
  3429. \t\t\t.flash-message .btn-close:hover {
  3430. \t\t\t\topacity: 1 !important;
  3431. \t\t\t\tbackground: rgba(0, 0, 0, 0.15) !important;
  3432. \t\t\t\ttransform: rotate(90deg) !important;
  3433. \t\t\t}
  3434. \t\t\t.flash-message .btn-close:hover::before {
  3435. \t\t\t\ttransform: translate(-50%, -50%) rotate(-90deg) !important;
  3436. \t\t\t}
  3437. \t\t\t@keyframes slideInDownFlash {
  3438. \t\t\t\tfrom {
  3439. \t\t\t\t\topacity: 0;
  3440. \t\t\t\t\ttransform: translateY(-30px) scale(0.95);
  3441. \t\t\t\t}
  3442. \t\t\t\tto {
  3443. \t\t\t\t\topacity: 1;
  3444. \t\t\t\t\ttransform: translateY(0) scale(1);
  3445. \t\t\t\t}
  3446. \t\t\t}
  3447. \t\t\t#flash-messages-container {
  3448. \t\t\t\tmargin-top: 20px;
  3449. \t\t\t\tmargin-bottom: 0;
  3450. \t\t\t}
  3451. \t\t\t@media(max-width: 768px) {
  3452. \t\t\t\t.flash-message {
  3453. \t\t\t\t\tpadding: 14px 16px !important;
  3454. \t\t\t\t\tfont-size: 0.9rem;
  3455. \t\t\t\t}
  3456. \t\t\t\t.flash-message i {
  3457. \t\t\t\t\tfont-size: 1.2rem !important;
  3458. \t\t\t\t}
  3459. \t\t\t}
  3460. \t\t\t/* Styles pour l'icône de comparaison */
  3461. \t\t\t.comparison-icon {
  3462. \t\t\t\tposition: relative;
  3463. \t\t\t\tdisplay: inline-block;
  3464. \t\t\t\tcolor: #333;
  3465. \t\t\t\ttext-decoration: none;
  3466. \t\t\t\ttransition: all 0.3s ease;
  3467. \t\t\t}
  3468. \t\t\t.comparison-icon:hover {
  3469. \t\t\t\tcolor: #ffa200;
  3470. \t\t\t}
  3471. \t\t\t.comparison-badge {
  3472. \t\t\t\tposition: absolute;
  3473. \t\t\t\ttop: -4px;
  3474. \t\t\t\tright: -2px;
  3475. \t\t\t\tbackground: #095ad3 !important;
  3476. \t\t\t\tcolor: white !important;
  3477. \t\t\t\tborder-radius: 50%;
  3478. \t\t\t\twidth: 18px;
  3479. \t\t\t\theight: 18px;
  3480. \t\t\t\tfont-size: 8px !important;
  3481. \t\t\t\tdisplay: flex !important;
  3482. \t\t\t\talign-items: center !important;
  3483. \t\t\t\tjustify-content: center !important;
  3484. \t\t\t\tfont-weight: bold !important;
  3485. \t\t\t\tanimation: pulse 2s infinite;
  3486. \t\t\t\tz-index: 10;
  3487. \t\t\t\tline-height: 1 !important;
  3488. \t\t\t}
  3489. \t\t\t/* Correction de l'alignement des boutons actifs dans prd-bottom */
  3490. \t\t\t/* Ne s'applique qu'aux boutons actifs pour éviter de casser le comportement hover */
  3491. \t\t\t.single-product .product-details .prd-bottom .social-info.active {
  3492. \t\t\t\tvertical-align: middle !important;
  3493. \t\t\t\tposition: relative !important;
  3494. \t\t\t\ttop: 0 !important;
  3495. \t\t\t\ttransform: none !important;
  3496. \t\t\t\tmargin: 0 !important;
  3497. \t\t\t\tpadding: 0 !important;
  3498. \t\t\t\tline-height: normal !important;
  3499. \t\t\t\twidth: 35px !important;
  3500. \t\t\t\theight: auto !important;
  3501. \t\t\t\tmin-height: auto !important;
  3502. \t\t\t\tmax-height: none !important;
  3503. \t\t\t}
  3504. \t\t\t.single-product .product-details .prd-bottom .social-info.wishlist-btn.active,
  3505. \t\t\t.single-product .product-details .prd-bottom .social-info.comparison-btn.active {
  3506. \t\t\t\tvertical-align: middle !important;
  3507. \t\t\t\tposition: relative !important;
  3508. \t\t\t\ttop: 0 !important;
  3509. \t\t\t\ttransform: none !important;
  3510. \t\t\t\tmargin: 0 !important;
  3511. \t\t\t\tpadding: 0 !important;
  3512. \t\t\t\tline-height: normal !important;
  3513. \t\t\t\twidth: 35px !important;
  3514. \t\t\t\theight: auto !important;
  3515. \t\t\t\tmin-height: auto !important;
  3516. \t\t\t\tmax-height: none !important;
  3517. \t\t\t}
  3518. \t\t\t.single-product .product-details .prd-bottom .social-info.active .hover-text {
  3519. \t\t\t\tmargin: 0 !important;
  3520. \t\t\t\tpadding: 0 !important;
  3521. \t\t\t\tline-height: normal !important;
  3522. \t\t\t\tposition: absolute !important;
  3523. \t\t\t\ttop: 0 !important;
  3524. \t\t\t\tbackground: #ffa200 !important;
  3525. \t\t\t\tleft: -40px !important;
  3526. \t\t\t}
  3527. \t\t\t/* S'assurer qu'aucune marge supplémentaire n'est ajoutée quand un bouton est actif */
  3528. \t\t\t.single-product .product-details .prd-bottom .social-info.active span,
  3529. \t\t\t.single-product .product-details .prd-bottom .social-info.active p {
  3530. \t\t\t\tmargin: 0 !important;
  3531. \t\t\t\tpadding: 0 !important;
  3532. \t\t\t}
  3533. \t\t\t/* Empêcher le hover de changer la largeur quand le bouton est actif */
  3534. \t\t\t.single-product .product-details .prd-bottom .social-info.active:hover {
  3535. \t\t\t\twidth: 35px !important;
  3536. \t\t\t}
  3537. \t\t\t.comparison-icon:hover .comparison-badge {
  3538. \t\t\t\tanimation: none;
  3539. \t\t\t}
  3540. \t\t\t/* Styles pour les mega-menus - style comme la barre de recherche */
  3541. \t\t\t.mega-menu {
  3542. \t\t\t\twidth: 100%;
  3543. \t\t\t\tmax-width: 1200px;
  3544. \t\t\t\tleft: 50%;
  3545. \t\t\t\ttransform: translateX(-50%);
  3546. \t\t\t\tpadding: 25px;
  3547. \t\t\t\tborder-radius: 12px;
  3548. \t\t\t\tbox-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
  3549. \t\t\t\tborder: none;
  3550. \t\t\t\tbackground: white;
  3551. \t\t\t\tdisplay: none;
  3552. \t\t\t\tposition: absolute;
  3553. \t\t\t\ttop: 100%;
  3554. \t\t\t\tz-index: 9999 !important;
  3555. \t\t\t\tmargin-top: 10px;
  3556. \t\t\t\topacity: 0;
  3557. \t\t\t\tvisibility: hidden;
  3558. \t\t\t\ttransition: opacity 0.3s ease, visibility 0.3s ease, transform 0.3s ease;
  3559. \t\t\t}
  3560. \t\t\t.mega-menu.active {
  3561. \t\t\t\tdisplay: block;
  3562. \t\t\t\topacity: 1;
  3563. \t\t\t\tvisibility: visible;
  3564. \t\t\t\ttransform: translateX(-50%) translateY(0);
  3565. \t\t\t}
  3566. \t\t\t.nav-item.dropdown {
  3567. \t\t\t\tposition: relative !important;
  3568. \t\t\t}
  3569. \t\t\t@media(min-width: 768px) {
  3570. \t\t\t\t.nav-item.dropdown {
  3571. \t\t\t\t\tposition: relative !important;
  3572. \t\t\t\t}
  3573. \t\t\t\t.mega-menu {
  3574. \t\t\t\t\tposition: absolute !important;
  3575. \t\t\t\t\tleft: 50% !important;
  3576. \t\t\t\t\ttransform: translateX(-50%) !important;
  3577. \t\t\t\t\twidth: auto !important;
  3578. \t\t\t\t\tmin-width: 600px !important;
  3579. \t\t\t\t}
  3580. \t\t\t}
  3581. \t\t\t/* Correction supplémentaire pour l'affichage sur la page d'accueil */
  3582. \t\t\tbody.home .nav-item.dropdown,
  3583. \t\t\t.nav-item.dropdown {
  3584. \t\t\t\tposition: relative !important;
  3585. \t\t\t}
  3586. \t\t\tbody.home .mega-menu,
  3587. \t\t\t.mega-menu {
  3588. \t\t\t\tposition: absolute !important;
  3589. \t\t\t\tleft: 50% !important;
  3590. \t\t\t\ttransform: translateX(-50%) translateY(0) !important;
  3591. \t\t\t\twidth: auto !important;
  3592. \t\t\t\tmin-width: 600px !important;
  3593. \t\t\t\tmax-width: 90% !important;
  3594. \t\t\t\ttop: 100% !important;
  3595. \t\t\t\tmargin-top: 10px !important;
  3596. \t\t\t}
  3597. \t\t\t/* Assurer que les mega-menus sont toujours visibles au survol */
  3598. \t\t\t.nav-item.dropdown:hover .mega-menu {
  3599. \t\t\t\topacity: 1 !important;
  3600. \t\t\t\tvisibility: visible !important;
  3601. \t\t\t\tdisplay: block !important;
  3602. \t\t\t\ttransform: translateX(-50%) translateY(0) !important;
  3603. \t\t\t}
  3604. \t\t\t.mega-menu .dropdown-item {
  3605. \t\t\t\tpadding: 0;
  3606. \t\t\t\tborder: none;
  3607. \t\t\t}
  3608. \t\t\t.mega-menu .dropdown-header {
  3609. \t\t\t\tfont-weight: 700;
  3610. \t\t\t\tcolor: #2c3e50;
  3611. \t\t\t\tmargin-bottom: 18px;
  3612. \t\t\t\tpadding-bottom: 10px;
  3613. \t\t\t\tborder-bottom: 3px solid #3498db;
  3614. \t\t\t\tfont-size: 16px;
  3615. \t\t\t\ttext-transform: uppercase;
  3616. \t\t\t\tletter-spacing: 0.5px;
  3617. \t\t\t}
  3618. \t\t\t.mega-menu .dropdown-item a {
  3619. \t\t\t\tdisplay: block;
  3620. \t\t\t\tpadding: 10px 15px;
  3621. \t\t\t\tcolor: #555;
  3622. \t\t\t\ttext-decoration: none;
  3623. \t\t\t\tborder-radius: 6px;
  3624. \t\t\t\ttransition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  3625. \t\t\t\tposition: relative;
  3626. \t\t\t\toverflow: hidden;
  3627. \t\t\t}
  3628. \t\t\t.mega-menu .dropdown-item a::before {
  3629. \t\t\t\tcontent: '';
  3630. \t\t\t\tposition: absolute;
  3631. \t\t\t\ttop: 0;
  3632. \t\t\t\tleft: -100%;
  3633. \t\t\t\twidth: 100%;
  3634. \t\t\t\theight: 100%;
  3635. \t\t\t\tbackground: linear-gradient(90deg, transparent, rgba(52, 152, 219, 0.1), transparent);
  3636. \t\t\t\ttransition: left 0.5s;
  3637. \t\t\t}
  3638. \t\t\t.mega-menu .dropdown-item a:hover::before {
  3639. \t\t\t\tleft: 100%;
  3640. \t\t\t}
  3641. \t\t\t.mega-menu .dropdown-item a:hover {
  3642. \t\t\t\tbackground: linear-gradient(135deg, #f8f9fa, #e3f2fd);
  3643. \t\t\t\tcolor: #2980b9;
  3644. \t\t\t\ttransform: translateX(8px);
  3645. \t\t\t\tbox-shadow: 0 2px 8px rgba(52, 152, 219, 0.2);
  3646. \t\t\t}
  3647. \t\t\t.mega-menu .dropdown-item a i {
  3648. \t\t\t\twidth: 22px;
  3649. \t\t\t\ttext-align: center;
  3650. \t\t\t\tmargin-right: 8px;
  3651. \t\t\t\tcolor: #3498db;
  3652. \t\t\t\ttransition: color 0.3s ease;
  3653. \t\t\t}
  3654. \t\t\t.mega-menu .dropdown-item a:hover i {
  3655. \t\t\t\tcolor: #2980b9;
  3656. \t\t\t}
  3657. \t\t\t/* Animation d'apparition améliorée */
  3658. \t\t\t@keyframes slideInDown {
  3659. \t\t\t\tfrom {
  3660. \t\t\t\t\topacity: 0;
  3661. \t\t\t\t\ttransform: translateY(-20px);
  3662. \t\t\t\t}
  3663. \t\t\t\tto {
  3664. \t\t\t\t\topacity: 1;
  3665. \t\t\t\t\ttransform: translateY(0);
  3666. \t\t\t\t}
  3667. \t\t\t}
  3668. \t\t\t.mega-menu {
  3669. \t\t\t\tanimation: slideInDown 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  3670. \t\t\t}
  3671. \t\t\t/* Effet de survol sur le lien principal */
  3672. \t\t\t.nav-item.dropdown .nav-link {
  3673. \t\t\t\tposition: relative;
  3674. \t\t\t\ttransition: all 0.3s ease;
  3675. \t\t\t}
  3676. \t\t\t.nav-item.dropdown .nav-link::after {
  3677. \t\t\t\tcontent: '';
  3678. \t\t\t\tposition: absolute;
  3679. \t\t\t\tbottom: -2px;
  3680. \t\t\t\tleft: 50%;
  3681. \t\t\t\twidth: 0;
  3682. \t\t\t\theight: 2px;
  3683. \t\t\t\tbackground: linear-gradient(90deg, #3498db, #2980b9);
  3684. \t\t\t\ttransition: all 0.3s ease;
  3685. \t\t\t\ttransform: translateX(-50%);
  3686. \t\t\t}
  3687. \t\t\t.nav-item.dropdown:hover .nav-link::after {
  3688. \t\t\t\twidth: 100%;
  3689. \t\t\t}
  3690. \t\t\t.nav-item.dropdown:hover .nav-link {
  3691. \t\t\t\tcolor: #2980b9;
  3692. \t\t\t}
  3693. \t\t\t@keyframes fadeInDown {
  3694. \t\t\t\tfrom {
  3695. \t\t\t\t\topacity: 0;
  3696. \t\t\t\t\ttransform: translateY(-10px);
  3697. \t\t\t\t}
  3698. \t\t\t\tto {
  3699. \t\t\t\t\topacity: 1;
  3700. \t\t\t\t\ttransform: translateY(0);
  3701. \t\t\t\t}
  3702. \t\t\t}
  3703. \t\t\t/* Responsive */
  3704. \t\t\t@media(max-width: 768px) {
  3705. \t\t\t\t.mega-menu {
  3706. \t\t\t\t\twidth: 100%;
  3707. \t\t\t\t\tleft: 0;
  3708. \t\t\t\t\tpadding: 15px;
  3709. \t\t\t\t}
  3710. \t\t\t\t.mega-menu .row {
  3711. \t\t\t\t\tmargin: 0;
  3712. \t\t\t\t}
  3713. \t\t\t\t.mega-menu .col-md-3 {
  3714. \t\t\t\t\tmargin-bottom: 20px;
  3715. \t\t\t\t}
  3716. \t\t\t}
  3717. \t\t\t/* ============================================
  3718. \t\t\t.footer-area {
  3719. \t\t\t\tbackground: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
  3720. \t\t\t\tposition: relative;
  3721. \t\t\t\toverflow: hidden;
  3722. \t\t\t\tpadding: 50px 0 20px;
  3723. \t\t\t}
  3724. \t\t\t.footer-pattern {
  3725. \t\t\t\tposition: absolute;
  3726. \t\t\t\ttop: 0;
  3727. \t\t\t\tleft: 0;
  3728. \t\t\t\tright: 0;
  3729. \t\t\t\tbottom: 0;
  3730. \t\t\t\tbackground-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%);
  3731. \t\t\t\tpointer-events: none;
  3732. \t\t\t}
  3733. \t\t\t.footer-area .container {
  3734. \t\t\t\tposition: relative;
  3735. \t\t\t\tz-index: 1;
  3736. \t\t\t}
  3737. \t\t\t/* Widgets */
  3738. \t\t\t.single-footer-widget {
  3739. \t\t\t\tcolor: rgba(255, 255, 255, 0.9);
  3740. \t\t\t}
  3741. \t\t\t.footer-brand {
  3742. \t\t\t\tfont-size: 1.6rem;
  3743. \t\t\t\tfont-weight: 700;
  3744. \t\t\t\tbackground: linear-gradient(135deg, #ffa200 0%, #e8910a 100%);
  3745. \t\t\t\t-webkit-background-clip: text;
  3746. \t\t\t\t-webkit-text-fill-color: transparent;
  3747. \t\t\t\tbackground-clip: text;
  3748. \t\t\t\tmargin-bottom: 12px;
  3749. \t\t\t\tdisplay: inline-block;
  3750. \t\t\t}
  3751. \t\t\t.footer-widget-title {
  3752. \t\t\t\tcolor: #fff;
  3753. \t\t\t\tfont-size: 1rem;
  3754. \t\t\t\tfont-weight: 600;
  3755. \t\t\t\tmargin-bottom: 18px;
  3756. \t\t\t\tposition: relative;
  3757. \t\t\t\tpadding-bottom: 8px;
  3758. \t\t\t}
  3759. \t\t\t.footer-widget-title::after {
  3760. \t\t\t\tcontent: '';
  3761. \t\t\t\tposition: absolute;
  3762. \t\t\t\tbottom: 0;
  3763. \t\t\t\tleft: 0;
  3764. \t\t\t\twidth: 40px;
  3765. \t\t\t\theight: 3px;
  3766. \t\t\t\tbackground: linear-gradient(135deg, #ffa200 0%, #e8910a 100%);
  3767. \t\t\t\tborder-radius: 2px;
  3768. \t\t\t}
  3769. \t\t\t.footer-description {
  3770. \t\t\t\tcolor: rgba(255, 255, 255, 0.7);
  3771. \t\t\t\tline-height: 1.6;
  3772. \t\t\t\tfont-size: 0.9rem;
  3773. \t\t\t\tmargin-bottom: 0;
  3774. \t\t\t}
  3775. \t\t\t/* Liste de liens */
  3776. \t\t\t.footer-list {
  3777. \t\t\t\tlist-style: none;
  3778. \t\t\t\tpadding: 0;
  3779. \t\t\t\tmargin: 0;
  3780. \t\t\t}
  3781. \t\t\t.footer-list li {
  3782. \t\t\t\tmargin-bottom: 10px;
  3783. \t\t\t}
  3784. \t\t\t.footer-list li a {
  3785. \t\t\t\tcolor: rgba(255, 255, 255, 0.7);
  3786. \t\t\t\ttext-decoration: none;
  3787. \t\t\t\ttransition: all 0.3s ease;
  3788. \t\t\t\tfont-size: 0.9rem;
  3789. \t\t\t\tdisplay: inline-flex;
  3790. \t\t\t\talign-items: center;
  3791. \t\t\t}
  3792. \t\t\t.footer-list li a i {
  3793. \t\t\t\tfont-size: 0.8rem;
  3794. \t\t\t\topacity: 0.6;
  3795. \t\t\t\ttransition: all 0.3s ease;
  3796. \t\t\t}
  3797. \t\t\t.footer-list li a:hover {
  3798. \t\t\t\tcolor: #ffa200;
  3799. \t\t\t\ttransform: translateX(5px);
  3800. \t\t\t}
  3801. \t\t\t.footer-list li a:hover i {
  3802. \t\t\t\topacity: 1;
  3803. \t\t\t\tcolor: #ffa200;
  3804. \t\t\t}
  3805. \t\t\t/* Newsletter */
  3806. \t\t\t.footer-newsletter-text {
  3807. \t\t\t\tcolor: rgba(255, 255, 255, 0.7);
  3808. \t\t\t\tfont-size: 0.85rem;
  3809. \t\t\t\tmargin-bottom: 15px;
  3810. \t\t\t\tline-height: 1.5;
  3811. \t\t\t}
  3812. \t\t\t.footer-newsletter-wrapper {
  3813. \t\t\t\tmargin-bottom: 15px;
  3814. \t\t\t}
  3815. \t\t\t.newsletter-input-group {
  3816. \t\t\t\tdisplay: flex;
  3817. \t\t\t\talign-items: center;
  3818. \t\t\t\tbackground: rgba(255, 255, 255, 0.08);
  3819. \t\t\t\tborder-radius: 30px;
  3820. \t\t\t\tpadding: 4px 4px 4px 15px;
  3821. \t\t\t\tbackdrop-filter: blur(10px);
  3822. \t\t\t\tborder: 1px solid rgba(255, 255, 255, 0.15);
  3823. \t\t\t\ttransition: all 0.3s ease;
  3824. \t\t\t\tgap: 8px;
  3825. \t\t\t}
  3826. \t\t\t.newsletter-input-group:focus-within {
  3827. \t\t\t\tbackground: rgba(255, 255, 255, 0.12);
  3828. \t\t\t\tborder-color: rgba(255, 162, 0, 0.6);
  3829. \t\t\t\tbox-shadow: 0 0 0 2px rgba(255, 162, 0, 0.15);
  3830. \t\t\t}
  3831. \t\t\t.newsletter-icon {
  3832. \t\t\t\tcolor: rgba(255, 255, 255, 0.5);
  3833. \t\t\t\tfont-size: 0.9rem;
  3834. \t\t\t\tflex-shrink: 0;
  3835. \t\t\t}
  3836. \t\t\t.newsletter-input-group:focus-within .newsletter-icon {
  3837. \t\t\t\tcolor: #ffa200;
  3838. \t\t\t}
  3839. \t\t\t.newsletter-input {
  3840. \t\t\t\tflex: 1;
  3841. \t\t\t\tbackground: transparent;
  3842. \t\t\t\tborder: none;
  3843. \t\t\t\tcolor: #fff;
  3844. \t\t\t\tpadding: 10px 8px;
  3845. \t\t\t\tfont-size: 0.9rem;
  3846. \t\t\t\tmin-width: 0;
  3847. \t\t\t}
  3848. \t\t\t.newsletter-input::placeholder {
  3849. \t\t\t\tcolor: rgba(255, 255, 255, 0.4);
  3850. \t\t\t\tfont-size: 0.85rem;
  3851. \t\t\t}
  3852. \t\t\t.newsletter-input:focus {
  3853. \t\t\t\toutline: none;
  3854. \t\t\t\tbox-shadow: none;
  3855. \t\t\t}
  3856. \t\t\t.newsletter-btn {
  3857. \t\t\t\tbackground: linear-gradient(135deg, #ffa200 0%, #e8910a 100%);
  3858. \t\t\t\tborder: none;
  3859. \t\t\t\tcolor: white;
  3860. \t\t\t\twidth: 42px;
  3861. \t\t\t\theight: 42px;
  3862. \t\t\t\tmin-width: 42px;
  3863. \t\t\t\tmin-height: 42px;
  3864. \t\t\t\tborder-radius: 50%;
  3865. \t\t\t\tdisplay: flex;
  3866. \t\t\t\talign-items: center;
  3867. \t\t\t\tjustify-content: center;
  3868. \t\t\t\tcursor: pointer;
  3869. \t\t\t\ttransition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  3870. \t\t\t\tflex-shrink: 0;
  3871. \t\t\t\tbox-shadow: 0 4px 15px rgba(255, 162, 0, 0.4), 0 0 0 0 rgba(255, 162, 0, 0.4);
  3872. \t\t\t\tfont-size: 0.9rem;
  3873. \t\t\t\tposition: relative;
  3874. \t\t\t\toverflow: hidden;
  3875. \t\t\t}
  3876. \t\t\t.newsletter-btn::before {
  3877. \t\t\t\tcontent: '';
  3878. \t\t\t\tposition: absolute;
  3879. \t\t\t\ttop: 50%;
  3880. \t\t\t\tleft: 50%;
  3881. \t\t\t\twidth: 0;
  3882. \t\t\t\theight: 0;
  3883. \t\t\t\tborder-radius: 50%;
  3884. \t\t\t\tbackground: rgba(255, 255, 255, 0.3);
  3885. \t\t\t\ttransform: translate(-50%, -50%);
  3886. \t\t\t\ttransition: width 0.6s ease, height 0.6s ease;
  3887. \t\t\t}
  3888. \t\t\t.newsletter-btn:hover::before {
  3889. \t\t\t\twidth: 100%;
  3890. \t\t\t\theight: 100%;
  3891. \t\t\t}
  3892. \t\t\t.newsletter-btn:hover {
  3893. \t\t\t\ttransform: translateX(3px) scale(1.05);
  3894. \t\t\t\tbox-shadow: 0 6px 20px rgba(255, 162, 0, 0.5), 0 0 0 8px rgba(255, 162, 0, 0.1);
  3895. \t\t\t\tbackground: linear-gradient(135deg, #e8910a 0%, #ffa200 100%);
  3896. \t\t\t}
  3897. \t\t\t.newsletter-btn:active {
  3898. \t\t\t\ttransform: translateX(3px) scale(0.98);
  3899. \t\t\t\tbox-shadow: 0 3px 10px rgba(255, 162, 0, 0.4);
  3900. \t\t\t}
  3901. \t\t\t.newsletter-btn:focus {
  3902. \t\t\t\toutline: none;
  3903. \t\t\t\tbox-shadow: 0 4px 15px rgba(255, 162, 0, 0.4), 0 0 0 3px rgba(255, 162, 0, 0.3);
  3904. \t\t\t}
  3905. \t\t\t.newsletter-btn-icon,
  3906. \t\t\t.newsletter-btn-loader {
  3907. \t\t\t\tposition: relative;
  3908. \t\t\t\tz-index: 2;
  3909. \t\t\t\tdisplay: flex;
  3910. \t\t\t\talign-items: center;
  3911. \t\t\t\tjustify-content: center;
  3912. \t\t\t\ttransition: all 0.3s ease;
  3913. \t\t\t}
  3914. \t\t\t.newsletter-btn:hover .newsletter-btn-icon {
  3915. \t\t\t\ttransform: translateX(2px) rotate(-10deg);
  3916. \t\t\t}
  3917. \t\t\t.newsletter-btn.loading .newsletter-btn-icon {
  3918. \t\t\t\topacity: 0;
  3919. \t\t\t\ttransform: scale(0);
  3920. \t\t\t}
  3921. \t\t\t.newsletter-btn.loading .newsletter-btn-loader {
  3922. \t\t\t\tdisplay: flex !important;
  3923. \t\t\t}
  3924. \t\t\t.newsletter-btn.success {
  3925. \t\t\t\tbackground: linear-gradient(135deg, #28a745 0%, #20c997 100%);
  3926. \t\t\t\tbox-shadow: 0 4px 15px rgba(40, 167, 69, 0.4);
  3927. \t\t\t}
  3928. \t\t\t.newsletter-btn.success .newsletter-btn-icon i::before {
  3929. \t\t\t\tcontent: \"\\f00c\";
  3930. \t\t\t}
  3931. \t\t\t/* Trust badges */
  3932. \t\t\t.footer-trust-badges {
  3933. \t\t\t\tdisplay: flex;
  3934. \t\t\t\tflex-direction: row;
  3935. \t\t\t\tgap: 15px;
  3936. \t\t\t\tflex-wrap: wrap;
  3937. \t\t\t}
  3938. \t\t\t.trust-item {
  3939. \t\t\t\tdisplay: flex;
  3940. \t\t\t\talign-items: center;
  3941. \t\t\t\tgap: 6px;
  3942. \t\t\t\tcolor: rgba(255, 255, 255, 0.6);
  3943. \t\t\t\tfont-size: 0.8rem;
  3944. \t\t\t}
  3945. \t\t\t.trust-item i {
  3946. \t\t\t\tcolor: #ffa200;
  3947. \t\t\t\tfont-size: 0.9rem;
  3948. \t\t\t}
  3949. \t\t\t/* Social icons */
  3950. \t\t\t.footer-social {
  3951. \t\t\t\tmargin-top: 0 !important;
  3952. \t\t\t\tposition: relative !important;
  3953. \t\t\t\twidth: 100% !important;
  3954. \t\t\t\tclear: both !important;
  3955. \t\t\t\tfloat: none !important;
  3956. \t\t\t}
  3957. \t\t\t.footer-social h6 {
  3958. \t\t\t\tcolor: #fff;
  3959. \t\t\t\tfont-size: 0.95rem;
  3960. \t\t\t\tfont-weight: 600;
  3961. \t\t\t\tmargin-bottom: 12px !important;
  3962. \t\t\t\tdisplay: block !important;
  3963. \t\t\t\twidth: 100% !important;
  3964. \t\t\t\tposition: relative !important;
  3965. \t\t\t\tclear: both !important;
  3966. \t\t\t\tfloat: none !important;
  3967. \t\t\t}
  3968. \t\t\t.footer-social-icons {
  3969. \t\t\t\tdisplay: flex !important;
  3970. \t\t\t\tgap: 12px !important;
  3971. \t\t\t\tflex-wrap: wrap !important;
  3972. \t\t\t\talign-items: center !important;
  3973. \t\t\t\tjustify-content: flex-start !important;
  3974. \t\t\t\twidth: 100% !important;
  3975. \t\t\t\tposition: relative !important;
  3976. \t\t\t\tclear: both !important;
  3977. \t\t\t\tfloat: none !important;
  3978. \t\t\t\tmargin: 0 !important;
  3979. \t\t\t\tpadding: 0 !important;
  3980. \t\t\t}
  3981. \t\t\t.social-icon {
  3982. \t\t\t\twidth: 38px !important;
  3983. \t\t\t\theight: 38px !important;
  3984. \t\t\t\tmin-width: 38px !important;
  3985. \t\t\t\tmin-height: 38px !important;
  3986. \t\t\t\tdisplay: inline-flex !important;
  3987. \t\t\t\talign-items: center !important;
  3988. \t\t\t\tjustify-content: center !important;
  3989. \t\t\t\tbackground: rgba(255, 255, 255, 0.1) !important;
  3990. \t\t\t\tborder-radius: 50% !important;
  3991. \t\t\t\tcolor: rgba(255, 255, 255, 0.8) !important;
  3992. \t\t\t\ttext-decoration: none !important;
  3993. \t\t\t\ttransition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
  3994. \t\t\t\tfont-size: 16px !important;
  3995. \t\t\t\tline-height: 1 !important;
  3996. \t\t\t\tbackdrop-filter: blur(10px) !important;
  3997. \t\t\t\tborder: 1px solid rgba(255, 255, 255, 0.1) !important;
  3998. \t\t\t\tflex-shrink: 0 !important;
  3999. \t\t\t\tposition: relative !important;
  4000. \t\t\t\tfloat: none !important;
  4001. \t\t\t\tmargin: 0 !important;
  4002. \t\t\t\tpadding: 0 !important;
  4003. \t\t\t\tvertical-align: middle !important;
  4004. \t\t\t}
  4005. \t\t\t.social-icon i {
  4006. \t\t\t\tfont-size: 16px !important;
  4007. \t\t\t\tline-height: 1 !important;
  4008. \t\t\t\tdisplay: inline-block !important;
  4009. \t\t\t\ttransition: transform 0.3s ease !important;
  4010. \t\t\t\tposition: relative !important;
  4011. \t\t\t\tz-index: 1 !important;
  4012. \t\t\t\tmargin: 0 !important;
  4013. \t\t\t\tpadding: 0 !important;
  4014. \t\t\t}
  4015. \t\t\t.social-icon:hover {
  4016. \t\t\t\tbackground: linear-gradient(135deg, #ffa200 0%, #e8910a 100%) !important;
  4017. \t\t\t\ttransform: translateY(-5px) scale(1.1) !important;
  4018. \t\t\t\tcolor: white !important;
  4019. \t\t\t\tborder-color: transparent !important;
  4020. \t\t\t\tbox-shadow: 0 8px 20px rgba(255, 162, 0, 0.4) !important;
  4021. \t\t\t}
  4022. \t\t\t.social-icon:hover i {
  4023. \t\t\t\ttransform: scale(1.1) !important;
  4024. \t\t\t}
  4025. \t\t\t/* Footer divider */
  4026. \t\t\t.footer-divider {
  4027. \t\t\t\theight: 1px;
  4028. \t\t\t\tbackground: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
  4029. \t\t\t\tmargin: 30px 0 20px;
  4030. \t\t\t}
  4031. \t\t\t/* Footer bottom */
  4032. \t\t\t.footer-bottom {
  4033. \t\t\t\tpadding-top: 15px;
  4034. \t\t\t}
  4035. \t\t\t.footer-text {
  4036. \t\t\t\tcolor: rgba(255, 255, 255, 0.6);
  4037. \t\t\t\tfont-size: 0.9rem;
  4038. \t\t\t\tmargin: 0;
  4039. \t\t\t\ttext-align: center;
  4040. \t\t\t}
  4041. \t\t\t/* Responsive */
  4042. \t\t\t@media(max-width: 991.98px) {
  4043. \t\t\t\t.footer-area {
  4044. \t\t\t\t\tpadding: 40px 0 20px;
  4045. \t\t\t\t}
  4046. \t\t\t\t.single-footer-widget {
  4047. \t\t\t\t\tmargin-bottom: 30px;
  4048. \t\t\t\t}
  4049. \t\t\t\t.footer-social {
  4050. \t\t\t\t\tmargin-top: 15px;
  4051. \t\t\t\t}
  4052. \t\t\t}
  4053. \t\t\t@media(max-width: 767.98px) {
  4054. \t\t\t\t.footer-area {
  4055. \t\t\t\t\tpadding: 35px 0 18px;
  4056. \t\t\t\t}
  4057. \t\t\t\t.footer-brand {
  4058. \t\t\t\t\tfont-size: 1.4rem;
  4059. \t\t\t\t}
  4060. \t\t\t\t.footer-widget-title {
  4061. \t\t\t\t\tfont-size: 0.95rem;
  4062. \t\t\t\t}
  4063. \t\t\t\t.newsletter-input-group {
  4064. \t\t\t\t\tpadding: 3px 3px 3px 12px;
  4065. \t\t\t\t}
  4066. \t\t\t\t.newsletter-input {
  4067. \t\t\t\t\tpadding: 8px 6px;
  4068. \t\t\t\t\tfont-size: 0.85rem;
  4069. \t\t\t\t}
  4070. \t\t\t\t.newsletter-btn {
  4071. \t\t\t\t\twidth: 38px;
  4072. \t\t\t\t\theight: 38px;
  4073. \t\t\t\t\tmin-width: 38px;
  4074. \t\t\t\t\tmin-height: 38px;
  4075. \t\t\t\t\tfont-size: 0.85rem;
  4076. \t\t\t\t}
  4077. \t\t\t\t.footer-trust-badges {
  4078. \t\t\t\t\tflex-direction: row;
  4079. \t\t\t\t\tflex-wrap: wrap;
  4080. \t\t\t\t\tjustify-content: flex-start;
  4081. \t\t\t\t\tgap: 12px;
  4082. \t\t\t\t}
  4083. \t\t\t}
  4084. \t\t\t@media(max-width: 575.98px) {
  4085. \t\t\t\t.footer-area {
  4086. \t\t\t\t\tpadding: 40px 0 20px;
  4087. \t\t\t\t}
  4088. \t\t\t\t.footer-brand {
  4089. \t\t\t\t\tfont-size: 1.3rem;
  4090. \t\t\t\t}
  4091. \t\t\t\t.social-icon {
  4092. \t\t\t\t\twidth: 38px;
  4093. \t\t\t\t\theight: 38px;
  4094. \t\t\t\t\tfont-size: 16px;
  4095. \t\t\t\t}
  4096. \t\t\t\t.social-icon i {
  4097. \t\t\t\t\tfont-size: 16px;
  4098. \t\t\t\t}
  4099. \t\t\t}
  4100. \t\t</style>
  4101. \t\t{% block stylesheets %}
  4102. \t\t\t{{ encore_entry_link_tags('app') }}
  4103. \t\t{% endblock %}
  4104. \t\t<!-- Script pour forcer l'application des styles CSS après chargement -->
  4105. \t\t<script>
  4106. \t\t\tdocument.addEventListener('DOMContentLoaded', function () { // Forcer le masquage du toggle sur grands écrans
  4107. if (window.innerWidth >= 992) {
  4108. const togglers = document.querySelectorAll('.navbar-toggler, .header_area .navbar .navbar-toggler');
  4109. togglers.forEach(function (toggler) {
  4110. if (toggler) {
  4111. toggler.style.display = 'none';
  4112. toggler.style.visibility = 'hidden';
  4113. toggler.style.opacity = '0';
  4114. toggler.style.width = '0';
  4115. toggler.style.height = '0';
  4116. toggler.style.padding = '0';
  4117. toggler.style.margin = '0';
  4118. toggler.style.border = 'none';
  4119. toggler.style.position = 'absolute';
  4120. toggler.style.left = '-9999px';
  4121. }
  4122. });
  4123. const iconBars = document.querySelectorAll('.navbar-toggler .icon-bar, .header_area .navbar .navbar-toggler .icon-bar, .navbar-toggler-icon');
  4124. iconBars.forEach(function (bar) {
  4125. if (bar) {
  4126. bar.style.display = 'none';
  4127. bar.style.visibility = 'hidden';
  4128. }
  4129. });
  4130. }
  4131. // Alignement des icônes navbar sur mobile
  4132. const navbarRight = document.querySelectorAll('.navbar-right, .header_area .navbar .nav.navbar-nav.navbar-right');
  4133. navbarRight.forEach(function (nav) {
  4134. if (nav && window.innerWidth<= 991.98) {
  4135.                     // Mobile: colonne avec icônes alignées horizontalement
  4136.                     nav.style.display = 'flex';
  4137.                     nav.style.flexDirection = 'column';
  4138.                     nav.style.alignItems = 'center';
  4139.                     nav.style.textAlign = 'center';
  4140.                     
  4141.                     // Le container d'icônes reste horizontal
  4142.                     const iconsContainer = nav.querySelector('.navbar-icons-wrapper');
  4143.                     if (iconsContainer) {
  4144.                         iconsContainer.style.display = 'flex';
  4145.                         iconsContainer.style.flexDirection = 'row';
  4146.                         iconsContainer.style.justifyContent = 'center';
  4147.                     }
  4148.                     
  4149.                     // Le bouton compte en bas
  4150.                     const accountBtn = nav.querySelector('li:last-child');
  4151.                     if (accountBtn) {
  4152.                         accountBtn.style.width = '100%';
  4153.                         accountBtn.style.display = 'flex';
  4154.                         accountBtn.style.justifyContent = 'center';
  4155.                         accountBtn.style.marginTop = '12px';
  4156.                         accountBtn.style.paddingTop = '12px';
  4157.                         accountBtn.style.borderTop = '1px solid #e0e0e0';
  4158.                     }
  4159.                 } else if (nav && window.innerWidth> 991.98) { // Desktop: alignement horizontal normal
  4160. nav.style.display = 'flex';
  4161. nav.style.flexDirection = 'row';
  4162. nav.style.alignItems = 'center';
  4163. nav.style.justifyContent = 'flex-end';
  4164. }
  4165. });
  4166. });
  4167. // Réappliquer lors du redimensionnement
  4168. window.addEventListener('resize', function () {
  4169. if (window.innerWidth >= 992) {
  4170. const togglers = document.querySelectorAll('.navbar-toggler, .header_area .navbar .navbar-toggler');
  4171. togglers.forEach(function (toggler) {
  4172. if (toggler) {
  4173. toggler.style.display = 'none';
  4174. toggler.style.visibility = 'hidden';
  4175. }
  4176. });
  4177. }
  4178. // Réappliquer l'alignement des icônes navbar
  4179. const navbarRight = document.querySelectorAll('.navbar-right, .header_area .navbar .nav.navbar-nav.navbar-right');
  4180. navbarRight.forEach(function (nav) {
  4181. if (nav && window.innerWidth<= 991.98) {
  4182.                     // Mobile: colonne avec icônes alignées horizontalement
  4183.                     nav.style.display = 'flex';
  4184.                     nav.style.flexDirection = 'column';
  4185.                     nav.style.alignItems = 'center';
  4186.                     nav.style.textAlign = 'center';
  4187.                     
  4188.                     // Le container d'icônes reste horizontal
  4189.                     const iconsContainer = nav.querySelector('.navbar-icons-wrapper');
  4190.                     if (iconsContainer) {
  4191.                         iconsContainer.style.display = 'flex';
  4192.                         iconsContainer.style.flexDirection = 'row';
  4193.                         iconsContainer.style.justifyContent = 'center';
  4194.                     }
  4195.                     
  4196.                     const accountBtn = nav.querySelector('li:last-child');
  4197.                     if (accountBtn) {
  4198.                         accountBtn.style.width = '100%';
  4199.                         accountBtn.style.display = 'flex';
  4200.                         accountBtn.style.justifyContent = 'center';
  4201.                         accountBtn.style.marginTop = '12px';
  4202.                         accountBtn.style.paddingTop = '12px';
  4203.                         accountBtn.style.borderTop = '1px solid #e0e0e0';
  4204.                     }
  4205.                 } else if (nav && window.innerWidth> 991.98) { // Desktop: alignement horizontal normal
  4206. nav.style.display = 'flex';
  4207. nav.style.flexDirection = 'row';
  4208. nav.style.alignItems = 'center';
  4209. nav.style.justifyContent = 'flex-end';
  4210. }
  4211. });
  4212. });
  4213. \t\t</script>
  4214. \t</head>
  4215. \t<body
  4216. \t\t{% if current_menu is defined and current_menu == \"listing\" %} id=\"category\" {% endif %}>
  4217. \t\t<!-- Start Header Area -->
  4218. \t\t<header class=\"header_area sticky-header\">
  4219. \t\t\t<div class=\"main_menu\">
  4220. \t\t\t\t<nav class=\"navbar navbar-expand-lg navbar-light main_box\">
  4221. \t\t\t\t\t<div
  4222. \t\t\t\t\t\tclass=\"container\">
  4223. \t\t\t\t\t\t<!-- Brand and toggle get grouped for better mobile display -->
  4224. \t\t\t\t\t\t<a class=\"navbar-brand logo_h\" href=\"{{ path('ui_home') }}\"><img style=\"width: auto;height: 60px\" src=\"{{ asset('logo.png') }}\" alt=\"\"></a>
  4225. \t\t\t\t\t\t<button class=\"navbar-toggler\" type=\"button\" data-bs-toggle=\"collapse\" data-bs-target=\"#navbarSupportedContent\" aria-controls=\"navbarSupportedContent\" aria-expanded=\"false\" aria-label=\"Toggle navigation\">
  4226. \t\t\t\t\t\t\t<span class=\"icon-bar\"></span>
  4227. \t\t\t\t\t\t\t<span class=\"icon-bar\"></span>
  4228. \t\t\t\t\t\t\t<span class=\"icon-bar\"></span>
  4229. \t\t\t\t\t\t</button>
  4230. \t\t\t\t\t\t<!-- Collect the nav links, forms, and other content for toggling -->
  4231. \t\t\t\t\t\t<div class=\"collapse navbar-collapse offset\" id=\"navbarSupportedContent\">
  4232. \t\t\t\t\t\t\t<ul class=\"nav navbar-nav menu_nav ml-auto\">
  4233. \t\t\t\t\t\t\t\t<li class=\"nav-item {% if current_menu is defined and current_menu == \" home\" %}active{% endif %}\">
  4234. \t\t\t\t\t\t\t\t\t<a class=\"nav-link\" href=\"{{ path('ui_home') }}\">Accueil</a>
  4235. \t\t\t\t\t\t\t\t</li>
  4236. \t\t\t\t\t\t\t\t<li class=\"nav-item {% if current_menu is defined and current_menu == \" shops\" %}active{% endif %}\">
  4237. \t\t\t\t\t\t\t\t\t<a class=\"nav-link\" href=\"{{ path('ui_shops_list') }}\">Boutiques</a>
  4238. \t\t\t\t\t\t\t\t</li>
  4239. \t\t\t\t\t\t\t\t<li class=\"nav-item {% if current_menu is defined and current_menu == \" listing\" %}active{% endif %}\">
  4240. \t\t\t\t\t\t\t\t\t<a class=\"nav-link\" href=\"{{ path('ui_listing') }}\">Produits</a>
  4241. \t\t\t\t\t\t\t\t</li>
  4242. \t\t\t\t\t\t\t\t<li class=\"nav-item {% if current_menu is defined and current_menu == \" contact\" %}active{% endif %}\">
  4243. \t\t\t\t\t\t\t\t\t<a class=\"nav-link\" href=\"{{ path('ui_contact') }}\">Contact</a>
  4244. \t\t\t\t\t\t\t\t</li>
  4245. \t\t\t\t\t\t\t</ul>
  4246. \t\t\t\t\t\t\t<ul class=\"nav navbar-nav navbar-right\">
  4247. \t\t\t\t\t\t\t\t<li class=\"nav-item\">
  4248. \t\t\t\t\t\t\t\t\t<div class=\"navbar-icons-wrapper\">
  4249. \t\t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_cart') }}\" class=\"cart {% if current_menu is defined and current_menu == \" cart\" %}active{% endif %}\" aria-label=\"Panier\">
  4250. \t\t\t\t\t\t\t\t\t\t\t<span class=\"ti-bag\"></span>
  4251. \t\t\t\t\t\t\t\t\t\t</a>
  4252. \t\t\t\t\t\t\t\t\t\t{% if app.user %}
  4253. \t\t\t\t\t\t\t\t\t\t\t<a href=\"{{ path('notifications_list') }}\" class=\"notification-icon\" title=\"Notifications\" aria-label=\"Notifications\">
  4254. \t\t\t\t\t\t\t\t\t\t\t\t<span class=\"ti-bell\"></span>
  4255. \t\t\t\t\t\t\t\t\t\t\t\t<span class=\"notification-badge text-white\" id=\"notificationBadge\" style=\"display: none;color: white;\">0</span>
  4256. \t\t\t\t\t\t\t\t\t\t\t</a>
  4257. \t\t\t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_product_comparison') }}\" class=\"comparison-icon\" title=\"Comparaison\" aria-label=\"Comparaison\">
  4258. \t\t\t\t\t\t\t\t\t\t\t\t<span class=\"lnr lnr-sync\"></span>
  4259. \t\t\t\t\t\t\t\t\t\t\t\t<span class=\"comparison-badge text-white\" id=\"comparisonBadge\" style=\"display: none;color: white;\">0</span>
  4260. \t\t\t\t\t\t\t\t\t\t\t</a>
  4261. \t\t\t\t\t\t\t\t\t\t{% endif %}
  4262. \t\t\t\t\t\t\t\t\t\t<button class=\"search\" type=\"button\" aria-label=\"Recherche\">
  4263. \t\t\t\t\t\t\t\t\t\t\t<span class=\"lnr lnr-magnifier\" id=\"search\"></span>
  4264. \t\t\t\t\t\t\t\t\t\t</button>
  4265. \t\t\t\t\t\t\t\t\t</div>
  4266. \t\t\t\t\t\t\t\t</li>
  4267. \t\t\t\t\t\t\t\t<li class=\"nav-item\">
  4268. \t\t\t\t\t\t\t\t\t{% if app.user %}
  4269. \t\t\t\t\t\t\t\t\t\t<a class=\"nav-link btn btn-primary btn-account text-white\" href=\"{{ path('ui_account_index') }}\">
  4270. \t\t\t\t\t\t\t\t\t\t\t<i class=\"ti-user\"></i>
  4271. \t\t\t\t\t\t\t\t\t\t\tMon compte
  4272. \t\t\t\t\t\t\t\t\t\t</a>
  4273. \t\t\t\t\t\t\t\t\t{% else %}
  4274. \t\t\t\t\t\t\t\t\t\t<a class=\"nav-link btn btn-primary btn-account text-white\" href=\"{{ path('ui_app_login') }}\">
  4275. \t\t\t\t\t\t\t\t\t\t\t<i class=\"ti-lock\"></i>
  4276. \t\t\t\t\t\t\t\t\t\t\tSe connecter
  4277. \t\t\t\t\t\t\t\t\t\t</a>
  4278. \t\t\t\t\t\t\t\t\t{% endif %}
  4279. \t\t\t\t\t\t\t\t</li>
  4280. \t\t\t\t\t\t\t</ul>
  4281. \t\t\t\t\t\t</div>
  4282. \t\t\t\t\t</div>
  4283. \t\t\t\t</nav>
  4284. \t\t\t</div>
  4285. \t\t\t<div class=\"search_input\" id=\"search_input_box\">
  4286. \t\t\t\t<div class=\"container\">
  4287. \t\t\t\t\t<form class=\"d-flex justify-content-between\" id=\"search_form\" action=\"{{ path('ui_listing') }}\" method=\"get\">
  4288. \t\t\t\t\t\t<input type=\"text\" class=\"form-control\" id=\"search_input\" name=\"q\" placeholder=\"Rechercher un produit, une boutique, une catégorie...\" autocomplete=\"off\" value=\"{{ app.request.query.get('q', '') }}\">
  4289. \t\t\t\t\t\t<button type=\"button\" class=\"btn\" id=\"search_submit_btn\">
  4290. \t\t\t\t\t\t\t<i class=\"lnr lnr-magnifier\"></i>
  4291. \t\t\t\t\t\t</button>
  4292. \t\t\t\t\t\t{% if app.request.query.get('q') %}
  4293. \t\t\t\t\t\t\t<button type=\"button\" class=\"btn btn-clear-search\" id=\"clear_search_btn\" title=\"Effacer la recherche\">
  4294. \t\t\t\t\t\t\t\t<i class=\"lnr lnr-cross\"></i>
  4295. \t\t\t\t\t\t\t</button>
  4296. \t\t\t\t\t\t{% endif %}
  4297. \t\t\t\t\t\t<span class=\"lnr lnr-cross\" id=\"close_search\" title=\"Fermer la recherche\"></span>
  4298. \t\t\t\t\t</form>
  4299. \t\t\t\t\t<div id=\"search_results\" class=\"search-results-container\"></div>
  4300. \t\t\t\t</div>
  4301. \t\t\t</div>
  4302. \t\t</header>
  4303. \t\t<!-- End Header Area -->
  4304. \t\t<!-- Flash Messages -->
  4305. \t\t<div class=\"container mt-3\" id=\"flash-messages-container\" style=\"position: relative; z-index: 1050;\">
  4306. \t\t\t<div class=\"row\">
  4307. \t\t\t\t<div class=\"col-12\">
  4308. \t\t\t\t\t{% for message in app.flashes('success') %}
  4309. \t\t\t\t\t\t<div class=\"alert alert-success alert-dismissible fade show flash-message\" role=\"alert\">
  4310. \t\t\t\t\t\t\t<i class=\"fa fa-check-circle\"></i>
  4311. \t\t\t\t\t\t\t<strong>{{ message }}</strong>
  4312. \t\t\t\t\t\t\t<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
  4313. \t\t\t\t\t\t</div>
  4314. \t\t\t\t\t{% endfor %}
  4315. \t\t\t\t\t{% for message in app.flashes('error') %}
  4316. \t\t\t\t\t\t<div class=\"alert alert-danger alert-dismissible fade show flash-message\" role=\"alert\">
  4317. \t\t\t\t\t\t\t<i class=\"fa fa-exclamation-circle\"></i>
  4318. \t\t\t\t\t\t\t<strong>{{ message }}</strong>
  4319. \t\t\t\t\t\t\t<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
  4320. \t\t\t\t\t\t</div>
  4321. \t\t\t\t\t{% endfor %}
  4322. \t\t\t\t\t{% for message in app.flashes('warning') %}
  4323. \t\t\t\t\t\t<div class=\"alert alert-warning alert-dismissible fade show flash-message\" role=\"alert\">
  4324. \t\t\t\t\t\t\t<i class=\"fa fa-exclamation-triangle\"></i>
  4325. \t\t\t\t\t\t\t<strong>{{ message }}</strong>
  4326. \t\t\t\t\t\t\t<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
  4327. \t\t\t\t\t\t</div>
  4328. \t\t\t\t\t{% endfor %}
  4329. \t\t\t\t\t{% for message in app.flashes('info') %}
  4330. \t\t\t\t\t\t<div class=\"alert alert-info alert-dismissible fade show flash-message\" role=\"alert\">
  4331. \t\t\t\t\t\t\t<i class=\"fa fa-info-circle\"></i>
  4332. \t\t\t\t\t\t\t<strong>{{ message }}</strong>
  4333. \t\t\t\t\t\t\t<button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>
  4334. \t\t\t\t\t\t</div>
  4335. \t\t\t\t\t{% endfor %}
  4336. \t\t\t\t</div>
  4337. \t\t\t</div>
  4338. \t\t</div>
  4339. \t\t{% block body %}{% endblock %}
  4340. \t\t<!-- start footer Area -->
  4341. \t\t<footer class=\"footer-area section_gap\">
  4342. \t\t\t<div class=\"footer-pattern\"></div>
  4343. \t\t\t<div class=\"container\">
  4344. \t\t\t\t<div class=\"row\">
  4345. \t\t\t\t\t<div class=\"col-lg-3 col-md-6 col-sm-6 mb-4 mb-lg-0\">
  4346. \t\t\t\t\t\t<div class=\"single-footer-widget\">
  4347. \t\t\t\t\t\t\t<div class=\"footer-logo mb-3\">
  4348. \t\t\t\t\t\t\t\t<h4 class=\"footer-brand\">MaketOu</h4>
  4349. \t\t\t\t\t\t\t</div>
  4350. \t\t\t\t\t\t\t<p class=\"footer-description\">
  4351. \t\t\t\t\t\t\t\tMaketOu est la première marketplace haïtienne qui connecte les acheteurs et les vendeurs. 
  4352. \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t                        Nous offrons une plateforme sécurisée et moderne pour le commerce en ligne en Haïti.
  4353. \t\t\t\t\t\t\t</p>
  4354. \t\t\t\t\t\t\t<div class=\"footer-social mt-3\">
  4355. \t\t\t\t\t\t\t\t<h6 class=\"mb-2\">Suivez-nous</h6>
  4356. \t\t\t\t\t\t\t\t<div class=\"footer-social-icons\">
  4357. \t\t\t\t\t\t\t\t\t<a href=\"#\" class=\"social-icon\" aria-label=\"Facebook\" title=\"Facebook\">
  4358. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-facebook\"></i>
  4359. \t\t\t\t\t\t\t\t\t</a>
  4360. \t\t\t\t\t\t\t\t\t<a href=\"#\" class=\"social-icon\" aria-label=\"Twitter\" title=\"Twitter\">
  4361. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-twitter\"></i>
  4362. \t\t\t\t\t\t\t\t\t</a>
  4363. \t\t\t\t\t\t\t\t\t<a href=\"#\" class=\"social-icon\" aria-label=\"Instagram\" title=\"Instagram\">
  4364. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-instagram\"></i>
  4365. \t\t\t\t\t\t\t\t\t</a>
  4366. \t\t\t\t\t\t\t\t\t<a href=\"#\" class=\"social-icon\" aria-label=\"LinkedIn\" title=\"LinkedIn\">
  4367. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-linkedin\"></i>
  4368. \t\t\t\t\t\t\t\t\t</a>
  4369. \t\t\t\t\t\t\t\t</div>
  4370. \t\t\t\t\t\t\t</div>
  4371. \t\t\t\t\t\t</div>
  4372. \t\t\t\t\t</div>
  4373. \t\t\t\t\t<div class=\"col-lg-2 col-md-6 col-sm-6 mb-4 mb-lg-0\">
  4374. \t\t\t\t\t\t<div class=\"single-footer-widget\">
  4375. \t\t\t\t\t\t\t<h6 class=\"footer-widget-title\">Liens rapides</h6>
  4376. \t\t\t\t\t\t\t<ul class=\"footer-list\">
  4377. \t\t\t\t\t\t\t\t<li>
  4378. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_home') }}\">
  4379. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Accueil</a>
  4380. \t\t\t\t\t\t\t\t</li>
  4381. \t\t\t\t\t\t\t\t<li>
  4382. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_listing') }}\">
  4383. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Produits</a>
  4384. \t\t\t\t\t\t\t\t</li>
  4385. \t\t\t\t\t\t\t\t<li>
  4386. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_shops_list') }}\">
  4387. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Boutiques</a>
  4388. \t\t\t\t\t\t\t\t</li>
  4389. \t\t\t\t\t\t\t\t{% if app.user %}
  4390. \t\t\t\t\t\t\t\t\t<li>
  4391. \t\t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_account_index') }}\">
  4392. \t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Mon compte</a>
  4393. \t\t\t\t\t\t\t\t\t</li>
  4394. \t\t\t\t\t\t\t\t{% else %}
  4395. \t\t\t\t\t\t\t\t\t<li>
  4396. \t\t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_app_login') }}\">
  4397. \t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Se connecter</a>
  4398. \t\t\t\t\t\t\t\t\t</li>
  4399. \t\t\t\t\t\t\t\t\t<li>
  4400. \t\t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_app_register') }}\">
  4401. \t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;S'inscrire</a>
  4402. \t\t\t\t\t\t\t\t\t</li>
  4403. \t\t\t\t\t\t\t\t{% endif %}
  4404. \t\t\t\t\t\t\t</ul>
  4405. \t\t\t\t\t\t</div>
  4406. \t\t\t\t\t</div>
  4407. \t\t\t\t\t<div class=\"col-lg-2 col-md-6 col-sm-6 mb-4 mb-lg-0\">
  4408. \t\t\t\t\t\t<div class=\"single-footer-widget\">
  4409. \t\t\t\t\t\t\t<h6 class=\"footer-widget-title\">Pour les vendeurs</h6>
  4410. \t\t\t\t\t\t\t<ul class=\"footer-list\">
  4411. \t\t\t\t\t\t\t\t<li>
  4412. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('seller_index') }}\">
  4413. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Ouvrir une boutique</a>
  4414. \t\t\t\t\t\t\t\t</li>
  4415. \t\t\t\t\t\t\t\t<li>
  4416. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('seller_help_how_to_sell') }}\">
  4417. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Comment vendre</a>
  4418. \t\t\t\t\t\t\t\t</li>
  4419. \t\t\t\t\t\t\t\t<li>
  4420. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('seller_help_pricing') }}\">
  4421. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Tarifs</a>
  4422. \t\t\t\t\t\t\t\t</li>
  4423. \t\t\t\t\t\t\t\t<li>
  4424. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('seller_help_support') }}\">
  4425. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Support vendeur</a>
  4426. \t\t\t\t\t\t\t\t</li>
  4427. \t\t\t\t\t\t\t</ul>
  4428. \t\t\t\t\t\t</div>
  4429. \t\t\t\t\t</div>
  4430. \t\t\t\t\t<div class=\"col-lg-2 col-md-6 col-sm-6 mb-4 mb-lg-0\">
  4431. \t\t\t\t\t\t<div class=\"single-footer-widget\">
  4432. \t\t\t\t\t\t\t<h6 class=\"footer-widget-title\">Support</h6>
  4433. \t\t\t\t\t\t\t<ul class=\"footer-list\">
  4434. \t\t\t\t\t\t\t\t<li>
  4435. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_help') }}\">
  4436. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Centre d'Aide</a>
  4437. \t\t\t\t\t\t\t\t</li>
  4438. \t\t\t\t\t\t\t\t<li>
  4439. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_contact') }}\">
  4440. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Contactez-nous</a>
  4441. \t\t\t\t\t\t\t\t</li>
  4442. \t\t\t\t\t\t\t\t<li>
  4443. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_faq') }}\">
  4444. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;FAQ</a>
  4445. \t\t\t\t\t\t\t\t</li>
  4446. \t\t\t\t\t\t\t\t<li>
  4447. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_privacy') }}\">
  4448. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Politique de Confidentialité</a>
  4449. \t\t\t\t\t\t\t\t</li>
  4450. \t\t\t\t\t\t\t\t<li>
  4451. \t\t\t\t\t\t\t\t\t<a href=\"{{ path('ui_terms') }}\">
  4452. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-angle-right me-2\"></i>&nbsp;Conditions d'Utilisation</a>
  4453. \t\t\t\t\t\t\t\t</li>
  4454. \t\t\t\t\t\t\t</ul>
  4455. \t\t\t\t\t\t</div>
  4456. \t\t\t\t\t</div>
  4457. \t\t\t\t\t<div class=\"col-lg-3 col-md-6 col-sm-6\">
  4458. \t\t\t\t\t\t<div class=\"single-footer-widget\">
  4459. \t\t\t\t\t\t\t<h6 class=\"footer-widget-title\">Newsletter</h6>
  4460. \t\t\t\t\t\t\t<p class=\"footer-newsletter-text\">Restez informé des dernières nouveautés</p>
  4461. \t\t\t\t\t\t\t<div class=\"footer-newsletter-wrapper\" id=\"mc_embed_signup\">
  4462. \t\t\t\t\t\t\t\t<form action=\"{{ path('ui_newsletter_subscribe') }}\" method=\"post\" class=\"footer-newsletter-form\">
  4463. \t\t\t\t\t\t\t\t\t<div class=\"newsletter-input-group\">
  4464. \t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-envelope newsletter-icon\"></i>
  4465. \t\t\t\t\t\t\t\t\t\t<input class=\"form-control newsletter-input\" name=\"email\" placeholder=\"Votre email\" required type=\"email\">
  4466. \t\t\t\t\t\t\t\t\t\t<button type=\"submit\" class=\"newsletter-btn\" aria-label=\"S'abonner\">
  4467. \t\t\t\t\t\t\t\t\t\t\t<span class=\"newsletter-btn-icon\">
  4468. \t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-paper-plane\" aria-hidden=\"true\"></i>
  4469. \t\t\t\t\t\t\t\t\t\t\t</span>
  4470. \t\t\t\t\t\t\t\t\t\t\t<span class=\"newsletter-btn-loader\" style=\"display: none;\">
  4471. \t\t\t\t\t\t\t\t\t\t\t\t<i class=\"fa fa-spinner fa-spin\" aria-hidden=\"true\"></i>
  4472. \t\t\t\t\t\t\t\t\t\t\t</span>
  4473. \t\t\t\t\t\t\t\t\t\t</button>
  4474. \t\t\t\t\t\t\t\t\t</div>
  4475. \t\t\t\t\t\t\t\t</form>
  4476. \t\t\t\t\t\t\t</div>
  4477. \t\t\t\t\t\t\t<div class=\"footer-trust-badges mt-3\">
  4478. \t\t\t\t\t\t\t\t<div class=\"trust-item\">
  4479. \t\t\t\t\t\t\t\t\t<i class=\"fa fa-shield\"></i>
  4480. \t\t\t\t\t\t\t\t\t<span>Paiement sécurisé</span>
  4481. \t\t\t\t\t\t\t\t</div>
  4482. \t\t\t\t\t\t\t\t<div class=\"trust-item\">
  4483. \t\t\t\t\t\t\t\t\t<i class=\"fa fa-truck\"></i>
  4484. \t\t\t\t\t\t\t\t\t<span>Livraison rapide</span>
  4485. \t\t\t\t\t\t\t\t</div>
  4486. \t\t\t\t\t\t\t</div>
  4487. \t\t\t\t\t\t</div>
  4488. \t\t\t\t\t</div>
  4489. \t\t\t\t</div>
  4490. \t\t\t\t<div class=\"footer-divider\"></div>
  4491. \t\t\t\t<div class=\"footer-bottom d-flex justify-content-center align-items-center flex-wrap\">
  4492. \t\t\t\t\t<p class=\"footer-text m-0\">
  4493. \t\t\t\t\t\tCopyright &copy;<script>
  4494. \t\t\t\t\t\t\tdocument.write(new Date().getFullYear());
  4495. \t\t\t\t\t\t</script>
  4496. \t\t\t\t\t\tTous droits réservés | Ce site a été fait avec
  4497. \t\t\t\t\t\t<i class=\"fa fa-heart-o\" aria-hidden=\"true\" style=\"color: #dc3545;\"></i>
  4498. \t\t\t\t\t\tpar
  4499. \t\t\t\t\t\t<a href=\"https://tech.foulgor.com\" target=\"_blank\" style=\"color: #ffa200;\">Foulgor Tech</a>
  4500. \t\t\t\t\t</p>
  4501. \t\t\t\t</div>
  4502. \t\t\t</div>
  4503. \t\t</footer>
  4504. \t\t<style>
  4505. \t\t\t.search-results-container {
  4506. \t\t\t\tposition: absolute;
  4507. \t\t\t\ttop: 100%;
  4508. \t\t\t\tleft: 15px;
  4509. \t\t\t\tright: 15px;
  4510. \t\t\t\tbackground: #fff;
  4511. \t\t\t\tborder: 1px solid #ddd;
  4512. \t\t\t\tborder-top: none;
  4513. \t\t\t\tz-index: 9999;
  4514. \t\t\t\tbox-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  4515. \t\t\t\tmax-height: 400px;
  4516. \t\t\t\toverflow-y: auto;
  4517. \t\t\t\tdisplay: none;
  4518. \t\t\t\tborder-radius: 0 0 4px 4px;
  4519. \t\t\t}
  4520. \t\t\t.search-results-container .list-group-item {
  4521. \t\t\t\tborder-left: none;
  4522. \t\t\t\tborder-right: none;
  4523. \t\t\t\tborder-radius: 0;
  4524. \t\t\t\tcursor: pointer;
  4525. \t\t\t\tpadding: 12px 15px;
  4526. \t\t\t\ttransition: background-color 0.2s ease;
  4527. \t\t\t}
  4528. \t\t\t.search-results-container .list-group-item:hover {
  4529. \t\t\t\tbackground-color: #f8f9fa;
  4530. \t\t\t}
  4531. \t\t\t.search-results-container .list-group-item i {
  4532. \t\t\t\tcolor: #777;
  4533. \t\t\t\tfont-size: 1.2rem;
  4534. \t\t\t}
  4535. \t\t\t/* Ensure container is relative for absolute positioning of results */
  4536. \t\t\t#search_input_box .container {
  4537. \t\t\t\tposition: relative;
  4538. \t\t\t}
  4539. \t\t\t#search_input_box .form-control {
  4540. \t\t\t\tflex: 1;
  4541. \t\t\t\tpadding-right: 10px;
  4542. \t\t\t}
  4543. \t\t\t#search_input_box #search_submit_btn {
  4544. \t\t\t\tbackground: transparent;
  4545. \t\t\t\tborder: 0;
  4546. \t\t\t\tcolor: #fff;
  4547. \t\t\t\tpadding: 0 15px;
  4548. \t\t\t\tcursor: pointer;
  4549. \t\t\t\ttransition: opacity 0.3s ease;
  4550. \t\t\t}
  4551. \t\t\t#search_input_box #search_submit_btn:hover {
  4552. \t\t\t\topacity: 0.8;
  4553. \t\t\t}
  4554. \t\t\t#search_input_box .btn-clear-search {
  4555. \t\t\t\tbackground: transparent;
  4556. \t\t\t\tborder: 0;
  4557. \t\t\t\tcolor: #fff;
  4558. \t\t\t\tpadding: 0 10px;
  4559. \t\t\t\tcursor: pointer;
  4560. \t\t\t\ttransition: opacity 0.3s ease;
  4561. \t\t\t\tdisplay: none;
  4562. \t\t\t}
  4563. \t\t\t#search_input_box .btn-clear-search:hover {
  4564. \t\t\t\topacity: 0.8;
  4565. \t\t\t}
  4566. \t\t\t#search_input_box .btn-clear-search i {
  4567. \t\t\t\tfont-size: 1.1rem;
  4568. \t\t\t}
  4569. \t\t\t#search_input_box form {
  4570. \t\t\t\tposition: relative;
  4571. \t\t\t\talign-items: center;
  4572. \t\t\t}
  4573. \t\t</style>
  4574. \t\t<script>
  4575. \t\t\t// Debounced autocomplete for header search
  4576. (function () {
  4577. const input = document.getElementById('search_input');
  4578. const box = document.getElementById('search_results');
  4579. const searchForm = document.getElementById('search_form');
  4580. const clearSearchBtn = document.getElementById('clear_search_btn');
  4581. const closeSearchBtn = document.getElementById('close_search');
  4582. if (! input || ! box) 
  4583. return;
  4584. // Fonction pour effacer la recherche
  4585. function clearSearch() {
  4586. input.value = '';
  4587. box.style.display = 'none';
  4588. box.innerHTML = '';
  4589. if (clearSearchBtn) {
  4590. clearSearchBtn.style.display = 'none';
  4591. }
  4592. // Si on est sur la page listing, utiliser AJAX pour mettre à jour
  4593. if (typeof currentFilters !== 'undefined') {
  4594. currentFilters.q = '';
  4595. currentFilters.page = 1;
  4596. if (typeof applyFilters === 'function') {
  4597. applyFilters();
  4598. }
  4599. if (typeof updateActiveFilters === 'function') {
  4600. updateActiveFilters();
  4601. }
  4602. } else { // Sinon, rediriger vers la page listing sans recherche
  4603. window.location.href = '{{ path('ui_listing') }}';
  4604. }
  4605. }
  4606. // Bouton pour effacer la recherche
  4607. if (clearSearchBtn) {
  4608. clearSearchBtn.addEventListener('click', function (e) {
  4609. e.preventDefault();
  4610. e.stopPropagation();
  4611. clearSearch();
  4612. });
  4613. }
  4614. // Bouton de soumission de recherche
  4615. var searchSubmitBtn = document.getElementById('search_submit_btn');
  4616. if (searchSubmitBtn) {
  4617. searchSubmitBtn.addEventListener('click', function (e) {
  4618. e.preventDefault();
  4619. e.stopPropagation();
  4620. const q = input.value.trim();
  4621. if (q.length === 0) {
  4622. clearSearch();
  4623. return false;
  4624. }
  4625. // Si on est sur la page listing, utiliser AJAX
  4626. if (typeof currentFilters !== 'undefined' && typeof applyFilters === 'function') {
  4627. currentFilters.q = q;
  4628. currentFilters.page = 1;
  4629. applyFilters();
  4630. if (typeof updateActiveFilters === 'function') {
  4631. updateActiveFilters();
  4632. }
  4633. // Fermer la boîte de recherche
  4634. if (closeSearchBtn) {
  4635. closeSearchBtn.click();
  4636. }
  4637. } else { // Sinon, rediriger vers la page listing avec la recherche
  4638. const listingUrl = '{{ path('ui_listing') }}' + '?q=' + encodeURIComponent(q);
  4639. window.location.href = listingUrl;
  4640. }
  4641. return false;
  4642. });
  4643. }
  4644. // Gestion du formulaire de recherche
  4645. if (searchForm) {
  4646. searchForm.addEventListener('submit', function (e) {
  4647. e.preventDefault();
  4648. e.stopPropagation();
  4649. const q = input.value.trim();
  4650. if (q.length === 0) {
  4651. clearSearch();
  4652. return;
  4653. }
  4654. // Si on est sur la page listing, utiliser AJAX
  4655. if (typeof currentFilters !== 'undefined' && typeof applyFilters === 'function') {
  4656. currentFilters.q = q;
  4657. currentFilters.page = 1;
  4658. applyFilters();
  4659. if (typeof updateActiveFilters === 'function') {
  4660. updateActiveFilters();
  4661. }
  4662. // Fermer la boîte de recherche
  4663. if (closeSearchBtn) {
  4664. closeSearchBtn.click();
  4665. }
  4666. } else { // Sinon, rediriger vers la page listing avec la recherche
  4667. const listingUrl = '{{ path('ui_listing') }}' + '?q=' + encodeURIComponent(q);
  4668. window.location.href = listingUrl;
  4669. }
  4670. return false;
  4671. });
  4672. }
  4673. let t = null;
  4674. input.addEventListener('input', function () {
  4675. const q = input.value.trim();
  4676. clearTimeout(t);
  4677. if (q.length === 0) {
  4678. box.style.display = 'none';
  4679. box.innerHTML = '';
  4680. // Afficher/masquer le bouton clear
  4681. if (clearSearchBtn) {
  4682. clearSearchBtn.style.display = 'none';
  4683. }
  4684. return;
  4685. }
  4686. // Afficher le bouton clear
  4687. if (clearSearchBtn) {
  4688. clearSearchBtn.style.display = 'block';
  4689. }
  4690. t = setTimeout(() => fetchSuggestions(q), 300);
  4691. });
  4692. function fetchSuggestions(q) {
  4693. const url = '{{ path('ui_api_search_suggest') }}' + '?q=' + encodeURIComponent(q);
  4694. fetch(url).then(r => r.json()).then(data => {
  4695. if (!data.success) {
  4696. box.style.display = 'none';
  4697. return;
  4698. }
  4699. renderSuggestions(data.results || []);
  4700. }).catch(() => {
  4701. box.style.display = 'none';
  4702. });
  4703. }
  4704. function renderSuggestions(items) {
  4705. if (! items.length) {
  4706. box.style.display = 'none';
  4707. box.innerHTML = '';
  4708. return;
  4709. }
  4710. box.innerHTML = items.map(it => suggestionItem(it)).join('');
  4711. box.style.display = 'block';
  4712. }
  4713. function suggestionItem(it) {
  4714. const icon = it.type === 'product' ? 'ti-package' : (it.type === 'shop' ? 'ti-briefcase' : (it.type === 'category' ? 'ti-layers' : 'ti-tag'));
  4715. const typeLabel = it.type === 'product' ? 'Produit' : (it.type === 'shop' ? 'Boutique' : (it.type === 'category' ? 'Catégorie' : 'Tag'));
  4716. return '<a href=\"' + it.url + '\" class=\"list-group-item list-group-item-action d-flex align-items-center\">' + '<i class=\"' + icon + ' me-3\"></i>' + '<span class=\"flex-grow-1\">' + escapeHtml(it.label) + '</span>' + '<span class=\"badge bg-light text-dark ms-2\">' + typeLabel + '</span>' + '</a>';
  4717. }
  4718. function escapeHtml(s) {
  4719. return s.replace(/[&<>\"]+/g, c => ({'&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;'}[c]));
  4720. }
  4721. document.addEventListener('click', function (e) {
  4722. if (! box.contains(e.target) && e.target !== input) {
  4723. box.style.display = 'none';
  4724. }
  4725. });
  4726. window.handleSearchSubmit = function (e) {
  4727. if (e) 
  4728. e.preventDefault();
  4729. const first = box.querySelector('a');
  4730. if (first) {
  4731. window.location.href = first.getAttribute('href');
  4732. return false;
  4733. }
  4734. // fallback to listing page search by name
  4735. const q = input.value.trim();
  4736. if (q.length) { // Si on est sur la page listing, utiliser AJAX
  4737. if (typeof currentFilters !== 'undefined') {
  4738. currentFilters.q = q;
  4739. currentFilters.page = 1;
  4740. if (typeof applyFilters === 'function') {
  4741. applyFilters();
  4742. }
  4743. if (typeof updateActiveFilters === 'function') {
  4744. updateActiveFilters();
  4745. }
  4746. } else {
  4747. window.location.href = '{{ path('ui_listing') }}' + '?q=' + encodeURIComponent(q);
  4748. }
  4749. }
  4750. return false;
  4751. }
  4752. // Gestion de la touche Enter dans le champ de recherche
  4753. if (input) {
  4754. input.addEventListener('keydown', function (e) {
  4755. if (e.key === 'Enter' || e.keyCode === 13) {
  4756. e.preventDefault();
  4757. e.stopPropagation();
  4758. const q = input.value.trim();
  4759. if (q.length === 0) {
  4760. clearSearch();
  4761. return false;
  4762. }
  4763. // Si on est sur la page listing, utiliser AJAX
  4764. if (typeof currentFilters !== 'undefined' && typeof applyFilters === 'function') {
  4765. currentFilters.q = q;
  4766. currentFilters.page = 1;
  4767. applyFilters();
  4768. if (typeof updateActiveFilters === 'function') {
  4769. updateActiveFilters();
  4770. }
  4771. // Fermer la boîte de recherche
  4772. if (closeSearchBtn) {
  4773. closeSearchBtn.click();
  4774. }
  4775. } else { // Sinon, rediriger vers la page listing avec la recherche
  4776. const listingUrl = '{{ path('ui_listing') }}' + '?q=' + encodeURIComponent(q);
  4777. window.location.href = listingUrl;
  4778. }
  4779. return false;
  4780. }
  4781. });
  4782. }
  4783. // Ajouter un event listener au bouton de soumission (réutiliser la variable si elle existe déjà)
  4784. if (!searchSubmitBtn) {
  4785.     searchSubmitBtn = document.getElementById('search_submit_btn');
  4786. }
  4787. if (searchSubmitBtn) {
  4788. searchSubmitBtn.addEventListener('click', function (e) {
  4789. e.preventDefault();
  4790. e.stopPropagation();
  4791. const q = input.value.trim();
  4792. if (q.length === 0) {
  4793. clearSearch();
  4794. return false;
  4795. }
  4796. // Si on est sur la page listing, utiliser AJAX
  4797. if (typeof currentFilters !== 'undefined' && typeof applyFilters === 'function') {
  4798. currentFilters.q = q;
  4799. currentFilters.page = 1;
  4800. applyFilters();
  4801. if (typeof updateActiveFilters === 'function') {
  4802. updateActiveFilters();
  4803. }
  4804. // Fermer la boîte de recherche
  4805. if (closeSearchBtn) {
  4806. closeSearchBtn.click();
  4807. }
  4808. } else { // Sinon, rediriger vers la page listing avec la recherche
  4809. const listingUrl = '{{ path('ui_listing') }}' + '?q=' + encodeURIComponent(q);
  4810. window.location.href = listingUrl;
  4811. }
  4812. return false;
  4813. });
  4814. }
  4815. // Afficher le bouton clear au chargement si une recherche est active
  4816. document.addEventListener('DOMContentLoaded', function () {
  4817. const q = input.value.trim();
  4818. if (q.length > 0 && clearSearchBtn) {
  4819. clearSearchBtn.style.display = 'block';
  4820. }
  4821. });
  4822. })();
  4823. // Gestion des mega-menus avec clic (comme la barre de recherche)
  4824. document.addEventListener('DOMContentLoaded', function () {
  4825. const dropdownItems = document.querySelectorAll('.nav-item.dropdown');
  4826. dropdownItems.forEach(function (item) {
  4827. const dropdownToggle = item.querySelector('.dropdown-toggle');
  4828. const dropdownMenu = item.querySelector('.mega-menu');
  4829. if (! dropdownToggle || ! dropdownMenu) 
  4830. return;
  4831. // Fermer les autres menus quand on ouvre un nouveau
  4832. function closeAllMenus() {
  4833. dropdownItems.forEach(function (otherItem) {
  4834. const otherMenu = otherItem.querySelector('.mega-menu');
  4835. if (otherMenu && otherMenu !== dropdownMenu) {
  4836. \$(otherMenu).slideUp(300);
  4837. otherMenu.classList.remove('active');
  4838. }
  4839. });
  4840. }
  4841. // Toggle au clic (comme la barre de recherche)
  4842. dropdownToggle.addEventListener('click', function (e) {
  4843. e.preventDefault();
  4844. e.stopPropagation();
  4845. closeAllMenus();
  4846. if (dropdownMenu.classList.contains('active')) { // Fermer le menu
  4847. dropdownMenu.style.opacity = '0';
  4848. dropdownMenu.style.visibility = 'hidden';
  4849. dropdownMenu.style.transform = 'translateX(-50%) translateY(-10px)';
  4850. setTimeout(() => {
  4851. dropdownMenu.classList.remove('active');
  4852. dropdownMenu.style.display = 'none';
  4853. }, 300);
  4854. } else { // Ouvrir le menu
  4855. dropdownMenu.style.display = 'block';
  4856. setTimeout(() => {
  4857. dropdownMenu.classList.add('active');
  4858. dropdownMenu.style.opacity = '1';
  4859. dropdownMenu.style.visibility = 'visible';
  4860. dropdownMenu.style.transform = 'translateX(-50%) translateY(0)';
  4861. }, 10);
  4862. }
  4863. });
  4864. // Fermer au clic en dehors
  4865. document.addEventListener('click', function (e) {
  4866. if (! item.contains(e.target) && dropdownMenu.classList.contains('active')) {
  4867. dropdownMenu.style.opacity = '0';
  4868. dropdownMenu.style.visibility = 'hidden';
  4869. dropdownMenu.style.transform = 'translateX(-50%) translateY(-10px)';
  4870. setTimeout(() => {
  4871. dropdownMenu.classList.remove('active');
  4872. dropdownMenu.style.display = 'none';
  4873. }, 300);
  4874. }
  4875. });
  4876. // Animation des éléments du menu
  4877. const menuItems = dropdownMenu.querySelectorAll('.dropdown-item a');
  4878. menuItems.forEach(function (menuItem, index) {
  4879. menuItem.style.animationDelay = (index * 0.05) + 's';
  4880. });
  4881. });
  4882. // Gestion des clics sur mobile
  4883. if (window.innerWidth <= 768) {
  4884. dropdownItems.forEach(function (item) {
  4885. const dropdownToggle = item.querySelector('.dropdown-toggle');
  4886. const dropdownMenu = item.querySelector('.mega-menu');
  4887. dropdownToggle.addEventListener('click', function (e) {
  4888. e.preventDefault();
  4889. // Fermer tous les autres menus
  4890. dropdownItems.forEach(function (otherItem) {
  4891. if (otherItem !== item) {
  4892. const otherMenu = otherItem.querySelector('.mega-menu');
  4893. otherMenu.style.opacity = '0';
  4894. otherMenu.style.visibility = 'hidden';
  4895. otherMenu.style.transform = 'translateY(-10px)';
  4896. }
  4897. });
  4898. // Toggle le menu actuel
  4899. if (dropdownMenu.style.opacity === '1') {
  4900. dropdownMenu.style.opacity = '0';
  4901. dropdownMenu.style.visibility = 'hidden';
  4902. dropdownMenu.style.transform = 'translateY(-10px)';
  4903. } else {
  4904. dropdownMenu.style.opacity = '1';
  4905. dropdownMenu.style.visibility = 'visible';
  4906. dropdownMenu.style.transform = 'translateY(0)';
  4907. }
  4908. });
  4909. });
  4910. }
  4911. // Fermer les menus quand on clique ailleurs
  4912. document.addEventListener('click', function (e) {
  4913. if (! e.target.closest('.nav-item.dropdown')) {
  4914. dropdownItems.forEach(function (item) {
  4915. const dropdownMenu = item.querySelector('.mega-menu');
  4916. dropdownMenu.style.opacity = '0';
  4917. dropdownMenu.style.visibility = 'hidden';
  4918. dropdownMenu.style.transform = 'translateY(-10px)';
  4919. });
  4920. }
  4921. });
  4922. });
  4923. \t\t</script>
  4924. \t\t<!-- End footer Area -->
  4925. \t\t<script src=\"{{ asset('ui/js/vendor/jquery-2.2.4.min.js') }}\"></script>
  4926. \t\t<script src=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js\"></script>
  4927. \t\t<script>
  4928. \t\t\t// Initialiser le collapse Bootstrap 5 pour le menu hamburger après chargement de Bootstrap
  4929. document.addEventListener('DOMContentLoaded', function () { // Attendre que Bootstrap soit complètement chargé
  4930. if (typeof bootstrap !== 'undefined') {
  4931. const navbarToggler = document.querySelector('.navbar-toggler');
  4932. const navbarCollapse = document.getElementById('navbarSupportedContent');
  4933. if (navbarToggler && navbarCollapse) {
  4934. // Bootstrap 5 devrait gérer automatiquement avec data-bs-toggle
  4935. // Mais on s'assure que ça fonctionne en écoutant les événements
  4936. navbarCollapse.addEventListener('show.bs.collapse', function () {
  4937. navbarToggler.setAttribute('aria-expanded', 'true');
  4938. navbarToggler.classList.add('active');
  4939. });
  4940. navbarCollapse.addEventListener('hide.bs.collapse', function () {
  4941. navbarToggler.setAttribute('aria-expanded', 'false');
  4942. navbarToggler.classList.remove('active');
  4943. });
  4944. }
  4945. }
  4946. });
  4947. \t\t</script>
  4948. \t\t<script src=\"https://unpkg.com/dropzone@5/dist/min/dropzone.min.js\"></script>
  4949. \t\t<script src=\"{{ asset('ui/js/jquery.ajaxchimp.min.js') }}\"></script>
  4950. \t\t<script src=\"{{ asset('ui/js/jquery.nice-select.min.js') }}\"></script>
  4951. \t\t<script src=\"{{ asset('ui/js/jquery.sticky.js') }}\"></script>
  4952. \t\t<script src=\"{{ asset('ui/js/nouislider.min.js') }}\"></script>
  4953. \t\t<script src=\"{{ asset('ui/js/countdown.js') }}\"></script>
  4954. \t\t<script src=\"{{ asset('ui/js/jquery.magnific-popup.min.js') }}\"></script>
  4955. \t\t<script src=\"{{ asset('ui/js/owl.carousel.min.js') }}\"></script>
  4956. \t\t<script src=\"https://maps.googleapis.com/maps/api/js?key=AIzaSyCjCGmQ0Uq4exrzdcL6rvxywDDOvfAu6eE\"></script>
  4957. \t\t<script src=\"{{ asset('ui/js/gmaps.min.js') }}\"></script>
  4958. \t\t<script src=\"{{ asset('ui/js/main.js') }}\"></script>
  4959. \t\t{{ encore_entry_script_tags('app') }}
  4960. \t\t<!-- PWA Service Worker Registration -->
  4961. \t\t<script>
  4962. \t\t\t// Enregistrement du Service Worker
  4963. if ('serviceWorker' in navigator) {
  4964. window.addEventListener('load', () => {
  4965. navigator.serviceWorker.register('{{ asset('sw.js') }}').then((registration) => {
  4966. console.log('Service Worker enregistré avec succès:', registration.scope);
  4967. // Vérifie les mises à jour du service worker
  4968. registration.addEventListener('updatefound', () => {
  4969. const newWorker = registration.installing;
  4970. newWorker.addEventListener('statechange', () => {
  4971. if (newWorker.state === 'installed' && navigator.serviceWorker.controller) { // Nouveau service worker disponible
  4972. if (confirm('Une nouvelle version de MaketOu est disponible. Voulez-vous l\\'installer maintenant ?')) {
  4973. newWorker.postMessage({type: 'SKIP_WAITING'});
  4974. window.location.reload();
  4975. }
  4976. }
  4977. });
  4978. });
  4979. }).catch((error) => {
  4980. console.log('Échec de l\\'enregistrement du Service Worker:', error);
  4981. });
  4982. // Écoute les messages du service worker
  4983. navigator.serviceWorker.addEventListener('message', (event) => {
  4984. console.log('Message du Service Worker:', event.data);
  4985. });
  4986. });
  4987. }
  4988. \t\t</script>
  4989. \t\t<!-- PWA Install Script -->
  4990. \t\t<script src=\"{{ asset('js/pwa-install.js') }}\"></script>
  4991. \t\t<script>
  4992. \t\t\t// Charger les compteurs au chargement de la page
  4993. document.addEventListener('DOMContentLoaded', function () {
  4994. {% if app.user %}
  4995. loadNotificationCount();
  4996. // Délai pour s'assurer que la session est bien établie après connexion
  4997. setTimeout(function () {
  4998. loadComparisonCount();
  4999. }, 500);{% endif %}
  5000. // Gérer le bouton de recherche mobile
  5001. const searchMobileBtn = document.getElementById('searchMobileBtn');
  5002. if (searchMobileBtn) {
  5003. searchMobileBtn.addEventListener('click', function (e) {
  5004. e.preventDefault();
  5005. // Utiliser le même comportement que le bouton desktop
  5006. const searchBox = document.getElementById('search_input_box');
  5007. if (searchBox) {
  5008. searchBox.style.display = 'block';
  5009. const searchInput = document.getElementById('search_input');
  5010. if (searchInput) {
  5011. setTimeout(() => searchInput.focus(), 100);
  5012. }
  5013. }
  5014. });
  5015. }
  5016. });
  5017. function loadNotificationCount() {
  5018. {% if app.user %}
  5019. fetch('{{ path(\"api_notifications_count\") }}').then(response => {
  5020. if (!response.ok) {
  5021. throw new Error('Erreur HTTP: ' + response.status);
  5022. }
  5023. return response.json();
  5024. }).then(data => {
  5025. const count = data.count || 0;
  5026. // Mettre à jour tous les badges de notification
  5027. const badges = [document.getElementById('notificationBadge'), document.getElementById('notificationBadgeMobile'), document.querySelector('.notification-badge')].filter(badge => badge !== null);
  5028. badges.forEach(badge => {
  5029. if (count > 0) {
  5030. badge.textContent = count;
  5031. badge.style.display = 'flex';
  5032. badge.style.color = 'white';
  5033. badge.style.backgroundColor = '#dc3545';
  5034. } else {
  5035. badge.style.display = 'none';
  5036. }
  5037. });
  5038. // Si on est sur la page des notifications, mettre à jour aussi le contenu de la page
  5039. if (typeof updateNotificationPageContent === 'function') {
  5040. updateNotificationPageContent(count);
  5041. }
  5042. }).catch(error => {
  5043. console.error('Erreur lors du chargement du compteur de notifications:', error);
  5044. });{% endif %}
  5045. }
  5046. // Exposer la fonction globalement pour qu'elle puisse être appelée depuis d'autres pages
  5047. window.loadNotificationCount = loadNotificationCount;
  5048. // Recharger le compteur toutes les 30 secondes pour garder les données à jour
  5049. {% if app.user %}
  5050. setInterval(function () {
  5051. loadNotificationCount();
  5052. }, 30000);{% endif %}function loadComparisonCount() {
  5053. {% if app.user %}
  5054. // Ne pas appeler l'API si on est sur une page d'erreur ou de redirection
  5055. if (window.location.pathname.includes('/api/') || window.location.pathname.includes('/login')) {
  5056. return;
  5057. }
  5058. // Utiliser un try-catch pour éviter toute redirection
  5059. try {
  5060. fetch('{{ path(\"ui_api_comparison_count\") }}', {
  5061. method: 'GET',
  5062. headers: {
  5063. 'X-Requested-With': 'XMLHttpRequest',
  5064. 'Accept': 'application/json'
  5065. },
  5066. credentials: 'same-origin',
  5067. redirect: 'error' // Empêcher les redirections automatiques
  5068. }).then(response => { // Vérifier si la réponse est OK
  5069. if (!response.ok) { // Si c'est une redirection (301, 302, etc.) ou une erreur d'authentification, ignorer silencieusement
  5070. if (response.status >= 300 && response.status < 400) {
  5071. console.warn('Redirection détectée, arrêt de la requête');
  5072. return null;
  5073. }
  5074. if (response.status === 401 || response.status === 403) {
  5075. console.warn('Utilisateur non authentifié pour la comparaison');
  5076. return null;
  5077. }
  5078. // Pour les autres erreurs, throw pour être capturé par catch
  5079. throw new Error('Erreur HTTP: ' + response.status);
  5080. }
  5081. // Vérifier que c'est bien du JSON
  5082. const contentType = response.headers.get('content-type');
  5083. if (! contentType || ! contentType.includes('application/json')) { // Si ce n'est pas du JSON, c'est probablement une redirection HTML
  5084. console.warn('La réponse n\\'est pas du JSON, probable redirection');
  5085. return null;
  5086. }
  5087. return response.json();
  5088. }).then(data => { // Si data est null (redirection ou erreur), ne rien faire
  5089. if (!data || typeof data.count === 'undefined') {
  5090. return;
  5091. }
  5092. // Mettre à jour les badges desktop et mobile
  5093. const badges = [document.getElementById('comparisonBadge'), document.getElementById('comparisonBadgeMobile')];
  5094. badges.forEach(badge => {
  5095. if (badge) {
  5096. if (data.count > 0) {
  5097. badge.textContent = data.count;
  5098. badge.style.display = 'flex';
  5099. } else {
  5100. badge.style.display = 'none';
  5101. }
  5102. }
  5103. });
  5104. }).catch(error => { // Ne pas afficher d'erreur si c'est juste une absence d'authentification ou une redirection
  5105. if (error.message && !error.message.includes('401') && !error.message.includes('403') && !error.message.includes('redirect')) {
  5106. console.error('Erreur lors du chargement du compteur de comparaison:', error);
  5107. }
  5108. // Empêcher toute redirection vers l'URL de l'API
  5109. return false;
  5110. });
  5111. } catch (e) { // Capturer toute erreur qui pourrait causer une redirection
  5112. console.warn('Erreur lors de l\\'appel à l\\'API de comparaison:', e);
  5113. }
  5114. {% endif %}
  5115. }
  5116. // Fonction globale pour gérer la comparaison
  5117. function toggleComparison(productId, element) {
  5118. if (! element) {
  5119. element = document.querySelector(`.comparison-btn[data-product-id=\"\${productId}\"]`);
  5120. }
  5121. if (! element) {
  5122. console.error('Bouton de comparaison non trouvé pour le produit', productId);
  5123. return;
  5124. }
  5125. const originalHtml = element.innerHTML;
  5126. // Désactiver le bouton/lien
  5127. if (element.tagName === 'BUTTON') {
  5128. element.disabled = true;
  5129. } else {
  5130. element.style.pointerEvents = 'none';
  5131. element.style.opacity = '0.6';
  5132. } element.innerHTML = '<span class=\"spinner-border spinner-border-sm\"></span>';
  5133. // Vérifier d'abord si le produit est déjà en comparaison
  5134. let isInComparison = false;
  5135. fetch(`/api/comparison/status/\${productId}`).then(response => response.json()).then(data => {
  5136. isInComparison = data.inComparison;
  5137. const url = isInComparison ? `/api/comparison/remove/\${productId}` : `/api/comparison/add/\${productId}`;
  5138. return fetch(url, {
  5139. method: 'POST',
  5140. headers: {
  5141. 'Content-Type': 'application/json',
  5142. 'X-Requested-With': 'XMLHttpRequest'
  5143. }
  5144. });
  5145. }).then(response => response.json()).then(data => {
  5146. if (data.success) { // Mettre à jour le compteur
  5147. loadComparisonCount();
  5148. // Mettre à jour l'apparence du bouton
  5149. if (element) { // Inverser l'état (car on vient de le changer)
  5150. const newState = ! isInComparison;
  5151. // Restaurer le HTML original puis mettre à jour
  5152. element.innerHTML = originalHtml;
  5153. if (newState) {
  5154. element.classList.add('active');
  5155. // Mettre à jour le texte pour les deux types de boutons
  5156. const textEl = element.querySelector('.comparison-text') || element.querySelector('.hover-text') || element.querySelector('p.hover-text');
  5157. if (textEl) 
  5158. textEl.textContent = 'En comparaison';
  5159. // Mettre à jour l'icône si nécessaire (chercher dans span ou i)
  5160. const iconEl = element.querySelector('.lnr-sync, span.lnr-sync, [class*=\"sync\"], i[class*=\"sync\"]');
  5161. if (iconEl) {
  5162. iconEl.style.color = '#28a745';
  5163. iconEl.classList.add('active');
  5164. }
  5165. } else {
  5166. element.classList.remove('active');
  5167. const textEl = element.querySelector('.comparison-text') || element.querySelector('.hover-text') || element.querySelector('p.hover-text');
  5168. if (textEl) 
  5169. textEl.textContent = 'Comparer';
  5170. // Restaurer la couleur de l'icône
  5171. const iconEl = element.querySelector('.lnr-sync, span.lnr-sync, [class*=\"sync\"], i[class*=\"sync\"]');
  5172. if (iconEl) {
  5173. iconEl.style.color = '';
  5174. iconEl.classList.remove('active');
  5175. }
  5176. }
  5177. }
  5178. // Afficher une notification
  5179. showNotification(data.message, 'success');
  5180. } else {
  5181. showNotification(data.message, 'error');
  5182. if (element) {
  5183. element.innerHTML = originalHtml;
  5184. }
  5185. }
  5186. }).catch(error => {
  5187. console.error('Erreur:', error);
  5188. showNotification('Une erreur est survenue', 'error');
  5189. if (element) {
  5190. element.innerHTML = originalHtml;
  5191. }
  5192. }). finally(() => {
  5193. if (element) {
  5194. if (element.tagName === 'BUTTON') {
  5195. element.disabled = false;
  5196. } else {
  5197. element.style.pointerEvents = '';
  5198. element.style.opacity = '';
  5199. }
  5200. }
  5201. });
  5202. }
  5203. // Fonction globale pour gérer les favoris
  5204. function toggleWishlist(productId, element) {
  5205. if (! element) {
  5206. element = document.querySelector(`.wishlist-btn[data-product-id=\"\${productId}\"]`);
  5207. }
  5208. if (! element) {
  5209. console.error('Bouton de wishlist non trouvé pour le produit', productId);
  5210. return;
  5211. }
  5212. const originalHtml = element.innerHTML;
  5213. // Désactiver le bouton/lien
  5214. if (element.tagName === 'BUTTON') {
  5215. element.disabled = true;
  5216. } else {
  5217. element.style.pointerEvents = 'none';
  5218. element.style.opacity = '0.6';
  5219. } element.innerHTML = '<span class=\"spinner-border spinner-border-sm\"></span>';
  5220. // Vérifier d'abord si le produit est déjà en favoris
  5221. let isInWishlist = false;
  5222. fetch(`/api/wishlist/status/\${productId}`).then(response => response.json()).then(data => {
  5223. isInWishlist = data.inWishlist;
  5224. const url = isInWishlist ? `/api/wishlist/remove/\${productId}` : `/api/wishlist/add/\${productId}`;
  5225. return fetch(url, {
  5226. method: 'POST',
  5227. headers: {
  5228. 'Content-Type': 'application/json',
  5229. 'X-Requested-With': 'XMLHttpRequest'
  5230. }
  5231. });
  5232. }).then(response => response.json()).then(data => {
  5233. if (data.success) { // Mettre à jour l'apparence du bouton
  5234. if (element) { // Inverser l'état (car on vient de le changer)
  5235. const newState = ! isInWishlist;
  5236. // Restaurer le HTML original puis mettre à jour
  5237. element.innerHTML = originalHtml;
  5238. // Chercher l'icône dans span ou i
  5239. const icon = element.querySelector('span.lnr-heart, i.lnr-heart, [class*=\"lnr-heart\"]');
  5240. const text = element.querySelector('.wishlist-text') || element.querySelector('.hover-text') || element.querySelector('p.hover-text');
  5241. if (newState) {
  5242. if (icon) { // Pour les icônes linr, on change la classe
  5243. if (icon.classList.contains('lnr-heart')) {
  5244. icon.classList.remove('lnr-heart');
  5245. }
  5246. if (! icon.classList.contains('lnr-heart-filled')) {
  5247. icon.classList.add('lnr-heart-filled');
  5248. }
  5249. icon.style.color = '#dc3545';
  5250. }
  5251. element.classList.add('active');
  5252. if (text) 
  5253. text.textContent = 'Dans favoris';
  5254. } else {
  5255. if (icon) { // Restaurer l'icône originale
  5256. if (icon.classList.contains('lnr-heart-filled')) {
  5257. icon.classList.remove('lnr-heart-filled');
  5258. }
  5259. if (! icon.classList.contains('lnr-heart')) {
  5260. icon.classList.add('lnr-heart');
  5261. }
  5262. icon.style.color = '';
  5263. }
  5264. element.classList.remove('active');
  5265. if (text) 
  5266. text.textContent = 'Favoris';
  5267. }
  5268. }
  5269. // Afficher une notification
  5270. showNotification(data.message, 'success');
  5271. // Si on est sur la page wishlist, recharger la page
  5272. if (window.location.pathname.includes('/account/wishlist')) {
  5273. setTimeout(() => location.reload(), 1000);
  5274. }
  5275. } else {
  5276. showNotification(data.message, 'error');
  5277. if (element) {
  5278. element.innerHTML = originalHtml;
  5279. }
  5280. }
  5281. }).catch(error => {
  5282. console.error('Erreur:', error);
  5283. showNotification('Une erreur est survenue', 'error');
  5284. if (element) {
  5285. element.innerHTML = originalHtml;
  5286. }
  5287. }). finally(() => {
  5288. if (element) {
  5289. if (element.tagName === 'BUTTON') {
  5290. element.disabled = false;
  5291. } else {
  5292. element.style.pointerEvents = '';
  5293. element.style.opacity = '';
  5294. }
  5295. }
  5296. });
  5297. }
  5298. // Fonction pour afficher des notifications
  5299. function showNotification(message, type = 'success') { // Créer l'élément de notification
  5300. const notification = document.createElement('div');
  5301. notification.className = `alert alert-\${
  5302. type === 'success' ? 'success' : 'danger'
  5303. } alert-dismissible fade show position-fixed`;
  5304. notification.style.cssText = 'top: 20px; right: 20px; z-index: 9999; min-width: 300px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);';
  5305. notification.innerHTML = `
  5306.             \${message}
  5307.             <button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\"></button>
  5308.         `;
  5309. document.body.appendChild(notification);
  5310. // Supprimer automatiquement après 3 secondes
  5311. setTimeout(() => {
  5312. notification.remove();
  5313. }, 3000);
  5314. }
  5315. // Initialiser les alertes Bootstrap 5 pour la fermeture
  5316. document.addEventListener('DOMContentLoaded', function () { // S'assurer que les alertes peuvent être fermées
  5317. const alertCloseButtons = document.querySelectorAll('.flash-message .btn-close');
  5318. alertCloseButtons.forEach(function (button) {
  5319. button.addEventListener('click', function () {
  5320. const alert = this.closest('.alert');
  5321. if (alert) {
  5322. alert.classList.remove('show');
  5323. setTimeout(function () {
  5324. alert.remove();
  5325. }, 150);
  5326. }
  5327. });
  5328. });
  5329. // Charger les statuts initiaux des produits
  5330. {% if app.user %}
  5331. // Charger les statuts de comparaison pour tous les produits visibles
  5332. document.querySelectorAll('.comparison-btn[data-product-id]').forEach(btn => {
  5333. const productId = btn.dataset.productId;
  5334. fetch(`/api/comparison/status/\${productId}`).then(response => response.json()).then(data => {
  5335. if (data.inComparison) {
  5336. btn.classList.add('active');
  5337. // Mettre à jour le texte pour les deux types de boutons
  5338. const textEl = btn.querySelector('.comparison-text') || btn.querySelector('.hover-text') || btn.querySelector('p.hover-text');
  5339. if (textEl) 
  5340. textEl.textContent = 'En comparaison';
  5341. // Mettre à jour l'icône si nécessaire
  5342. const iconEl = btn.querySelector('.lnr-sync, [class*=\"sync\"]');
  5343. if (iconEl) 
  5344. iconEl.style.color = '#28a745';
  5345. }
  5346. }).catch(() => {});
  5347. });
  5348. // Charger les statuts de wishlist pour tous les produits visibles
  5349. document.querySelectorAll('.wishlist-btn[data-product-id]').forEach(btn => {
  5350. const productId = btn.dataset.productId;
  5351. fetch(`/api/wishlist/status/\${productId}`).then(response => response.json()).then(data => {
  5352. if (data.inWishlist) {
  5353. // Chercher l'icône dans span ou i
  5354. const icon = btn.querySelector('span.lnr-heart, i.lnr-heart, [class*=\"lnr-heart\"]');
  5355. if (icon) {
  5356. icon.classList.remove('lnr-heart');
  5357. icon.classList.add('lnr-heart');
  5358. icon.style.color = '#ffa200';
  5359. }
  5360. // Mettre à jour le texte pour les deux types de boutons
  5361. const textEl = btn.querySelector('.wishlist-text') || btn.querySelector('.hover-text') || btn.querySelector('p.hover-text');
  5362. if (textEl) 
  5363. textEl.textContent = 'favoris';
  5364. }
  5365. }).catch(() => {});
  5366. });
  5367. // Charger le compteur de comparaison
  5368. loadComparisonCount();{% endif %}
  5369. });
  5370. \t\t</script>
  5371. \t\t<script>
  5372. \t\t\t// Loader global pour tous les boutons de formulaire
  5373. document.addEventListener('DOMContentLoaded', function () { // Intercepter tous les formulaires
  5374. const forms = document.querySelectorAll('form');
  5375. forms.forEach(function (form) {
  5376. form.addEventListener('submit', function (e) {
  5377. const submitButtons = form.querySelectorAll('button[type=\"submit\"], input[type=\"submit\"], button:not([type])');
  5378. submitButtons.forEach(function (button) { // Vérifier si le bouton n'est pas déjà désactivé
  5379. if (! button.disabled && ! button.classList.contains('loading')) {
  5380. button.classList.add('loading');
  5381. button.disabled = true;
  5382. // Sauvegarder le texte original
  5383. const originalText = button.innerHTML;
  5384. button.setAttribute('data-original-text', originalText);
  5385. // Ajouter le loader
  5386. button.innerHTML = '<span class=\"spinner-border spinner-border-sm me-2\" role=\"status\" aria-hidden=\"true\"></span>Envoi...';
  5387. // Si le formulaire n'est pas valide, réactiver le bouton après 1 seconde
  5388. setTimeout(function () {
  5389. if (! form.checkValidity()) {
  5390. button.classList.remove('loading');
  5391. button.disabled = false;
  5392. button.innerHTML = originalText;
  5393. }
  5394. }, 1000);
  5395. }
  5396. });
  5397. });
  5398. });
  5399. // Pour les boutons qui déclenchent des actions AJAX
  5400. const ajaxButtons = document.querySelectorAll('[data-ajax], .ajax-submit, button[data-submit]');
  5401. ajaxButtons.forEach(function (button) {
  5402. button.addEventListener('click', function (e) {
  5403. if (this.disabled || this.classList.contains('loading')) {
  5404. e.preventDefault();
  5405. return false;
  5406. }
  5407. this.classList.add('loading');
  5408. this.disabled = true;
  5409. const originalText = this.innerHTML;
  5410. this.setAttribute('data-original-text', originalText);
  5411. this.innerHTML = '<span class=\"spinner-border spinner-border-sm me-2\" role=\"status\" aria-hidden=\"true\"></span>Chargement...';
  5412. });
  5413. });
  5414. // Gestionnaire spécifique pour le formulaire de newsletter
  5415. const newsletterForm = document.querySelector('.footer-newsletter-form');
  5416. if (newsletterForm) {
  5417. newsletterForm.addEventListener('submit', function (e) {
  5418. const submitBtn = this.querySelector('.newsletter-btn');
  5419. if (submitBtn && ! submitBtn.disabled) {
  5420. submitBtn.classList.add('loading');
  5421. submitBtn.disabled = true;
  5422. // Afficher le loader et masquer l'icône
  5423. const icon = submitBtn.querySelector('.newsletter-btn-icon');
  5424. const loader = submitBtn.querySelector('.newsletter-btn-loader');
  5425. if (icon) 
  5426. icon.style.display = 'none';
  5427. if (loader) 
  5428. loader.style.display = 'flex';
  5429. // Réactiver le bouton après 5 secondes au cas où la requête échoue silencieusement
  5430. setTimeout(function () {
  5431. if (submitBtn.classList.contains('loading')) {
  5432. submitBtn.classList.remove('loading');
  5433. submitBtn.disabled = false;
  5434. if (icon) 
  5435. icon.style.display = 'flex';
  5436. if (loader) 
  5437. loader.style.display = 'none';
  5438. }
  5439. }, 5000);
  5440. }
  5441. });
  5442. // Gérer la réponse du formulaire (si AJAX)
  5443. newsletterForm.addEventListener('submit', function (e) {
  5444. // Si le formulaire est soumis normalement (non-AJAX), le navigateur gère la réponse
  5445. // Sinon, on peut intercepter pour gérer la réponse AJAX ici
  5446. });
  5447. }
  5448. });
  5449. // CSS pour le spinner
  5450. const style = document.createElement('style');
  5451. style.textContent = `
  5452.     .spinner-border-sm {
  5453.         width: 1rem;
  5454.         height: 1rem;
  5455.         border-width: 0.15em;
  5456.     }
  5457.     .spinner-border {
  5458.         display: inline-block;
  5459.         width: 1rem;
  5460.         height: 1rem;
  5461.         vertical-align: text-bottom;
  5462.         border: 0.15em solid currentColor;
  5463.         border-right-color: transparent;
  5464.         border-radius: 50%;
  5465.         animation: spinner-border 0.75s linear infinite;
  5466.     }
  5467.     @keyframes spinner-border {
  5468.         to { transform: rotate(360deg); }
  5469.     }
  5470.     button.loading {
  5471.         opacity: 0.7;
  5472.         cursor: not-allowed !important;
  5473.     }
  5474. `;
  5475. document.head.appendChild(style);
  5476. \t\t</script>
  5477. \t\t<!-- Cart Modal -->
  5478. \t\t<div id=\"ebay-cart-modal\" class=\"ebay-cart-modal-overlay\" style=\"display: none;\" data-url=\"\">
  5479. \t\t\t<div class=\"ebay-cart-modal\">
  5480. \t\t\t\t<div class=\"ebay-modal-header\">
  5481. \t\t\t\t\t<h3>
  5482. \t\t\t\t\t\t<i class=\"lnr lnr-checkmark-circle\"></i>
  5483. \t\t\t\t\t\tAjouté au panier !</h3>
  5484. \t\t\t\t\t<button class=\"ebay-modal-close\" onclick=\"closeEbayCartModal()\">&times;</button>
  5485. \t\t\t\t</div>
  5486. \t\t\t\t<div class=\"ebay-modal-content\">
  5487. \t\t\t\t\t<div class=\"ebay-product-info\">
  5488. \t\t\t\t\t\t<div class=\"ebay-product-image\">
  5489. \t\t\t\t\t\t\t<img id=\"ebay-modal-product-image\" src=\"\" alt=\"Produit\"/>
  5490. \t\t\t\t\t\t</div>
  5491. \t\t\t\t\t\t<div class=\"ebay-product-details\">
  5492. \t\t\t\t\t\t\t<h4 id=\"ebay-modal-product-name\">Nom du produit</h4>
  5493. \t\t\t\t\t\t\t<div class=\"ebay-product-price\" id=\"ebay-modal-product-price\">Prix</div>
  5494. \t\t\t\t\t\t\t<div class=\"ebay-product-quantity\">
  5495. \t\t\t\t\t\t\t\t<span>Quantité:
  5496. \t\t\t\t\t\t\t\t</span>
  5497. \t\t\t\t\t\t\t\t<span id=\"ebay-modal-product-quantity\">1</span>
  5498. \t\t\t\t\t\t\t</div>
  5499. \t\t\t\t\t\t</div>
  5500. \t\t\t\t\t</div>
  5501. \t\t\t\t\t<!-- Recommendations Section -->
  5502. \t\t\t\t\t<div class=\"ebay-recommendations\" style=\"display: none;\">
  5503. \t\t\t\t\t\t<h4>Les clients ont aussi acheté :</h4>
  5504. \t\t\t\t\t\t<div
  5505. \t\t\t\t\t\t\tclass=\"ebay-recommendations-grid\" id=\"ebay-modal-recommendations\"><!-- Recommendations will be injected here -->
  5506. \t\t\t\t\t\t</div>
  5507. \t\t\t\t\t</div>
  5508. \t\t\t\t\t<div class=\"ebay-modal-actions\">
  5509. \t\t\t\t\t\t<button class=\"ebay-btn-continue\" onclick=\"closeEbayCartModal()\">
  5510. \t\t\t\t\t\t\tContinuer mes achats
  5511. \t\t\t\t\t\t</button>
  5512. \t\t\t\t\t\t<a href=\"{{ path('ui_cart') }}\" class=\"ebay-btn-view-cart\">
  5513. \t\t\t\t\t\t\tVoir mon panier
  5514. \t\t\t\t\t\t</a>
  5515. \t\t\t\t\t</div>
  5516. \t\t\t\t</div>
  5517. \t\t\t</div>
  5518. \t\t</div>
  5519. \t\t<script src=\"{{ asset('ui/js/cart-modal.js') }}\"></script>
  5520. \t\t<script src=\"{{ asset('ui/js/notification-badge.js') }}\"></script>
  5521. \t\t{% block javascripts %}{% endblock %}
  5522. \t</body>
  5523. </html>
  5524. ""base_home.html.twig""/home/u540977899/domains/maketou-ht.com/public_html/templates/base_home.html.twig");
  5525.     }
  5526. }