var/cache/dev/twig/c2/c224d21395ebef29d69a3ef70e9293d0.php line 46

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. /* home/cart.html.twig */
  16. class __TwigTemplate_120158e7ea77c8a776f55513944d6d80 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->blocks = [
  28.             'title' => [$this'block_title'],
  29.             'body' => [$this'block_body'],
  30.             'stylesheets' => [$this'block_stylesheets'],
  31.             'javascripts' => [$this'block_javascripts'],
  32.         ];
  33.     }
  34.     protected function doGetParent(array $context): bool|string|Template|TemplateWrapper
  35.     {
  36.         // line 1
  37.         return "base_home.html.twig";
  38.     }
  39.     protected function doDisplay(array $context, array $blocks = []): iterable
  40.     {
  41.         $macros $this->macros;
  42.         $__internal_5a27a8ba21ca79b61932376b2fa922d2 $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  43.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "template""home/cart.html.twig"));
  44.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  45.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "template""home/cart.html.twig"));
  46.         $this->parent $this->load("base_home.html.twig"1);
  47.         yield from $this->parent->unwrap()->yield($contextarray_merge($this->blocks$blocks));
  48.         
  49.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  50.         
  51.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  52.     }
  53.     // line 3
  54.     /**
  55.      * @return iterable<null|scalar|\Stringable>
  56.      */
  57.     public function block_title(array $context, array $blocks = []): iterable
  58.     {
  59.         $macros $this->macros;
  60.         $__internal_5a27a8ba21ca79b61932376b2fa922d2 $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  61.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""title"));
  62.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  63.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""title"));
  64.         yield "Panier | MaketOu";
  65.         
  66.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  67.         
  68.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  69.         yield from [];
  70.     }
  71.     // line 5
  72.     /**
  73.      * @return iterable<null|scalar|\Stringable>
  74.      */
  75.     public function block_body(array $context, array $blocks = []): iterable
  76.     {
  77.         $macros $this->macros;
  78.         $__internal_5a27a8ba21ca79b61932376b2fa922d2 $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  79.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""body"));
  80.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  81.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""body"));
  82.         // line 6
  83.         yield "    <!-- Start Banner Area -->
  84.     <section class=\"banner-area organic-breadcrumb\">
  85.         <div class=\"container\">
  86.             <div class=\"breadcrumb-banner d-flex flex-wrap align-items-center justify-content-end\">
  87.                 <div class=\"col-first\">
  88.                     <h1>Panier</h1>
  89.                     <nav class=\"d-flex align-items-center\">
  90.                         <a href=\"";
  91.         // line 13
  92.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_home");
  93.         yield "\">Accueil<span class=\"lnr lnr-arrow-right\"></span></a>
  94.                         <a href=\"javascript:void(0)\">Panier</a>
  95.                     </nav>
  96.                 </div>
  97.             </div>
  98.         </div>
  99.     </section>
  100.     <!-- End Banner Area -->
  101.     <!--================Cart Area =================-->
  102.     <section class=\"cart_area\">
  103.         <div class=\"container\">
  104.             <div class=\"row\">
  105.                 <div class=\"col-lg-8\">
  106.                     <div class=\"cart_inner\">
  107.                         <div class=\"table-responsive\">
  108.                             <table class=\"table\">
  109.                                 <thead>
  110.                                     <tr>
  111.                                         <th scope=\"col\">Produit</th>
  112.                                         <th scope=\"col\">Prix</th>
  113.                                         <th scope=\"col\">Quantité</th>
  114.                                         <th scope=\"col\">Total</th>
  115.                                         <th scope=\"col\">Action</th>
  116.                                     </tr>
  117.                                 </thead>
  118.                                 <tbody>
  119.                                     ";
  120.         // line 40
  121.         $context['_parent'] = $context;
  122.         $context['_seq'] = CoreExtension::ensureTraversable(($context["items"] ?? null));
  123.         $context['_iterated'] = false;
  124.         foreach ($context['_seq'] as $context["_key"] => $context["item"]) {
  125.             // line 41
  126.             yield "                                    <tr>
  127.                                         <td data-label=\"Produit\">
  128.                                             <div class=\"cart-item\">
  129.                                                 ";
  130.             // line 44
  131.             $context["image"] = (((CoreExtension::getAttribute($this->env$this->source$context["item"], "image", [], "any"truetruefalse44) && (Twig\Extension\CoreExtension::length($this->env->getCharset(), CoreExtension::getAttribute($this->env$this->source$context["item"], "image", [], "any"falsefalsefalse44)) > 0))) ? (CoreExtension::getAttribute($this->env$this->source$context["item"], "image", [], "any"falsefalsefalse44)) : ($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/img/category/s-p1.jpg")));
  132.             // line 45
  133.             yield "                                                <img src=\"";
  134.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(($context["image"] ?? null), "html"nulltrue);
  135.             yield "\" alt=\"";
  136.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env$this->source$context["item"], "name", [], "any"falsefalsefalse45), "html"nulltrue);
  137.             yield "\" class=\"cart-item-image\">
  138.                                                 <div class=\"cart-item-info\">
  139.                                                     <a href=\"";
  140.             // line 47
  141.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_product_show", ["slug" => CoreExtension::getAttribute($this->env$this->source$context["item"], "slug", [], "any"falsefalsefalse47)]), "html"nulltrue);
  142.             yield "\" class=\"cart-item-name\">";
  143.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env$this->source$context["item"], "name", [], "any"falsefalsefalse47), "html"nulltrue);
  144.             yield "</a>
  145.                                                 </div>
  146.                                             </div>
  147.                                         </td>
  148.                                         <td data-label=\"Prix\">
  149.                                             <span class=\"cart-item-price\">";
  150.             // line 52
  151.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Twig\Extension\CoreExtension']->formatNumber(CoreExtension::getAttribute($this->env$this->source$context["item"], "price", [], "any"falsefalsefalse52), 2"."" "), "html"nulltrue);
  152.             yield " HTG</span>
  153.                                         </td>
  154.                                         <td data-label=\"Quantité\">
  155.                                             <div class=\"quantity-controls\">
  156.                                                 <button class=\"quantity-btn quantity-btn-decrease\" id=\"decrease-btn-";
  157.             // line 56
  158.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env$this->source$context["item"], "id", [], "any"falsefalsefalse56), "html"nulltrue);
  159.             yield "\" data-product-id=\"";
  160.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env$this->source$context["item"], "id", [], "any"falsefalsefalse56), "html"nulltrue);
  161.             yield "\" onclick=\"handleDecreaseOrRemove(";
  162.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env$this->source$context["item"], "id", [], "any"falsefalsefalse56), "html"nulltrue);
  163.             yield ")\">
  164.                                                     ";
  165.             // line 57
  166.             if ((CoreExtension::getAttribute($this->env$this->source$context["item"], "qty", [], "any"falsefalsefalse57) == 1)) {
  167.                 // line 58
  168.                 yield "                                                        <i class=\"lnr lnr-trash\"></i>
  169.                                                     ";
  170.             } else {
  171.                 // line 60
  172.                 yield "                                                        <span>−</span>
  173.                                                     ";
  174.             }
  175.             // line 62
  176.             yield "                                                </button>
  177.                                                 <input type=\"text\" value=\"";
  178.             // line 63
  179.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env$this->source$context["item"], "qty", [], "any"falsefalsefalse63), "html"nulltrue);
  180.             yield "\" class=\"quantity-input\" id=\"qty-";
  181.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env$this->source$context["item"], "id", [], "any"falsefalsefalse63), "html"nulltrue);
  182.             yield "\" onchange=\"updateQuantity(";
  183.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env$this->source$context["item"], "id", [], "any"falsefalsefalse63), "html"nulltrue);
  184.             yield ", this.value)\">
  185.                                                 <button class=\"quantity-btn\" onclick=\"changeQuantity(";
  186.             // line 64
  187.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env$this->source$context["item"], "id", [], "any"falsefalsefalse64), "html"nulltrue);
  188.             yield ", 1)\">+</button>
  189.                                             </div>
  190.                                         </td>
  191.                                         <td data-label=\"Total\">
  192.                                             <span class=\"cart-item-total\" id=\"total-";
  193.             // line 68
  194.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env$this->source$context["item"], "id", [], "any"falsefalsefalse68), "html"nulltrue);
  195.             yield "\">";
  196.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Twig\Extension\CoreExtension']->formatNumber((CoreExtension::getAttribute($this->env$this->source$context["item"], "price", [], "any"falsefalsefalse68) * CoreExtension::getAttribute($this->env$this->source$context["item"], "qty", [], "any"falsefalsefalse68)), 2"."" "), "html"nulltrue);
  197.             yield " HTG</span>
  198.                                         </td>
  199.                                         <td data-label=\"Action\">
  200.                                             <button class=\"remove-btn\" onclick=\"removeFromCart(";
  201.             // line 71
  202.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env$this->source$context["item"], "id", [], "any"falsefalsefalse71), "html"nulltrue);
  203.             yield ")\">Supprimer</button>
  204.                                         </td>
  205.                                     </tr>
  206.                                     ";
  207.             $context['_iterated'] = true;
  208.         }
  209.         // line 74
  210.         if (!$context['_iterated']) {
  211.             // line 75
  212.             yield "                                        <tr>
  213.                                             <td colspan=\"5\" style=\"text-align: center; padding: 50px;\">
  214.                                                 Votre panier est vide.
  215.                                                 <br>
  216.                                                 <a href=\"";
  217.             // line 79
  218.             yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
  219.             yield "\" style=\"color: #007185;\">Continuer vos achats</a>
  220.                                             </td>
  221.                                         </tr>
  222.                                     ";
  223.         }
  224.         $_parent $context['_parent'];
  225.         unset($context['_seq'], $context['_key'], $context['item'], $context['_parent'], $context['_iterated']);
  226.         $context array_intersect_key($context$_parent) + $_parent;
  227.         // line 83
  228.         yield "                                </tbody>
  229.                             </table>
  230.                         </div>
  231.                     </div>
  232.                 </div>
  233.                 <div class=\"col-lg-4\">
  234.                     <div class=\"cart-summary\">
  235.                         <h3>Résumé de la commande</h3>
  236.                         <div class=\"cart-subtotal\">
  237.                             <span id=\"cart-subtotal-label\">Sous-total (<span id=\"cart-item-count\">";
  238.         // line 92
  239.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(Twig\Extension\CoreExtension::length($this->env->getCharset(), ($context["items"] ?? null)), "html"nulltrue);
  240.         yield "</span> article";
  241.         yield (((Twig\Extension\CoreExtension::length($this->env->getCharset(), ($context["items"] ?? null)) > 1)) ? ("s") : (""));
  242.         yield ")</span>
  243.                             <span id=\"cart-subtotal\">";
  244.         // line 93
  245.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Twig\Extension\CoreExtension']->formatNumber(($context["subtotal"] ?? null), 2"."" "), "html"nulltrue);
  246.         yield " HTG</span>
  247.                         </div>
  248.                         <div class=\"cart-total\">
  249.                             <span>Total</span>
  250.                             <span id=\"cart-total\">";
  251.         // line 97
  252.         yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Twig\Extension\CoreExtension']->formatNumber(($context["subtotal"] ?? null), 2"."" "), "html"nulltrue);
  253.         yield " HTG</span>
  254.                         </div>
  255.                         <button class=\"checkout-btn mt-3\" onclick=\"proceedToCheckout()\">Passer la commande</button>
  256.                         <button class=\"continue-shopping\" onclick=\"window.location.href='";
  257.         // line 100
  258.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
  259.         yield "'\">Continuer vos achats</button>
  260.                     </div>
  261.                 </div>
  262.             </div>
  263.         </div>
  264.     </section>
  265.     <!--================End Cart Area =================-->
  266.     <!-- Modal personnalisé -->
  267.     <div id=\"customModal\" class=\"custom-modal\">
  268.         <div class=\"custom-modal-overlay\"></div>
  269.         <div class=\"custom-modal-content\">
  270.             <div class=\"custom-modal-header\">
  271.                 <h3 class=\"custom-modal-title\" id=\"modalTitle\">Titre</h3>
  272.                 <button class=\"custom-modal-close\" onclick=\"closeCustomModal()\" aria-label=\"Fermer\">
  273.                     <span>&times;</span>
  274.                 </button>
  275.             </div>
  276.             <div class=\"custom-modal-body\" id=\"modalBody\">
  277.                 <p id=\"modalMessage\">Message</p>
  278.             </div>
  279.             <div class=\"custom-modal-footer\" id=\"modalFooter\">
  280.                 <button class=\"custom-modal-btn custom-modal-btn-primary\" id=\"modalConfirmBtn\" onclick=\"confirmModalAction()\">Confirmer</button>
  281.                 <button class=\"custom-modal-btn custom-modal-btn-secondary\" id=\"modalCancelBtn\" onclick=\"closeCustomModal()\">Annuler</button>
  282.             </div>
  283.         </div>
  284.     </div>
  285. ";
  286.         
  287.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  288.         
  289.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  290.         yield from [];
  291.     }
  292.     // line 130
  293.     /**
  294.      * @return iterable<null|scalar|\Stringable>
  295.      */
  296.     public function block_stylesheets(array $context, array $blocks = []): iterable
  297.     {
  298.         $macros $this->macros;
  299.         $__internal_5a27a8ba21ca79b61932376b2fa922d2 $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  300.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""stylesheets"));
  301.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  302.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""stylesheets"));
  303.         // line 131
  304.         yield "<style>
  305. .cart_area {
  306.     background-color: #f8f8f8;
  307.     padding: 20px 0;
  308. }
  309. .cart_inner {
  310.     background: white;
  311.     border-radius: 8px;
  312.     box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  313.     overflow: hidden;
  314. }
  315. .table th {
  316.     background-color: #f3f3f3;
  317.     border-bottom: 2px solid #ddd;
  318.     font-weight: 600;
  319.     color: #333;
  320.     padding: 15px;
  321. }
  322. .table td {
  323.     vertical-align: middle;
  324.     padding: 15px;
  325. }
  326. .cart-item {
  327.     display: flex;
  328.     align-items: center;
  329. }
  330. .cart-item-image {
  331.     width: 80px;
  332.     height: 80px;
  333.     object-fit: cover;
  334.     border-radius: 8px;
  335.     margin-right: 15px;
  336. }
  337. .cart-item-info {
  338.     flex-grow: 1;
  339. }
  340. .cart-item-name {
  341.     font-weight: 500;
  342.     color: #007185;
  343.     text-decoration: none;
  344.     margin-bottom: 5px;
  345. }
  346. .cart-item-name:hover {
  347.     text-decoration: underline;
  348. }
  349. .cart-item-price {
  350.     color: #333;
  351.     font-size: 18px;
  352.     font-weight: 700;
  353. }
  354. .quantity-controls {
  355.     display: flex !important;
  356.     align-items: center !important;
  357.     justify-content: center !important;
  358.     border: 1px solid #ddd !important;
  359.     border-radius: 4px !important;
  360.     width: 120px !important;
  361.     height: 40px !important;
  362.     position: relative !important;
  363.     background: white !important;
  364.     overflow: hidden !important;
  365. }
  366. .quantity-controls .quantity-btn {
  367.     background: #f8f8f8 !important;
  368.     border: none !important;
  369.     width: 35px !important;
  370.     height: 100% !important;
  371.     min-width: 35px !important;
  372.     cursor: pointer !important;
  373.     font-size: 18px !important;
  374.     font-weight: 600 !important;
  375.     color: #333 !important;
  376.     display: flex !important;
  377.     align-items: center !important;
  378.     justify-content: center !important;
  379.     padding: 0 !important;
  380.     margin: 0 !important;
  381.     line-height: 1 !important;
  382.     transition: background-color 0.2s ease !important;
  383.     position: relative !important;
  384.     z-index: 1 !important;
  385. }
  386. .quantity-controls .quantity-btn:first-child {
  387.     border-right: 1px solid #ddd !important;
  388. }
  389. .quantity-controls .quantity-btn:last-child {
  390.     border-left: 1px solid #ddd !important;
  391. }
  392. .quantity-controls .quantity-btn:hover {
  393.     background: #e7e7e7 !important;
  394.     color: #000 !important;
  395. }
  396. .quantity-controls .quantity-btn:active {
  397.     background: #d0d0d0 !important;
  398. }
  399. .quantity-controls .quantity-btn-remove {
  400.     background: #f8f8f8 !important;
  401.     color: #dc3545 !important;
  402. }
  403. .quantity-controls .quantity-btn-remove:hover {
  404.     background: #dc3545 !important;
  405.     color: white !important;
  406. }
  407. .quantity-controls .quantity-btn-remove i {
  408.     font-size: 16px !important;
  409. }
  410. .quantity-controls .quantity-btn-decrease span {
  411.     font-size: 24px !important;
  412.     font-weight: 300 !important;
  413.     line-height: 1 !important;
  414. }
  415. .quantity-controls .quantity-input {
  416.     border: none !important;
  417.     width: 50px !important;
  418.     min-width: 50px !important;
  419.     height: 100% !important;
  420.     text-align: center !important;
  421.     font-size: 15px !important;
  422.     font-weight: 500 !important;
  423.     padding: 0 !important;
  424.     margin: 0 !important;
  425.     background: white !important;
  426.     color: #333 !important;
  427.     outline: none !important;
  428.     box-shadow: none !important;
  429.     -moz-appearance: textfield !important;
  430.     position: relative !important;
  431.     z-index: 1 !important;
  432. }
  433. .quantity-controls .quantity-input::-webkit-outer-spin-button,
  434. .quantity-controls .quantity-input::-webkit-inner-spin-button {
  435.     -webkit-appearance: none !important;
  436.     margin: 0 !important;
  437. }
  438. /* Surcharger les styles externes qui pourraient interférer */
  439. .cart_inner .table tbody tr td .quantity-controls,
  440. .cart_inner .table tbody tr td .quantity-controls .quantity-btn,
  441. .cart_inner .table tbody tr td .quantity-controls .quantity-input {
  442.     position: relative !important;
  443. }
  444. .cart_inner .table tbody tr td .quantity-controls .quantity-btn:before,
  445. .cart_inner .table tbody tr td .quantity-controls .quantity-btn:after {
  446.     display: none !important;
  447.     content: none !important;
  448. }
  449. .cart-item-total {
  450.     font-size: 18px;
  451.     font-weight: 700;
  452.     color: #333;
  453. }
  454. /* Animation pour le badge du panier */
  455. @keyframes bounce {
  456.     0%, 20%, 50%, 80%, 100% {
  457.         transform: translateY(0);
  458.     }
  459.     40% {
  460.         transform: translateY(-5px);
  461.     }
  462.     60% {
  463.         transform: translateY(-3px);
  464.     }
  465. }
  466. /* Responsive Styles */
  467. @media (max-width: 991.98px) {
  468.     .cart_area {
  469.         padding: 15px 0;
  470.     }
  471.     
  472.     .cart-summary {
  473.         margin-top: 2rem;
  474.     }
  475. }
  476. @media (max-width: 767.98px) {
  477.     .cart_inner {
  478.         border-radius: 0;
  479.     }
  480.     
  481.     .table {
  482.         font-size: 0.875rem;
  483.     }
  484.     
  485.     .table th {
  486.         padding: 10px 8px;
  487.         font-size: 0.8rem;
  488.     }
  489.     
  490.     .table td {
  491.         padding: 10px 8px;
  492.     }
  493.     
  494.     .cart-item {
  495.         flex-direction: column;
  496.         align-items: flex-start;
  497.     }
  498.     
  499.     .cart-item-image {
  500.         width: 60px;
  501.         height: 60px;
  502.         margin-right: 0;
  503.         margin-bottom: 10px;
  504.     }
  505.     
  506.     .cart-item-name {
  507.         font-size: 0.9rem;
  508.     }
  509.     
  510.     .cart-item-price,
  511.     .cart-item-total {
  512.         font-size: 1rem;
  513.     }
  514.     
  515.     .quantity-controls {
  516.         width: 110px !important;
  517.         height: 38px !important;
  518.     }
  519.     
  520.     .quantity-controls .quantity-btn {
  521.         width: 32px !important;
  522.         font-size: 16px !important;
  523.     }
  524.     
  525.     .quantity-controls .quantity-input {
  526.         width: 46px !important;
  527.         font-size: 14px !important;
  528.     }
  529.     
  530.     .cart-summary {
  531.         margin-top: 1.5rem;
  532.         padding: 1.5rem;
  533.     }
  534.     
  535.     .checkout-btn,
  536.     .continue-shopping {
  537.         width: 100%;
  538.         margin-bottom: 0.5rem;
  539.     }
  540. }
  541. @media (max-width: 575.98px) {
  542.     .table thead {
  543.         display: none;
  544.     }
  545.     
  546.     .table tbody tr {
  547.         display: block;
  548.         margin-bottom: 1rem;
  549.         border: 1px solid #dee2e6;
  550.         border-radius: 8px;
  551.         padding: 1rem;
  552.     }
  553.     
  554.     .table tbody td {
  555.         display: flex;
  556.         justify-content: space-between;
  557.         align-items: center;
  558.         padding: 0.5rem 0;
  559.         border: none;
  560.         text-align: right;
  561.     }
  562.     
  563.     .table tbody td::before {
  564.         content: attr(data-label);
  565.         font-weight: bold;
  566.         text-align: left;
  567.         margin-right: 1rem;
  568.     }
  569.     
  570.     .table tbody td:first-child {
  571.         flex-direction: column;
  572.         align-items: flex-start;
  573.     }
  574.     
  575.     .cart-item-image {
  576.         width: 100%;
  577.         height: 200px;
  578.         margin-bottom: 1rem;
  579.     }
  580.     
  581.     .cart-item-name {
  582.         font-size: 1rem;
  583.         margin-bottom: 0.5rem;
  584.     }
  585.     
  586.     .quantity-controls {
  587.         width: 100% !important;
  588.         max-width: 150px !important;
  589.         margin: 0 auto !important;
  590.         justify-content: center !important;
  591.         height: 40px !important;
  592.     }
  593.     
  594.     .quantity-controls .quantity-btn {
  595.         width: 40px !important;
  596.         font-size: 18px !important;
  597.     }
  598.     
  599.     .quantity-controls .quantity-input {
  600.         width: 60px !important;
  601.         font-size: 16px !important;
  602.     }
  603.     
  604.     .remove-btn {
  605.         width: 100%;
  606.         margin-top: 0.5rem;
  607.     }
  608. }
  609. .remove-btn {
  610.     background: #ff9900;
  611.     color: white;
  612.     border: none;
  613.     padding: 8px 16px;
  614.     border-radius: 4px;
  615.     cursor: pointer;
  616.     font-size: 12px;
  617. }
  618. .remove-btn:hover {
  619.     background: #e68900;
  620. }
  621. .cart-summary {
  622.     background: white;
  623.     border-radius: 8px;
  624.     box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  625.     padding: 20px;
  626.     height: fit-content;
  627. }
  628. .cart-subtotal {
  629.     display: flex;
  630.     justify-content: space-between;
  631.     padding: 10px 0;
  632.     border-bottom: 1px solid #ddd;
  633.     margin-bottom: 15px;
  634. }
  635. .cart-total {
  636.     font-size: 20px;
  637.     font-weight: 700;
  638.     color: #333;
  639. }
  640. .checkout-btn {
  641.     background: #ffa200;
  642.     color: white;
  643.     border: none;
  644.     padding: 12px 24px;
  645.     border-radius: 4px;
  646.     cursor: pointer;
  647.     width: 100%;
  648.     font-size: 16px;
  649.     font-weight: 600;
  650. }
  651. .checkout-btn:hover {
  652.     background: #e68900;
  653. }
  654. .checkout-btn:disabled,
  655. .checkout-btn.disabled {
  656.     background: #cccccc !important;
  657.     color: #666666 !important;
  658.     cursor: pointer !important; /* Garder le curseur pointer pour indiquer que c'est cliquable */
  659.     opacity: 0.6;
  660.     pointer-events: auto !important; /* S'assurer que le clic fonctionne */
  661. }
  662. .checkout-btn:disabled:hover,
  663. .checkout-btn.disabled:hover {
  664.     background: #cccccc !important;
  665.     transform: none !important;
  666.     box-shadow: none !important;
  667. }
  668. .continue-shopping {
  669.     background: #095ad3;
  670.     color: #ffffff;
  671.     border: none;
  672.     padding: 12px 24px;
  673.     border-radius: 4px;
  674.     cursor: pointer;
  675.     width: 100%;
  676.     font-size: 16px;
  677.     font-weight: 600;
  678.     margin-top: 10px;
  679. }
  680. .continue-shopping:hover {
  681.     background: #e68900;
  682.     color: #ffffff
  683. }
  684. /* ============================================
  685.    MODAL PERSONNALISÉ
  686.    ============================================ */
  687. .custom-modal {
  688.     display: none;
  689.     position: fixed;
  690.     top: 0;
  691.     left: 0;
  692.     width: 100%;
  693.     height: 100%;
  694.     z-index: 10000;
  695.     opacity: 0;
  696.     transition: opacity 0.3s ease;
  697. }
  698. .custom-modal.show {
  699.     display: flex;
  700.     align-items: center;
  701.     justify-content: center;
  702.     opacity: 1;
  703. }
  704. .custom-modal-overlay {
  705.     position: absolute;
  706.     top: 0;
  707.     left: 0;
  708.     width: 100%;
  709.     height: 100%;
  710.     background: rgba(0, 0, 0, 0.5);
  711.     backdrop-filter: blur(4px);
  712.     -webkit-backdrop-filter: blur(4px);
  713. }
  714. .custom-modal-content {
  715.     position: relative;
  716.     background: white;
  717.     border-radius: 12px;
  718.     box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
  719.     max-width: 500px;
  720.     width: 90%;
  721.     max-height: 90vh;
  722.     overflow: hidden;
  723.     transform: scale(0.9) translateY(-20px);
  724.     transition: transform 0.3s ease;
  725.     z-index: 10001;
  726. }
  727. .custom-modal.show .custom-modal-content {
  728.     transform: scale(1) translateY(0);
  729. }
  730. .custom-modal-header {
  731.     display: flex;
  732.     align-items: center;
  733.     justify-content: space-between;
  734.     padding: 20px 24px;
  735.     border-bottom: 1px solid #e0e0e0;
  736.     background: linear-gradient(135deg, #ffa200 0%, #ff9900 100%);
  737. }
  738. .custom-modal-header.error {
  739.     background: linear-gradient(135deg, #dc3545 0%, #c82333 100%);
  740. }
  741. .custom-modal-header.success {
  742.     background: linear-gradient(135deg, #28a745 0%, #218838 100%);
  743. }
  744. .custom-modal-header.warning {
  745.     background: linear-gradient(135deg, #ffc107 0%, #e0a800 100%);
  746. }
  747. .custom-modal-header.info {
  748.     background: linear-gradient(135deg, #17a2b8 0%, #138496 100%);
  749. }
  750. .custom-modal-title {
  751.     margin: 0;
  752.     font-size: 20px;
  753.     font-weight: 600;
  754.     color: white;
  755.     display: flex;
  756.     align-items: center;
  757.     gap: 10px;
  758. }
  759. .custom-modal-title::before {
  760.     content: '';
  761.     width: 24px;
  762.     height: 24px;
  763.     display: inline-block;
  764.     background-size: contain;
  765.     background-repeat: no-repeat;
  766.     background-position: center;
  767. }
  768. .custom-modal-title.success::before {
  769.     content: '✓';
  770.     font-size: 20px;
  771.     font-weight: bold;
  772. }
  773. .custom-modal-title.error::before {
  774.     content: '✕';
  775.     font-size: 20px;
  776.     font-weight: bold;
  777. }
  778. .custom-modal-title.warning::before {
  779.     content: '⚠';
  780.     font-size: 20px;
  781.     font-weight: bold;
  782. }
  783. .custom-modal-title.info::before {
  784.     content: 'ℹ';
  785.     font-size: 20px;
  786.     font-weight: bold;
  787. }
  788. .custom-modal-close {
  789.     background: rgba(255, 255, 255, 0.15);
  790.     border: 2px solid rgba(255, 255, 255, 0.3);
  791.     color: white;
  792.     font-size: 22px;
  793.     font-weight: 300;
  794.     line-height: 1;
  795.     width: 36px;
  796.     height: 36px;
  797.     border-radius: 50%;
  798.     cursor: pointer;
  799.     display: flex;
  800.     align-items: center;
  801.     justify-content: center;
  802.     transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  803.     padding: 0;
  804.     margin: 0;
  805.     position: relative;
  806.     overflow: hidden;
  807. }
  808. .custom-modal-close::before {
  809.     content: '';
  810.     position: absolute;
  811.     top: 50%;
  812.     left: 50%;
  813.     width: 0;
  814.     height: 0;
  815.     border-radius: 50%;
  816.     background: rgba(255, 255, 255, 0.2);
  817.     transform: translate(-50%, -50%);
  818.     transition: width 0.3s ease, height 0.3s ease;
  819. }
  820. .custom-modal-close:hover {
  821.     background: rgba(255, 255, 255, 0.25);
  822.     border-color: rgba(255, 255, 255, 0.5);
  823.     transform: rotate(90deg) scale(1.1);
  824.     box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  825. }
  826. .custom-modal-close:hover::before {
  827.     width: 100%;
  828.     height: 100%;
  829. }
  830. .custom-modal-close:active {
  831.     transform: rotate(90deg) scale(0.95);
  832.     background: rgba(255, 255, 255, 0.3);
  833. }
  834. .custom-modal-close span {
  835.     position: relative;
  836.     z-index: 1;
  837.     display: block;
  838.     line-height: 1;
  839. }
  840. .custom-modal-body {
  841.     padding: 24px;
  842.     font-size: 16px;
  843.     line-height: 1.6;
  844.     color: #333;
  845.     max-height: 60vh;
  846.     overflow-y: auto;
  847. }
  848. .custom-modal-body p {
  849.     margin: 0;
  850. }
  851. .custom-modal-footer {
  852.     display: flex;
  853.     gap: 12px;
  854.     justify-content: flex-end;
  855.     padding: 16px 24px;
  856.     border-top: 1px solid #e0e0e0;
  857.     background: #f8f9fa;
  858. }
  859. .custom-modal-footer.single-button {
  860.     justify-content: center;
  861. }
  862. .custom-modal-btn {
  863.     padding: 10px 24px;
  864.     border: none;
  865.     border-radius: 6px;
  866.     font-size: 15px;
  867.     font-weight: 500;
  868.     cursor: pointer;
  869.     transition: all 0.2s ease;
  870.     min-width: 100px;
  871. }
  872. .custom-modal-btn-primary {
  873.     background: #ffa200;
  874.     color: white;
  875. }
  876. .custom-modal-btn-primary:hover {
  877.     background: #e68900;
  878.     transform: translateY(-1px);
  879.     box-shadow: 0 4px 8px rgba(255, 162, 0, 0.3);
  880. }
  881. .custom-modal-btn-secondary {
  882.     background: #6c757d;
  883.     color: white;
  884. }
  885. .custom-modal-btn-secondary:hover {
  886.     background: #5a6268;
  887.     transform: translateY(-1px);
  888.     box-shadow: 0 4px 8px rgba(108, 117, 125, 0.3);
  889. }
  890. .custom-modal-btn-success {
  891.     background: #28a745;
  892.     color: white;
  893. }
  894. .custom-modal-btn-success:hover {
  895.     background: #218838;
  896.     transform: translateY(-1px);
  897.     box-shadow: 0 4px 8px rgba(40, 167, 69, 0.3);
  898. }
  899. .custom-modal-btn-danger {
  900.     background: #dc3545;
  901.     color: white;
  902. }
  903. .custom-modal-btn-danger:hover {
  904.     background: #c82333;
  905.     transform: translateY(-1px);
  906.     box-shadow: 0 4px 8px rgba(220, 53, 69, 0.3);
  907. }
  908. /* Animation pour les modals */
  909. @keyframes modalFadeIn {
  910.     from {
  911.         opacity: 0;
  912.     }
  913.     to {
  914.         opacity: 1;
  915.     }
  916. }
  917. @keyframes modalSlideIn {
  918.     from {
  919.         transform: scale(0.9) translateY(-20px);
  920.         opacity: 0;
  921.     }
  922.     to {
  923.         transform: scale(1) translateY(0);
  924.         opacity: 1;
  925.     }
  926. }
  927. .custom-modal.show .custom-modal-overlay {
  928.     animation: modalFadeIn 0.3s ease;
  929. }
  930. .custom-modal.show .custom-modal-content {
  931.     animation: modalSlideIn 0.3s ease;
  932. }
  933. /* Responsive */
  934. @media (max-width: 575.98px) {
  935.     .custom-modal-content {
  936.         width: 95%;
  937.         margin: 20px;
  938.     }
  939.     
  940.     .custom-modal-header {
  941.         padding: 16px 20px;
  942.     }
  943.     
  944.     .custom-modal-title {
  945.         font-size: 18px;
  946.     }
  947.     
  948.     .custom-modal-body {
  949.         padding: 20px;
  950.         font-size: 15px;
  951.     }
  952.     
  953.     .custom-modal-footer {
  954.         flex-direction: column;
  955.         padding: 16px 20px;
  956.     }
  957.     
  958.     .custom-modal-btn {
  959.         width: 100%;
  960.     }
  961. }
  962. </style>
  963. ";
  964.         
  965.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  966.         
  967.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  968.         yield from [];
  969.     }
  970.     // line 871
  971.     /**
  972.      * @return iterable<null|scalar|\Stringable>
  973.      */
  974.     public function block_javascripts(array $context, array $blocks = []): iterable
  975.     {
  976.         $macros $this->macros;
  977.         $__internal_5a27a8ba21ca79b61932376b2fa922d2 $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  978.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""javascripts"));
  979.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  980.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block""javascripts"));
  981.         // line 872
  982.         yield "<script>
  983. // Variables globales pour le modal
  984. let modalConfirmCallback = null;
  985. let modalCancelCallback = null;
  986. // Fonctions pour gérer le modal personnalisé
  987. function showCustomModal(options) {
  988.     const modal = document.getElementById('customModal');
  989.     const title = document.getElementById('modalTitle');
  990.     const message = document.getElementById('modalMessage');
  991.     const footer = document.getElementById('modalFooter');
  992.     const confirmBtn = document.getElementById('modalConfirmBtn');
  993.     const cancelBtn = document.getElementById('modalCancelBtn');
  994.     const header = modal.querySelector('.custom-modal-header');
  995.     
  996.     // Réinitialiser les classes
  997.     header.className = 'custom-modal-header';
  998.     title.className = 'custom-modal-title';
  999.     footer.className = 'custom-modal-footer';
  1000.     
  1001.     // Définir le titre et le message
  1002.     title.textContent = options.title || 'Information';
  1003.     message.textContent = options.message || '';
  1004.     
  1005.     // Définir le type (success, error, warning, info)
  1006.     const type = options.type || 'info';
  1007.     header.classList.add(type);
  1008.     title.classList.add(type);
  1009.     
  1010.     // Configurer les boutons
  1011.     if (options.showCancel !== false) {
  1012.         cancelBtn.style.display = 'block';
  1013.         footer.classList.remove('single-button');
  1014.     } else {
  1015.         cancelBtn.style.display = 'none';
  1016.         footer.classList.add('single-button');
  1017.     }
  1018.     
  1019.     // Configurer le bouton de confirmation
  1020.     if (options.confirmText) {
  1021.         confirmBtn.textContent = options.confirmText;
  1022.     }
  1023.     
  1024.     if (options.confirmClass) {
  1025.         confirmBtn.className = 'custom-modal-btn ' + options.confirmClass;
  1026.     } else {
  1027.         confirmBtn.className = 'custom-modal-btn custom-modal-btn-primary';
  1028.     }
  1029.     
  1030.     // Stocker les callbacks
  1031.     modalConfirmCallback = options.onConfirm || null;
  1032.     modalCancelCallback = options.onCancel || null;
  1033.     
  1034.     // Afficher le modal
  1035.     modal.classList.add('show');
  1036.     document.body.style.overflow = 'hidden';
  1037. }
  1038. function closeCustomModal() {
  1039.     const modal = document.getElementById('customModal');
  1040.     const cancelCallback = modalCancelCallback; // Sauvegarder avant réinitialisation
  1041.     
  1042.     modal.classList.remove('show');
  1043.     document.body.style.overflow = '';
  1044.     
  1045.     // Réinitialiser les callbacks
  1046.     modalConfirmCallback = null;
  1047.     modalCancelCallback = null;
  1048.     
  1049.     // Appeler le callback d'annulation si présent
  1050.     if (cancelCallback) {
  1051.         cancelCallback();
  1052.     }
  1053. }
  1054. function confirmModalAction() {
  1055.     if (modalConfirmCallback) {
  1056.         modalConfirmCallback();
  1057.     }
  1058.     closeCustomModal();
  1059. }
  1060. // Fermer le modal en cliquant sur l'overlay
  1061. document.addEventListener('DOMContentLoaded', function() {
  1062.     const modal = document.getElementById('customModal');
  1063.     const overlay = modal.querySelector('.custom-modal-overlay');
  1064.     
  1065.     overlay.addEventListener('click', function() {
  1066.         closeCustomModal();
  1067.     });
  1068.     
  1069.     // Fermer avec la touche Escape
  1070.     document.addEventListener('keydown', function(e) {
  1071.         if (e.key === 'Escape' && modal.classList.contains('show')) {
  1072.             closeCustomModal();
  1073.         }
  1074.     });
  1075. });
  1076. // Fonctions utilitaires pour différents types de modals
  1077. function showAlert(title, message, type = 'info') {
  1078.     showCustomModal({
  1079.         title: title,
  1080.         message: message,
  1081.         type: type,
  1082.         showCancel: false,
  1083.         confirmText: 'OK'
  1084.     });
  1085. }
  1086. function showConfirm(title, message, onConfirm, onCancel = null, type = 'warning') {
  1087.     showCustomModal({
  1088.         title: title,
  1089.         message: message,
  1090.         type: type,
  1091.         showCancel: true,
  1092.         confirmText: 'Confirmer',
  1093.         cancelText: 'Annuler',
  1094.         onConfirm: onConfirm,
  1095.         onCancel: onCancel
  1096.     });
  1097. }
  1098. function proceedToCheckout() {
  1099.     // Vérifier qu'il y a des articles dans le panier
  1100.     if (Object.keys(cartData).length === 0) {
  1101.         showCustomModal({
  1102.             title: 'Panier vide',
  1103.             message: 'Votre panier est vide. Veuillez ajouter des articles avant de procéder à la commande.',
  1104.             type: 'warning',
  1105.             showCancel: false,
  1106.             confirmText: 'OK',
  1107.             onConfirm: function() {
  1108.                 // Rediriger vers la page de listing pour encourager l'ajout d'articles
  1109.                 window.location.href = '";
  1110.         // line 1006
  1111.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_listing");
  1112.         yield "';
  1113.             }
  1114.         });
  1115.         return;
  1116.     }
  1117.     // Rediriger vers la page de checkout
  1118.     window.location.href = '";
  1119.         // line 1013
  1120.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_checkout");
  1121.         yield "';
  1122. }
  1123. function changeQuantity(productId, delta) {
  1124.     const qtyInput = document.getElementById('qty-' + productId);
  1125.     if (!qtyInput) return;
  1126.     
  1127.     const currentQty = parseInt(qtyInput.value) || 0;
  1128.     const newQty = Math.max(0, currentQty + delta);
  1129.     
  1130.     updateQuantity(productId, newQty);
  1131. }
  1132. function handleDecreaseOrRemove(productId) {
  1133.     const qtyInput = document.getElementById('qty-' + productId);
  1134.     if (!qtyInput) return;
  1135.     
  1136.     const currentQty = parseInt(qtyInput.value) || 0;
  1137.     
  1138.     if (currentQty === 1) {
  1139.         // Si la quantité est 1, supprimer le produit
  1140.         removeFromCart(productId);
  1141.     } else {
  1142.         // Sinon, diminuer la quantité
  1143.         changeQuantity(productId, -1);
  1144.     }
  1145. }
  1146. // Initialiser les données du panier
  1147. let cartData = {}; // Stocker les données du panier côté client
  1148. ";
  1149.         // line 1044
  1150.         $context['_parent'] = $context;
  1151.         $context['_seq'] = CoreExtension::ensureTraversable(($context["items"] ?? null));
  1152.         foreach ($context['_seq'] as $context["_key"] => $context["item"]) {
  1153.             // line 1045
  1154.             yield "    ";
  1155.             $context["image"] = (((CoreExtension::getAttribute($this->env$this->source$context["item"], "image", [], "any"truetruefalse1045) && CoreExtension::getAttribute($this->env$this->source$context["item"], "image", [], "any"falsefalsefalse1045))) ? (CoreExtension::getAttribute($this->env$this->source$context["item"], "image", [], "any"falsefalsefalse1045)) : ($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("ui/img/category/s-p1.jpg")));
  1156.             // line 1046
  1157.             yield "cartData[";
  1158.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env$this->source$context["item"], "id", [], "any"falsefalsefalse1046), "html"nulltrue);
  1159.             yield "] = {
  1160.     id: ";
  1161.             // line 1047
  1162.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env$this->source$context["item"], "id", [], "any"falsefalsefalse1047), "html"nulltrue);
  1163.             yield ",
  1164.     name: '";
  1165.             // line 1048
  1166.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env$this->source$context["item"], "name", [], "any"falsefalsefalse1048), "html"nulltrue);
  1167.             yield "',
  1168.     price: ";
  1169.             // line 1049
  1170.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env$this->source$context["item"], "price", [], "any"falsefalsefalse1049), "html"nulltrue);
  1171.             yield ",
  1172.     qty: ";
  1173.             // line 1050
  1174.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env$this->source$context["item"], "qty", [], "any"falsefalsefalse1050), "html"nulltrue);
  1175.             yield ",
  1176.     image: '";
  1177.             // line 1051
  1178.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(($context["image"] ?? null), "html"nulltrue);
  1179.             yield "',
  1180.     slug: '";
  1181.             // line 1052
  1182.             yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape(CoreExtension::getAttribute($this->env$this->source$context["item"], "slug", [], "any"falsefalsefalse1052), "html"nulltrue);
  1183.             yield "'
  1184. };
  1185. ";
  1186.         }
  1187.         $_parent $context['_parent'];
  1188.         unset($context['_seq'], $context['_key'], $context['item'], $context['_parent']);
  1189.         $context array_intersect_key($context$_parent) + $_parent;
  1190.         // line 1055
  1191.         yield "
  1192. function updateQuantity(productId, newQty) {
  1193.     const item = cartData[productId];
  1194.     
  1195.     if (!item) {
  1196.         console.error('Produit non trouvé:', productId);
  1197.         return;
  1198.     }
  1199.     
  1200.     // Validation de la quantité
  1201.     newQty = Math.max(0, parseInt(newQty) || 0);
  1202.     
  1203.     if (newQty === 0) {
  1204.         removeFromCart(productId);
  1205.         return;
  1206.     }
  1207.     
  1208.     if (newQty > 99) {
  1209.         showAlert('Quantité maximale', 'La quantité maximale est de 99 articles.', 'warning');
  1210.         return;
  1211.     }
  1212.     
  1213.     // Mettre à jour l'interface immédiatement (optimistic update)
  1214.     updateCartDisplay(productId, newQty);
  1215.     
  1216.     // Envoyer la requête au serveur
  1217.     fetch('";
  1218.         // line 1081
  1219.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_cart_update");
  1220.         yield "', {
  1221.         method: 'POST',
  1222.         headers: { 
  1223.             'Content-Type': 'application/x-www-form-urlencoded',
  1224.             'X-Requested-With': 'XMLHttpRequest'
  1225.         },
  1226.         body: 'productId=' + productId + '&qty=' + newQty
  1227.     })
  1228.     .then(response => {
  1229.         console.log('🔍 Réponse HTTP:', response.status, response.statusText);
  1230.         // Vérifier si la réponse est OK avant de parser
  1231.         if (!response.ok) {
  1232.             throw new Error('Erreur HTTP ' + response.status + ': ' + response.statusText);
  1233.         }
  1234.         return response.json();
  1235.     })
  1236.     .then(data => {
  1237.         console.log('📦 Données reçues:', data);
  1238.         if (data.ok) {
  1239.             // Les données serveur confirment la mise à jour
  1240.             // Mettre à jour le sous-total avec les valeurs exactes du serveur
  1241.             if (data.subtotal !== undefined) {
  1242.                 updateSubtotalDisplay(data);
  1243.                 updateCartBadge(data.totalQty || 0);
  1244.             }
  1245.             console.log('✅ Panier mis à jour avec succès - Sous-total:', data.subtotal, 'HTG');
  1246.         } else {
  1247.             // En cas d'erreur, restaurer la valeur précédente
  1248.             const oldQty = item.qty;
  1249.             updateCartDisplay(productId, oldQty);
  1250.             showAlert('Erreur', data.message || 'Erreur lors de la mise à jour du panier.', 'error');
  1251.         }
  1252.     })
  1253.     .catch(error => {
  1254.         console.error('❌ Erreur détaillée:', error);
  1255.         console.error('❌ Type d\\'erreur:', error.constructor.name);
  1256.         console.error('❌ Message d\\'erreur:', error.message);
  1257.         // Restaurer la valeur précédente en cas d'erreur
  1258.         const oldQty = item.qty;
  1259.         updateCartDisplay(productId, oldQty);
  1260.         // Afficher un message d'erreur plus détaillé
  1261.         let errorMessage = 'Une erreur de connexion est survenue. Veuillez réessayer.';
  1262.         if (error.message.includes('HTTP')) {
  1263.             errorMessage = 'Erreur du serveur: ' + error.message;
  1264.         } else if (error.message.includes('JSON')) {
  1265.             errorMessage = 'Erreur de traitement des données. Veuillez recharger la page.';
  1266.         }
  1267.         showAlert('Erreur de connexion', errorMessage, 'error');
  1268.     });
  1269. }
  1270. function updateCartDisplay(productId, qty) {
  1271.     const item = cartData[productId];
  1272.     if (!item) return;
  1273.     
  1274.     // Mettre à jour les données locales
  1275.     item.qty = qty;
  1276.     
  1277.     // Mettre à jour la quantité dans l'input
  1278.     const qtyInput = document.getElementById('qty-' + productId);
  1279.     if (qtyInput) {
  1280.         qtyInput.value = qty;
  1281.     }
  1282.     
  1283.     // Mettre à jour le bouton de diminution/suppression
  1284.     const decreaseBtn = document.getElementById('decrease-btn-' + productId);
  1285.     if (decreaseBtn) {
  1286.         if (qty === 1) {
  1287.             // Changer en bouton de suppression (poubelle)
  1288.             decreaseBtn.innerHTML = '<i class=\"lnr lnr-trash\"></i>';
  1289.             decreaseBtn.classList.add('quantity-btn-remove');
  1290.             decreaseBtn.classList.remove('quantity-btn-decrease');
  1291.         } else {
  1292.             // Changer en bouton de diminution (moins)
  1293.             decreaseBtn.innerHTML = '<span>−</span>';
  1294.             decreaseBtn.classList.add('quantity-btn-decrease');
  1295.             decreaseBtn.classList.remove('quantity-btn-remove');
  1296.         }
  1297.     }
  1298.     
  1299.     // Mettre à jour le total du produit
  1300.     const totalElement = document.getElementById('total-' + productId);
  1301.     if (totalElement) {
  1302.         const itemTotal = (item.price * qty);
  1303.         totalElement.textContent = itemTotal.toLocaleString('fr-FR', {
  1304.             minimumFractionDigits: 2,
  1305.             maximumFractionDigits: 2
  1306.         }) + ' HTG';
  1307.     }
  1308.     
  1309.     // Mettre à jour les totaux généraux
  1310.     updateCartSummary();
  1311. }
  1312. function updateCartTotals(data) {
  1313.     // Utiliser la fonction unifiée pour mettre à jour les totaux
  1314.     updateSubtotalDisplay(data);
  1315. }
  1316. function updateCartSummary() {
  1317.     // Calculer les totaux côté client depuis cartData
  1318.     let subtotal = 0;
  1319.     let totalItems = 0;
  1320.     Object.values(cartData).forEach(item => {
  1321.         subtotal += item.price * item.qty;
  1322.         totalItems += item.qty;
  1323.     });
  1324.     // Mettre à jour l'affichage du sous-total
  1325.     const subtotalElement = document.getElementById('cart-subtotal');
  1326.     if (subtotalElement) {
  1327.         subtotalElement.textContent = subtotal.toLocaleString('fr-FR', {
  1328.             minimumFractionDigits: 2,
  1329.             maximumFractionDigits: 2
  1330.         }) + ' HTG';
  1331.     }
  1332.     // Mettre à jour l'affichage du total
  1333.     const totalElement = document.getElementById('cart-total');
  1334.     if (totalElement) {
  1335.         totalElement.textContent = subtotal.toLocaleString('fr-FR', {
  1336.             minimumFractionDigits: 2,
  1337.             maximumFractionDigits: 2
  1338.         }) + ' HTG';
  1339.     }
  1340.     // Mettre à jour le compteur d'articles
  1341.     const itemCountElement = document.getElementById('cart-item-count');
  1342.     if (itemCountElement) {
  1343.         itemCountElement.textContent = totalItems;
  1344.     }
  1345.     // Mettre à jour le label du sous-total
  1346.     const subtotalLabel = document.getElementById('cart-subtotal-label');
  1347.     if (subtotalLabel) {
  1348.         const itemText = totalItems + ' article' + (totalItems > 1 ? 's' : '');
  1349.         subtotalLabel.innerHTML = 'Sous-total (<span id=\"cart-item-count\">' + totalItems + '</span> ' + (totalItems > 1 ? 'articles' : 'article') + ')';
  1350.     }
  1351.     // Mettre à jour l'état du bouton checkout
  1352.     updateCheckoutButtonState();
  1353. }
  1354. // Fonction pour mettre à jour l'état du bouton checkout
  1355. function updateCheckoutButtonState() {
  1356.     const checkoutBtn = document.querySelector('.checkout-btn');
  1357.     const isCartEmpty = Object.keys(cartData).length === 0;
  1358.     if (checkoutBtn) {
  1359.         if (isCartEmpty) {
  1360.             checkoutBtn.classList.add('disabled');
  1361.             checkoutBtn.title = 'Votre panier est vide';
  1362.         } else {
  1363.             checkoutBtn.classList.remove('disabled');
  1364.             checkoutBtn.title = 'Procéder à la commande';
  1365.         }
  1366.     }
  1367. }
  1368. // Fonction pour mettre à jour le badge du panier
  1369. function updateCartBadge(totalQty) {
  1370.     const cartBadge = document.querySelector('.cart-badge');
  1371.     if (cartBadge) {
  1372.         cartBadge.textContent = totalQty || 0;
  1373.         console.log('🛒 Badge du panier mis à jour:', totalQty);
  1374.         // Animation du badge si la quantité change
  1375.         if (totalQty > 0) {
  1376.             cartBadge.style.animation = 'none';
  1377.             cartBadge.offsetHeight; // Trigger reflow
  1378.             cartBadge.style.animation = 'bounce 0.5s ease';
  1379.         }
  1380.     }
  1381. }
  1382. // Fonction améliorée pour mettre à jour le sous-total avec débogage
  1383. function updateSubtotalDisplay(data = null) {
  1384.     // Si des données serveur sont fournies, les utiliser (priorité absolue)
  1385.     if (data && data.subtotal !== undefined) {
  1386.         console.log('🔄 Mise à jour sous-total avec données serveur:', data.subtotal, 'HTG');
  1387.         const subtotalElement = document.getElementById('cart-subtotal');
  1388.         const totalElement = document.getElementById('cart-total');
  1389.         const formattedSubtotal = parseFloat(data.subtotal).toLocaleString('fr-FR', {
  1390.             minimumFractionDigits: 2,
  1391.             maximumFractionDigits: 2
  1392.         }) + ' HTG';
  1393.         if (subtotalElement) {
  1394.             subtotalElement.textContent = formattedSubtotal;
  1395.         }
  1396.         if (totalElement) {
  1397.             totalElement.textContent = formattedSubtotal;
  1398.         }
  1399.         // Mettre à jour le compteur d'articles
  1400.         const itemCountElement = document.getElementById('cart-item-count');
  1401.         if (itemCountElement && data.totalQty !== undefined) {
  1402.             const totalItems = data.totalQty;
  1403.             console.log('🔢 Mise à jour compteur articles:', totalItems, 'articles au total');
  1404.             const itemText = totalItems + ' article' + (totalItems > 1 ? 's' : '');
  1405.             const subtotalLabel = document.getElementById('cart-subtotal-label');
  1406.             if (subtotalLabel) {
  1407.                 subtotalLabel.innerHTML = 'Sous-total (<span id=\"cart-item-count\">' + totalItems + '</span> ' + (totalItems > 1 ? 'articles' : 'article') + ')';
  1408.                 console.log('📊 Label mis à jour:', subtotalLabel.innerHTML);
  1409.             }
  1410.         }
  1411.         // Vérification de cohérence (debug)
  1412.         let clientSubtotal = 0;
  1413.         let clientTotalItems = 0;
  1414.         Object.values(cartData).forEach(item => {
  1415.             clientSubtotal += parseFloat(item.price) * parseInt(item.qty);
  1416.             clientTotalItems += parseInt(item.qty);
  1417.         });
  1418.         const serverSubtotal = parseFloat(data.subtotal);
  1419.         if (Math.abs(clientSubtotal - serverSubtotal) > 0.01) {
  1420.             console.warn('⚠️ Incohérence détectée:', {
  1421.                 client: clientSubtotal.toFixed(2),
  1422.                 server: serverSubtotal.toFixed(2),
  1423.                 difference: Math.abs(clientSubtotal - serverSubtotal).toFixed(2)
  1424.             });
  1425.         }
  1426.     } else {
  1427.         // Calcul de secours côté client (si pas de données serveur)
  1428.         console.log('🔄 Calcul sous-total côté client (secours)');
  1429.         let subtotal = 0;
  1430.         let totalItems = 0;
  1431.         Object.values(cartData).forEach(item => {
  1432.             subtotal += parseFloat(item.price) * parseInt(item.qty);
  1433.             totalItems += parseInt(item.qty);
  1434.         });
  1435.         const formattedSubtotal = subtotal.toLocaleString('fr-FR', {
  1436.             minimumFractionDigits: 2,
  1437.             maximumFractionDigits: 2
  1438.         }) + ' HTG';
  1439.         // Mettre à jour l'affichage du sous-total
  1440.         const subtotalElement = document.getElementById('cart-subtotal');
  1441.         if (subtotalElement) {
  1442.             subtotalElement.textContent = formattedSubtotal;
  1443.         }
  1444.         const totalElement = document.getElementById('cart-total');
  1445.         if (totalElement) {
  1446.             totalElement.textContent = formattedSubtotal;
  1447.         }
  1448.         // Mettre à jour le label du sous-total
  1449.         const subtotalLabel = document.getElementById('cart-subtotal-label');
  1450.         if (subtotalLabel) {
  1451.             const itemText = totalItems + ' article' + (totalItems > 1 ? 's' : '');
  1452.             subtotalLabel.innerHTML = 'Sous-total (<span id=\"cart-item-count\">' + totalItems + '</span> ' + (totalItems > 1 ? 'articles' : 'article') + ')';
  1453.         }
  1454.     }
  1455. }
  1456. function removeFromCart(productId) {
  1457.     const item = cartData[productId];
  1458.     const itemName = item ? item.name : 'cet article';
  1459.     
  1460.     showConfirm(
  1461.         'Supprimer l\\'article',
  1462.         `Êtes-vous sûr de vouloir supprimer \"\${itemName}\" de votre panier ?`,
  1463.         function() {
  1464.             // Mettre à jour l'interface immédiatement
  1465.             const row = document.querySelector(`tr:has(#qty-\${productId})`);
  1466.             if (row) {
  1467.                 row.style.opacity = '0.5';
  1468.                 row.style.pointerEvents = 'none';
  1469.             }
  1470.             
  1471.             performRemoveFromCart(productId, row);
  1472.         },
  1473.         null,
  1474.         'warning'
  1475.     );
  1476. }
  1477. function performRemoveFromCart(productId, row) {
  1478.     
  1479.     fetch('";
  1480.         // line 1377
  1481.         yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("ui_cart_remove");
  1482.         yield "', {
  1483.         method: 'POST',
  1484.         headers: { 
  1485.             'Content-Type': 'application/x-www-form-urlencoded',
  1486.             'X-Requested-With': 'XMLHttpRequest'
  1487.         },
  1488.         body: 'productId=' + productId
  1489.     })
  1490.     .then(response => response.json())
  1491.     .then(data => {
  1492.         if (data.ok) {
  1493.             // Supprimer des données locales
  1494.             delete cartData[productId];
  1495.             
  1496.             // Supprimer la ligne du DOM
  1497.             const row = document.querySelector(`tr:has(#qty-\${productId})`);
  1498.             if (row) {
  1499.                 row.remove();
  1500.             }
  1501.             
  1502.             // Mettre à jour les totaux
  1503.             updateCartTotals(data);
  1504.             
  1505.             // Mettre à jour le résumé du panier
  1506.             updateCartSummary();
  1507.             
  1508.             // Afficher un message de succès
  1509.             showAlert('Article supprimé', 'L\\'article a été supprimé de votre panier avec succès.', 'success');
  1510.             
  1511.             // Vérifier si le panier est vide
  1512.             if (Object.keys(cartData).length === 0) {
  1513.                 setTimeout(function() {
  1514.                     location.reload();
  1515.                 }, 1500);
  1516.             }
  1517.         } else {
  1518.             // Restaurer l'affichage en cas d'erreur
  1519.             if (row) {
  1520.                 row.style.opacity = '1';
  1521.                 row.style.pointerEvents = 'auto';
  1522.             }
  1523.             showAlert('Erreur', data.message || 'Erreur lors de la suppression de l\\'article.', 'error');
  1524.         }
  1525.     })
  1526.     .catch(error => {
  1527.         console.error('Erreur:', error);
  1528.         // Restaurer l'affichage en cas d'erreur réseau
  1529.         if (row) {
  1530.             row.style.opacity = '1';
  1531.             row.style.pointerEvents = 'auto';
  1532.         }
  1533.         showAlert('Erreur de connexion', 'Une erreur de connexion est survenue. Veuillez réessayer.', 'error');
  1534.     });
  1535. }
  1536. // Script pour forcer l'application des styles des boutons de quantité et initialiser l'état du bouton checkout
  1537. document.addEventListener('DOMContentLoaded', function() {
  1538.     // Initialiser l'état du bouton checkout
  1539.     updateCheckoutButtonState();
  1540.     const quantityControls = document.querySelectorAll('.quantity-controls');
  1541.     quantityControls.forEach(function(control) {
  1542.         if (control) {
  1543.             // Forcer les styles sur le conteneur
  1544.             control.style.display = 'flex';
  1545.             control.style.alignItems = 'center';
  1546.             control.style.justifyContent = 'center';
  1547.             control.style.border = '1px solid #ddd';
  1548.             control.style.borderRadius = '4px';
  1549.             control.style.width = '120px';
  1550.             control.style.height = '40px';
  1551.             control.style.position = 'relative';
  1552.             control.style.background = 'white';
  1553.             control.style.overflow = 'hidden';
  1554.             // Forcer les styles sur les boutons
  1555.             const buttons = control.querySelectorAll('.quantity-btn');
  1556.             buttons.forEach(function(btn, index) {
  1557.                 btn.style.background = '#f8f8f8';
  1558.                 btn.style.border = 'none';
  1559.                 btn.style.width = '35px';
  1560.                 btn.style.height = '100%';
  1561.                 btn.style.cursor = 'pointer';
  1562.                 btn.style.fontSize = '18px';
  1563.                 btn.style.fontWeight = '600';
  1564.                 btn.style.color = '#333';
  1565.                 btn.style.display = 'flex';
  1566.                 btn.style.alignItems = 'center';
  1567.                 btn.style.justifyContent = 'center';
  1568.                 btn.style.padding = '0';
  1569.                 btn.style.margin = '0';
  1570.                 btn.style.lineHeight = '1';
  1571.                 btn.style.position = 'relative';
  1572.                 btn.style.zIndex = '1';
  1573.                 // Ajouter les bordures entre les boutons
  1574.                 if (index === 0) {
  1575.                     btn.style.borderRight = '1px solid #ddd';
  1576.                 } else if (index === buttons.length - 1) {
  1577.                     btn.style.borderLeft = '1px solid #ddd';
  1578.                 }
  1579.             });
  1580.             // Forcer les styles sur l'input
  1581.             const input = control.querySelector('.quantity-input');
  1582.             if (input) {
  1583.                 input.style.border = 'none';
  1584.                 input.style.width = '50px';
  1585.                 input.style.height = '100%';
  1586.                 input.style.textAlign = 'center';
  1587.                 input.style.fontSize = '15px';
  1588.                 input.style.fontWeight = '500';
  1589.                 input.style.padding = '0';
  1590.                 input.style.margin = '0';
  1591.                 input.style.background = 'white';
  1592.                 input.style.color = '#333';
  1593.                 input.style.outline = 'none';
  1594.                 input.style.boxShadow = 'none';
  1595.                 input.style.position = 'relative';
  1596.                 input.style.zIndex = '1';
  1597.             }
  1598.         }
  1599.     });
  1600. });
  1601. </script>
  1602. ";
  1603.         
  1604.         $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  1605.         
  1606.         $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  1607.         yield from [];
  1608.     }
  1609.     /**
  1610.      * @codeCoverageIgnore
  1611.      */
  1612.     public function getTemplateName(): string
  1613.     {
  1614.         return "home/cart.html.twig";
  1615.     }
  1616.     /**
  1617.      * @codeCoverageIgnore
  1618.      */
  1619.     public function isTraitable(): bool
  1620.     {
  1621.         return false;
  1622.     }
  1623.     /**
  1624.      * @codeCoverageIgnore
  1625.      */
  1626.     public function getDebugInfo(): array
  1627.     {
  1628.         return array (  1641 => 1377,  1342 => 1081,  1314 => 1055,  1305 => 1052,  1301 => 1051,  1297 => 1050,  1293 => 1049,  1289 => 1048,  1285 => 1047,  1280 => 1046,  1277 => 1045,  1273 => 1044,  1239 => 1013,  1229 => 1006,  1093 => 872,  1080 => 871,  331 => 131,  318 => 130,  278 => 100,  272 => 97,  265 => 93,  259 => 92,  248 => 83,  238 => 79,  232 => 75,  230 => 74,  222 => 71,  214 => 68,  207 => 64,  199 => 63,  196 => 62,  192 => 60,  188 => 58,  186 => 57,  178 => 56,  171 => 52,  161 => 47,  153 => 45,  151 => 44,  146 => 41,  141 => 40,  111 => 13,  102 => 6,  89 => 5,  66 => 3,  43 => 1,);
  1629.     }
  1630.     public function getSourceContext(): Source
  1631.     {
  1632.         return new Source("{% extends 'base_home.html.twig' %}
  1633. {% block title %}Panier | MaketOu{% endblock %}
  1634. {% block body %}
  1635.     <!-- Start Banner Area -->
  1636.     <section class=\"banner-area organic-breadcrumb\">
  1637.         <div class=\"container\">
  1638.             <div class=\"breadcrumb-banner d-flex flex-wrap align-items-center justify-content-end\">
  1639.                 <div class=\"col-first\">
  1640.                     <h1>Panier</h1>
  1641.                     <nav class=\"d-flex align-items-center\">
  1642.                         <a href=\"{{ path('ui_home') }}\">Accueil<span class=\"lnr lnr-arrow-right\"></span></a>
  1643.                         <a href=\"javascript:void(0)\">Panier</a>
  1644.                     </nav>
  1645.                 </div>
  1646.             </div>
  1647.         </div>
  1648.     </section>
  1649.     <!-- End Banner Area -->
  1650.     <!--================Cart Area =================-->
  1651.     <section class=\"cart_area\">
  1652.         <div class=\"container\">
  1653.             <div class=\"row\">
  1654.                 <div class=\"col-lg-8\">
  1655.                     <div class=\"cart_inner\">
  1656.                         <div class=\"table-responsive\">
  1657.                             <table class=\"table\">
  1658.                                 <thead>
  1659.                                     <tr>
  1660.                                         <th scope=\"col\">Produit</th>
  1661.                                         <th scope=\"col\">Prix</th>
  1662.                                         <th scope=\"col\">Quantité</th>
  1663.                                         <th scope=\"col\">Total</th>
  1664.                                         <th scope=\"col\">Action</th>
  1665.                                     </tr>
  1666.                                 </thead>
  1667.                                 <tbody>
  1668.                                     {% for item in items %}
  1669.                                     <tr>
  1670.                                         <td data-label=\"Produit\">
  1671.                                             <div class=\"cart-item\">
  1672.                                                 {% set image = (item.image is defined and item.image|length > 0) ? item.image : asset('ui/img/category/s-p1.jpg') %}
  1673.                                                 <img src=\"{{ image }}\" alt=\"{{ item.name }}\" class=\"cart-item-image\">
  1674.                                                 <div class=\"cart-item-info\">
  1675.                                                     <a href=\"{{ path('ui_product_show', { slug: item.slug }) }}\" class=\"cart-item-name\">{{ item.name }}</a>
  1676.                                                 </div>
  1677.                                             </div>
  1678.                                         </td>
  1679.                                         <td data-label=\"Prix\">
  1680.                                             <span class=\"cart-item-price\">{{ item.price|number_format(2, '.', ' ') }} HTG</span>
  1681.                                         </td>
  1682.                                         <td data-label=\"Quantité\">
  1683.                                             <div class=\"quantity-controls\">
  1684.                                                 <button class=\"quantity-btn quantity-btn-decrease\" id=\"decrease-btn-{{ item.id }}\" data-product-id=\"{{ item.id }}\" onclick=\"handleDecreaseOrRemove({{ item.id }})\">
  1685.                                                     {% if item.qty == 1 %}
  1686.                                                         <i class=\"lnr lnr-trash\"></i>
  1687.                                                     {% else %}
  1688.                                                         <span>−</span>
  1689.                                                     {% endif %}
  1690.                                                 </button>
  1691.                                                 <input type=\"text\" value=\"{{ item.qty }}\" class=\"quantity-input\" id=\"qty-{{ item.id }}\" onchange=\"updateQuantity({{ item.id }}, this.value)\">
  1692.                                                 <button class=\"quantity-btn\" onclick=\"changeQuantity({{ item.id }}, 1)\">+</button>
  1693.                                             </div>
  1694.                                         </td>
  1695.                                         <td data-label=\"Total\">
  1696.                                             <span class=\"cart-item-total\" id=\"total-{{ item.id }}\">{{ (item.price * item.qty)|number_format(2, '.', ' ') }} HTG</span>
  1697.                                         </td>
  1698.                                         <td data-label=\"Action\">
  1699.                                             <button class=\"remove-btn\" onclick=\"removeFromCart({{ item.id }})\">Supprimer</button>
  1700.                                         </td>
  1701.                                     </tr>
  1702.                                     {% else %}
  1703.                                         <tr>
  1704.                                             <td colspan=\"5\" style=\"text-align: center; padding: 50px;\">
  1705.                                                 Votre panier est vide.
  1706.                                                 <br>
  1707.                                                 <a href=\"{{ path('ui_listing') }}\" style=\"color: #007185;\">Continuer vos achats</a>
  1708.                                             </td>
  1709.                                         </tr>
  1710.                                     {% endfor %}
  1711.                                 </tbody>
  1712.                             </table>
  1713.                         </div>
  1714.                     </div>
  1715.                 </div>
  1716.                 <div class=\"col-lg-4\">
  1717.                     <div class=\"cart-summary\">
  1718.                         <h3>Résumé de la commande</h3>
  1719.                         <div class=\"cart-subtotal\">
  1720.                             <span id=\"cart-subtotal-label\">Sous-total (<span id=\"cart-item-count\">{{ items|length }}</span> article{{ items|length > 1 ? 's' : '' }})</span>
  1721.                             <span id=\"cart-subtotal\">{{ subtotal|number_format(2, '.', ' ') }} HTG</span>
  1722.                         </div>
  1723.                         <div class=\"cart-total\">
  1724.                             <span>Total</span>
  1725.                             <span id=\"cart-total\">{{ subtotal|number_format(2, '.', ' ') }} HTG</span>
  1726.                         </div>
  1727.                         <button class=\"checkout-btn mt-3\" onclick=\"proceedToCheckout()\">Passer la commande</button>
  1728.                         <button class=\"continue-shopping\" onclick=\"window.location.href='{{ path('ui_listing') }}'\">Continuer vos achats</button>
  1729.                     </div>
  1730.                 </div>
  1731.             </div>
  1732.         </div>
  1733.     </section>
  1734.     <!--================End Cart Area =================-->
  1735.     <!-- Modal personnalisé -->
  1736.     <div id=\"customModal\" class=\"custom-modal\">
  1737.         <div class=\"custom-modal-overlay\"></div>
  1738.         <div class=\"custom-modal-content\">
  1739.             <div class=\"custom-modal-header\">
  1740.                 <h3 class=\"custom-modal-title\" id=\"modalTitle\">Titre</h3>
  1741.                 <button class=\"custom-modal-close\" onclick=\"closeCustomModal()\" aria-label=\"Fermer\">
  1742.                     <span>&times;</span>
  1743.                 </button>
  1744.             </div>
  1745.             <div class=\"custom-modal-body\" id=\"modalBody\">
  1746.                 <p id=\"modalMessage\">Message</p>
  1747.             </div>
  1748.             <div class=\"custom-modal-footer\" id=\"modalFooter\">
  1749.                 <button class=\"custom-modal-btn custom-modal-btn-primary\" id=\"modalConfirmBtn\" onclick=\"confirmModalAction()\">Confirmer</button>
  1750.                 <button class=\"custom-modal-btn custom-modal-btn-secondary\" id=\"modalCancelBtn\" onclick=\"closeCustomModal()\">Annuler</button>
  1751.             </div>
  1752.         </div>
  1753.     </div>
  1754. {% endblock %}
  1755. {% block stylesheets %}
  1756. <style>
  1757. .cart_area {
  1758.     background-color: #f8f8f8;
  1759.     padding: 20px 0;
  1760. }
  1761. .cart_inner {
  1762.     background: white;
  1763.     border-radius: 8px;
  1764.     box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  1765.     overflow: hidden;
  1766. }
  1767. .table th {
  1768.     background-color: #f3f3f3;
  1769.     border-bottom: 2px solid #ddd;
  1770.     font-weight: 600;
  1771.     color: #333;
  1772.     padding: 15px;
  1773. }
  1774. .table td {
  1775.     vertical-align: middle;
  1776.     padding: 15px;
  1777. }
  1778. .cart-item {
  1779.     display: flex;
  1780.     align-items: center;
  1781. }
  1782. .cart-item-image {
  1783.     width: 80px;
  1784.     height: 80px;
  1785.     object-fit: cover;
  1786.     border-radius: 8px;
  1787.     margin-right: 15px;
  1788. }
  1789. .cart-item-info {
  1790.     flex-grow: 1;
  1791. }
  1792. .cart-item-name {
  1793.     font-weight: 500;
  1794.     color: #007185;
  1795.     text-decoration: none;
  1796.     margin-bottom: 5px;
  1797. }
  1798. .cart-item-name:hover {
  1799.     text-decoration: underline;
  1800. }
  1801. .cart-item-price {
  1802.     color: #333;
  1803.     font-size: 18px;
  1804.     font-weight: 700;
  1805. }
  1806. .quantity-controls {
  1807.     display: flex !important;
  1808.     align-items: center !important;
  1809.     justify-content: center !important;
  1810.     border: 1px solid #ddd !important;
  1811.     border-radius: 4px !important;
  1812.     width: 120px !important;
  1813.     height: 40px !important;
  1814.     position: relative !important;
  1815.     background: white !important;
  1816.     overflow: hidden !important;
  1817. }
  1818. .quantity-controls .quantity-btn {
  1819.     background: #f8f8f8 !important;
  1820.     border: none !important;
  1821.     width: 35px !important;
  1822.     height: 100% !important;
  1823.     min-width: 35px !important;
  1824.     cursor: pointer !important;
  1825.     font-size: 18px !important;
  1826.     font-weight: 600 !important;
  1827.     color: #333 !important;
  1828.     display: flex !important;
  1829.     align-items: center !important;
  1830.     justify-content: center !important;
  1831.     padding: 0 !important;
  1832.     margin: 0 !important;
  1833.     line-height: 1 !important;
  1834.     transition: background-color 0.2s ease !important;
  1835.     position: relative !important;
  1836.     z-index: 1 !important;
  1837. }
  1838. .quantity-controls .quantity-btn:first-child {
  1839.     border-right: 1px solid #ddd !important;
  1840. }
  1841. .quantity-controls .quantity-btn:last-child {
  1842.     border-left: 1px solid #ddd !important;
  1843. }
  1844. .quantity-controls .quantity-btn:hover {
  1845.     background: #e7e7e7 !important;
  1846.     color: #000 !important;
  1847. }
  1848. .quantity-controls .quantity-btn:active {
  1849.     background: #d0d0d0 !important;
  1850. }
  1851. .quantity-controls .quantity-btn-remove {
  1852.     background: #f8f8f8 !important;
  1853.     color: #dc3545 !important;
  1854. }
  1855. .quantity-controls .quantity-btn-remove:hover {
  1856.     background: #dc3545 !important;
  1857.     color: white !important;
  1858. }
  1859. .quantity-controls .quantity-btn-remove i {
  1860.     font-size: 16px !important;
  1861. }
  1862. .quantity-controls .quantity-btn-decrease span {
  1863.     font-size: 24px !important;
  1864.     font-weight: 300 !important;
  1865.     line-height: 1 !important;
  1866. }
  1867. .quantity-controls .quantity-input {
  1868.     border: none !important;
  1869.     width: 50px !important;
  1870.     min-width: 50px !important;
  1871.     height: 100% !important;
  1872.     text-align: center !important;
  1873.     font-size: 15px !important;
  1874.     font-weight: 500 !important;
  1875.     padding: 0 !important;
  1876.     margin: 0 !important;
  1877.     background: white !important;
  1878.     color: #333 !important;
  1879.     outline: none !important;
  1880.     box-shadow: none !important;
  1881.     -moz-appearance: textfield !important;
  1882.     position: relative !important;
  1883.     z-index: 1 !important;
  1884. }
  1885. .quantity-controls .quantity-input::-webkit-outer-spin-button,
  1886. .quantity-controls .quantity-input::-webkit-inner-spin-button {
  1887.     -webkit-appearance: none !important;
  1888.     margin: 0 !important;
  1889. }
  1890. /* Surcharger les styles externes qui pourraient interférer */
  1891. .cart_inner .table tbody tr td .quantity-controls,
  1892. .cart_inner .table tbody tr td .quantity-controls .quantity-btn,
  1893. .cart_inner .table tbody tr td .quantity-controls .quantity-input {
  1894.     position: relative !important;
  1895. }
  1896. .cart_inner .table tbody tr td .quantity-controls .quantity-btn:before,
  1897. .cart_inner .table tbody tr td .quantity-controls .quantity-btn:after {
  1898.     display: none !important;
  1899.     content: none !important;
  1900. }
  1901. .cart-item-total {
  1902.     font-size: 18px;
  1903.     font-weight: 700;
  1904.     color: #333;
  1905. }
  1906. /* Animation pour le badge du panier */
  1907. @keyframes bounce {
  1908.     0%, 20%, 50%, 80%, 100% {
  1909.         transform: translateY(0);
  1910.     }
  1911.     40% {
  1912.         transform: translateY(-5px);
  1913.     }
  1914.     60% {
  1915.         transform: translateY(-3px);
  1916.     }
  1917. }
  1918. /* Responsive Styles */
  1919. @media (max-width: 991.98px) {
  1920.     .cart_area {
  1921.         padding: 15px 0;
  1922.     }
  1923.     
  1924.     .cart-summary {
  1925.         margin-top: 2rem;
  1926.     }
  1927. }
  1928. @media (max-width: 767.98px) {
  1929.     .cart_inner {
  1930.         border-radius: 0;
  1931.     }
  1932.     
  1933.     .table {
  1934.         font-size: 0.875rem;
  1935.     }
  1936.     
  1937.     .table th {
  1938.         padding: 10px 8px;
  1939.         font-size: 0.8rem;
  1940.     }
  1941.     
  1942.     .table td {
  1943.         padding: 10px 8px;
  1944.     }
  1945.     
  1946.     .cart-item {
  1947.         flex-direction: column;
  1948.         align-items: flex-start;
  1949.     }
  1950.     
  1951.     .cart-item-image {
  1952.         width: 60px;
  1953.         height: 60px;
  1954.         margin-right: 0;
  1955.         margin-bottom: 10px;
  1956.     }
  1957.     
  1958.     .cart-item-name {
  1959.         font-size: 0.9rem;
  1960.     }
  1961.     
  1962.     .cart-item-price,
  1963.     .cart-item-total {
  1964.         font-size: 1rem;
  1965.     }
  1966.     
  1967.     .quantity-controls {
  1968.         width: 110px !important;
  1969.         height: 38px !important;
  1970.     }
  1971.     
  1972.     .quantity-controls .quantity-btn {
  1973.         width: 32px !important;
  1974.         font-size: 16px !important;
  1975.     }
  1976.     
  1977.     .quantity-controls .quantity-input {
  1978.         width: 46px !important;
  1979.         font-size: 14px !important;
  1980.     }
  1981.     
  1982.     .cart-summary {
  1983.         margin-top: 1.5rem;
  1984.         padding: 1.5rem;
  1985.     }
  1986.     
  1987.     .checkout-btn,
  1988.     .continue-shopping {
  1989.         width: 100%;
  1990.         margin-bottom: 0.5rem;
  1991.     }
  1992. }
  1993. @media (max-width: 575.98px) {
  1994.     .table thead {
  1995.         display: none;
  1996.     }
  1997.     
  1998.     .table tbody tr {
  1999.         display: block;
  2000.         margin-bottom: 1rem;
  2001.         border: 1px solid #dee2e6;
  2002.         border-radius: 8px;
  2003.         padding: 1rem;
  2004.     }
  2005.     
  2006.     .table tbody td {
  2007.         display: flex;
  2008.         justify-content: space-between;
  2009.         align-items: center;
  2010.         padding: 0.5rem 0;
  2011.         border: none;
  2012.         text-align: right;
  2013.     }
  2014.     
  2015.     .table tbody td::before {
  2016.         content: attr(data-label);
  2017.         font-weight: bold;
  2018.         text-align: left;
  2019.         margin-right: 1rem;
  2020.     }
  2021.     
  2022.     .table tbody td:first-child {
  2023.         flex-direction: column;
  2024.         align-items: flex-start;
  2025.     }
  2026.     
  2027.     .cart-item-image {
  2028.         width: 100%;
  2029.         height: 200px;
  2030.         margin-bottom: 1rem;
  2031.     }
  2032.     
  2033.     .cart-item-name {
  2034.         font-size: 1rem;
  2035.         margin-bottom: 0.5rem;
  2036.     }
  2037.     
  2038.     .quantity-controls {
  2039.         width: 100% !important;
  2040.         max-width: 150px !important;
  2041.         margin: 0 auto !important;
  2042.         justify-content: center !important;
  2043.         height: 40px !important;
  2044.     }
  2045.     
  2046.     .quantity-controls .quantity-btn {
  2047.         width: 40px !important;
  2048.         font-size: 18px !important;
  2049.     }
  2050.     
  2051.     .quantity-controls .quantity-input {
  2052.         width: 60px !important;
  2053.         font-size: 16px !important;
  2054.     }
  2055.     
  2056.     .remove-btn {
  2057.         width: 100%;
  2058.         margin-top: 0.5rem;
  2059.     }
  2060. }
  2061. .remove-btn {
  2062.     background: #ff9900;
  2063.     color: white;
  2064.     border: none;
  2065.     padding: 8px 16px;
  2066.     border-radius: 4px;
  2067.     cursor: pointer;
  2068.     font-size: 12px;
  2069. }
  2070. .remove-btn:hover {
  2071.     background: #e68900;
  2072. }
  2073. .cart-summary {
  2074.     background: white;
  2075.     border-radius: 8px;
  2076.     box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  2077.     padding: 20px;
  2078.     height: fit-content;
  2079. }
  2080. .cart-subtotal {
  2081.     display: flex;
  2082.     justify-content: space-between;
  2083.     padding: 10px 0;
  2084.     border-bottom: 1px solid #ddd;
  2085.     margin-bottom: 15px;
  2086. }
  2087. .cart-total {
  2088.     font-size: 20px;
  2089.     font-weight: 700;
  2090.     color: #333;
  2091. }
  2092. .checkout-btn {
  2093.     background: #ffa200;
  2094.     color: white;
  2095.     border: none;
  2096.     padding: 12px 24px;
  2097.     border-radius: 4px;
  2098.     cursor: pointer;
  2099.     width: 100%;
  2100.     font-size: 16px;
  2101.     font-weight: 600;
  2102. }
  2103. .checkout-btn:hover {
  2104.     background: #e68900;
  2105. }
  2106. .checkout-btn:disabled,
  2107. .checkout-btn.disabled {
  2108.     background: #cccccc !important;
  2109.     color: #666666 !important;
  2110.     cursor: pointer !important; /* Garder le curseur pointer pour indiquer que c'est cliquable */
  2111.     opacity: 0.6;
  2112.     pointer-events: auto !important; /* S'assurer que le clic fonctionne */
  2113. }
  2114. .checkout-btn:disabled:hover,
  2115. .checkout-btn.disabled:hover {
  2116.     background: #cccccc !important;
  2117.     transform: none !important;
  2118.     box-shadow: none !important;
  2119. }
  2120. .continue-shopping {
  2121.     background: #095ad3;
  2122.     color: #ffffff;
  2123.     border: none;
  2124.     padding: 12px 24px;
  2125.     border-radius: 4px;
  2126.     cursor: pointer;
  2127.     width: 100%;
  2128.     font-size: 16px;
  2129.     font-weight: 600;
  2130.     margin-top: 10px;
  2131. }
  2132. .continue-shopping:hover {
  2133.     background: #e68900;
  2134.     color: #ffffff
  2135. }
  2136. /* ============================================
  2137.    MODAL PERSONNALISÉ
  2138.    ============================================ */
  2139. .custom-modal {
  2140.     display: none;
  2141.     position: fixed;
  2142.     top: 0;
  2143.     left: 0;
  2144.     width: 100%;
  2145.     height: 100%;
  2146.     z-index: 10000;
  2147.     opacity: 0;
  2148.     transition: opacity 0.3s ease;
  2149. }
  2150. .custom-modal.show {
  2151.     display: flex;
  2152.     align-items: center;
  2153.     justify-content: center;
  2154.     opacity: 1;
  2155. }
  2156. .custom-modal-overlay {
  2157.     position: absolute;
  2158.     top: 0;
  2159.     left: 0;
  2160.     width: 100%;
  2161.     height: 100%;
  2162.     background: rgba(0, 0, 0, 0.5);
  2163.     backdrop-filter: blur(4px);
  2164.     -webkit-backdrop-filter: blur(4px);
  2165. }
  2166. .custom-modal-content {
  2167.     position: relative;
  2168.     background: white;
  2169.     border-radius: 12px;
  2170.     box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
  2171.     max-width: 500px;
  2172.     width: 90%;
  2173.     max-height: 90vh;
  2174.     overflow: hidden;
  2175.     transform: scale(0.9) translateY(-20px);
  2176.     transition: transform 0.3s ease;
  2177.     z-index: 10001;
  2178. }
  2179. .custom-modal.show .custom-modal-content {
  2180.     transform: scale(1) translateY(0);
  2181. }
  2182. .custom-modal-header {
  2183.     display: flex;
  2184.     align-items: center;
  2185.     justify-content: space-between;
  2186.     padding: 20px 24px;
  2187.     border-bottom: 1px solid #e0e0e0;
  2188.     background: linear-gradient(135deg, #ffa200 0%, #ff9900 100%);
  2189. }
  2190. .custom-modal-header.error {
  2191.     background: linear-gradient(135deg, #dc3545 0%, #c82333 100%);
  2192. }
  2193. .custom-modal-header.success {
  2194.     background: linear-gradient(135deg, #28a745 0%, #218838 100%);
  2195. }
  2196. .custom-modal-header.warning {
  2197.     background: linear-gradient(135deg, #ffc107 0%, #e0a800 100%);
  2198. }
  2199. .custom-modal-header.info {
  2200.     background: linear-gradient(135deg, #17a2b8 0%, #138496 100%);
  2201. }
  2202. .custom-modal-title {
  2203.     margin: 0;
  2204.     font-size: 20px;
  2205.     font-weight: 600;
  2206.     color: white;
  2207.     display: flex;
  2208.     align-items: center;
  2209.     gap: 10px;
  2210. }
  2211. .custom-modal-title::before {
  2212.     content: '';
  2213.     width: 24px;
  2214.     height: 24px;
  2215.     display: inline-block;
  2216.     background-size: contain;
  2217.     background-repeat: no-repeat;
  2218.     background-position: center;
  2219. }
  2220. .custom-modal-title.success::before {
  2221.     content: '✓';
  2222.     font-size: 20px;
  2223.     font-weight: bold;
  2224. }
  2225. .custom-modal-title.error::before {
  2226.     content: '✕';
  2227.     font-size: 20px;
  2228.     font-weight: bold;
  2229. }
  2230. .custom-modal-title.warning::before {
  2231.     content: '⚠';
  2232.     font-size: 20px;
  2233.     font-weight: bold;
  2234. }
  2235. .custom-modal-title.info::before {
  2236.     content: 'ℹ';
  2237.     font-size: 20px;
  2238.     font-weight: bold;
  2239. }
  2240. .custom-modal-close {
  2241.     background: rgba(255, 255, 255, 0.15);
  2242.     border: 2px solid rgba(255, 255, 255, 0.3);
  2243.     color: white;
  2244.     font-size: 22px;
  2245.     font-weight: 300;
  2246.     line-height: 1;
  2247.     width: 36px;
  2248.     height: 36px;
  2249.     border-radius: 50%;
  2250.     cursor: pointer;
  2251.     display: flex;
  2252.     align-items: center;
  2253.     justify-content: center;
  2254.     transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  2255.     padding: 0;
  2256.     margin: 0;
  2257.     position: relative;
  2258.     overflow: hidden;
  2259. }
  2260. .custom-modal-close::before {
  2261.     content: '';
  2262.     position: absolute;
  2263.     top: 50%;
  2264.     left: 50%;
  2265.     width: 0;
  2266.     height: 0;
  2267.     border-radius: 50%;
  2268.     background: rgba(255, 255, 255, 0.2);
  2269.     transform: translate(-50%, -50%);
  2270.     transition: width 0.3s ease, height 0.3s ease;
  2271. }
  2272. .custom-modal-close:hover {
  2273.     background: rgba(255, 255, 255, 0.25);
  2274.     border-color: rgba(255, 255, 255, 0.5);
  2275.     transform: rotate(90deg) scale(1.1);
  2276.     box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  2277. }
  2278. .custom-modal-close:hover::before {
  2279.     width: 100%;
  2280.     height: 100%;
  2281. }
  2282. .custom-modal-close:active {
  2283.     transform: rotate(90deg) scale(0.95);
  2284.     background: rgba(255, 255, 255, 0.3);
  2285. }
  2286. .custom-modal-close span {
  2287.     position: relative;
  2288.     z-index: 1;
  2289.     display: block;
  2290.     line-height: 1;
  2291. }
  2292. .custom-modal-body {
  2293.     padding: 24px;
  2294.     font-size: 16px;
  2295.     line-height: 1.6;
  2296.     color: #333;
  2297.     max-height: 60vh;
  2298.     overflow-y: auto;
  2299. }
  2300. .custom-modal-body p {
  2301.     margin: 0;
  2302. }
  2303. .custom-modal-footer {
  2304.     display: flex;
  2305.     gap: 12px;
  2306.     justify-content: flex-end;
  2307.     padding: 16px 24px;
  2308.     border-top: 1px solid #e0e0e0;
  2309.     background: #f8f9fa;
  2310. }
  2311. .custom-modal-footer.single-button {
  2312.     justify-content: center;
  2313. }
  2314. .custom-modal-btn {
  2315.     padding: 10px 24px;
  2316.     border: none;
  2317.     border-radius: 6px;
  2318.     font-size: 15px;
  2319.     font-weight: 500;
  2320.     cursor: pointer;
  2321.     transition: all 0.2s ease;
  2322.     min-width: 100px;
  2323. }
  2324. .custom-modal-btn-primary {
  2325.     background: #ffa200;
  2326.     color: white;
  2327. }
  2328. .custom-modal-btn-primary:hover {
  2329.     background: #e68900;
  2330.     transform: translateY(-1px);
  2331.     box-shadow: 0 4px 8px rgba(255, 162, 0, 0.3);
  2332. }
  2333. .custom-modal-btn-secondary {
  2334.     background: #6c757d;
  2335.     color: white;
  2336. }
  2337. .custom-modal-btn-secondary:hover {
  2338.     background: #5a6268;
  2339.     transform: translateY(-1px);
  2340.     box-shadow: 0 4px 8px rgba(108, 117, 125, 0.3);
  2341. }
  2342. .custom-modal-btn-success {
  2343.     background: #28a745;
  2344.     color: white;
  2345. }
  2346. .custom-modal-btn-success:hover {
  2347.     background: #218838;
  2348.     transform: translateY(-1px);
  2349.     box-shadow: 0 4px 8px rgba(40, 167, 69, 0.3);
  2350. }
  2351. .custom-modal-btn-danger {
  2352.     background: #dc3545;
  2353.     color: white;
  2354. }
  2355. .custom-modal-btn-danger:hover {
  2356.     background: #c82333;
  2357.     transform: translateY(-1px);
  2358.     box-shadow: 0 4px 8px rgba(220, 53, 69, 0.3);
  2359. }
  2360. /* Animation pour les modals */
  2361. @keyframes modalFadeIn {
  2362.     from {
  2363.         opacity: 0;
  2364.     }
  2365.     to {
  2366.         opacity: 1;
  2367.     }
  2368. }
  2369. @keyframes modalSlideIn {
  2370.     from {
  2371.         transform: scale(0.9) translateY(-20px);
  2372.         opacity: 0;
  2373.     }
  2374.     to {
  2375.         transform: scale(1) translateY(0);
  2376.         opacity: 1;
  2377.     }
  2378. }
  2379. .custom-modal.show .custom-modal-overlay {
  2380.     animation: modalFadeIn 0.3s ease;
  2381. }
  2382. .custom-modal.show .custom-modal-content {
  2383.     animation: modalSlideIn 0.3s ease;
  2384. }
  2385. /* Responsive */
  2386. @media (max-width: 575.98px) {
  2387.     .custom-modal-content {
  2388.         width: 95%;
  2389.         margin: 20px;
  2390.     }
  2391.     
  2392.     .custom-modal-header {
  2393.         padding: 16px 20px;
  2394.     }
  2395.     
  2396.     .custom-modal-title {
  2397.         font-size: 18px;
  2398.     }
  2399.     
  2400.     .custom-modal-body {
  2401.         padding: 20px;
  2402.         font-size: 15px;
  2403.     }
  2404.     
  2405.     .custom-modal-footer {
  2406.         flex-direction: column;
  2407.         padding: 16px 20px;
  2408.     }
  2409.     
  2410.     .custom-modal-btn {
  2411.         width: 100%;
  2412.     }
  2413. }
  2414. </style>
  2415. {% endblock %}
  2416. {% block javascripts %}
  2417. <script>
  2418. // Variables globales pour le modal
  2419. let modalConfirmCallback = null;
  2420. let modalCancelCallback = null;
  2421. // Fonctions pour gérer le modal personnalisé
  2422. function showCustomModal(options) {
  2423.     const modal = document.getElementById('customModal');
  2424.     const title = document.getElementById('modalTitle');
  2425.     const message = document.getElementById('modalMessage');
  2426.     const footer = document.getElementById('modalFooter');
  2427.     const confirmBtn = document.getElementById('modalConfirmBtn');
  2428.     const cancelBtn = document.getElementById('modalCancelBtn');
  2429.     const header = modal.querySelector('.custom-modal-header');
  2430.     
  2431.     // Réinitialiser les classes
  2432.     header.className = 'custom-modal-header';
  2433.     title.className = 'custom-modal-title';
  2434.     footer.className = 'custom-modal-footer';
  2435.     
  2436.     // Définir le titre et le message
  2437.     title.textContent = options.title || 'Information';
  2438.     message.textContent = options.message || '';
  2439.     
  2440.     // Définir le type (success, error, warning, info)
  2441.     const type = options.type || 'info';
  2442.     header.classList.add(type);
  2443.     title.classList.add(type);
  2444.     
  2445.     // Configurer les boutons
  2446.     if (options.showCancel !== false) {
  2447.         cancelBtn.style.display = 'block';
  2448.         footer.classList.remove('single-button');
  2449.     } else {
  2450.         cancelBtn.style.display = 'none';
  2451.         footer.classList.add('single-button');
  2452.     }
  2453.     
  2454.     // Configurer le bouton de confirmation
  2455.     if (options.confirmText) {
  2456.         confirmBtn.textContent = options.confirmText;
  2457.     }
  2458.     
  2459.     if (options.confirmClass) {
  2460.         confirmBtn.className = 'custom-modal-btn ' + options.confirmClass;
  2461.     } else {
  2462.         confirmBtn.className = 'custom-modal-btn custom-modal-btn-primary';
  2463.     }
  2464.     
  2465.     // Stocker les callbacks
  2466.     modalConfirmCallback = options.onConfirm || null;
  2467.     modalCancelCallback = options.onCancel || null;
  2468.     
  2469.     // Afficher le modal
  2470.     modal.classList.add('show');
  2471.     document.body.style.overflow = 'hidden';
  2472. }
  2473. function closeCustomModal() {
  2474.     const modal = document.getElementById('customModal');
  2475.     const cancelCallback = modalCancelCallback; // Sauvegarder avant réinitialisation
  2476.     
  2477.     modal.classList.remove('show');
  2478.     document.body.style.overflow = '';
  2479.     
  2480.     // Réinitialiser les callbacks
  2481.     modalConfirmCallback = null;
  2482.     modalCancelCallback = null;
  2483.     
  2484.     // Appeler le callback d'annulation si présent
  2485.     if (cancelCallback) {
  2486.         cancelCallback();
  2487.     }
  2488. }
  2489. function confirmModalAction() {
  2490.     if (modalConfirmCallback) {
  2491.         modalConfirmCallback();
  2492.     }
  2493.     closeCustomModal();
  2494. }
  2495. // Fermer le modal en cliquant sur l'overlay
  2496. document.addEventListener('DOMContentLoaded', function() {
  2497.     const modal = document.getElementById('customModal');
  2498.     const overlay = modal.querySelector('.custom-modal-overlay');
  2499.     
  2500.     overlay.addEventListener('click', function() {
  2501.         closeCustomModal();
  2502.     });
  2503.     
  2504.     // Fermer avec la touche Escape
  2505.     document.addEventListener('keydown', function(e) {
  2506.         if (e.key === 'Escape' && modal.classList.contains('show')) {
  2507.             closeCustomModal();
  2508.         }
  2509.     });
  2510. });
  2511. // Fonctions utilitaires pour différents types de modals
  2512. function showAlert(title, message, type = 'info') {
  2513.     showCustomModal({
  2514.         title: title,
  2515.         message: message,
  2516.         type: type,
  2517.         showCancel: false,
  2518.         confirmText: 'OK'
  2519.     });
  2520. }
  2521. function showConfirm(title, message, onConfirm, onCancel = null, type = 'warning') {
  2522.     showCustomModal({
  2523.         title: title,
  2524.         message: message,
  2525.         type: type,
  2526.         showCancel: true,
  2527.         confirmText: 'Confirmer',
  2528.         cancelText: 'Annuler',
  2529.         onConfirm: onConfirm,
  2530.         onCancel: onCancel
  2531.     });
  2532. }
  2533. function proceedToCheckout() {
  2534.     // Vérifier qu'il y a des articles dans le panier
  2535.     if (Object.keys(cartData).length === 0) {
  2536.         showCustomModal({
  2537.             title: 'Panier vide',
  2538.             message: 'Votre panier est vide. Veuillez ajouter des articles avant de procéder à la commande.',
  2539.             type: 'warning',
  2540.             showCancel: false,
  2541.             confirmText: 'OK',
  2542.             onConfirm: function() {
  2543.                 // Rediriger vers la page de listing pour encourager l'ajout d'articles
  2544.                 window.location.href = '{{ path('ui_listing') }}';
  2545.             }
  2546.         });
  2547.         return;
  2548.     }
  2549.     // Rediriger vers la page de checkout
  2550.     window.location.href = '{{ path('ui_checkout') }}';
  2551. }
  2552. function changeQuantity(productId, delta) {
  2553.     const qtyInput = document.getElementById('qty-' + productId);
  2554.     if (!qtyInput) return;
  2555.     
  2556.     const currentQty = parseInt(qtyInput.value) || 0;
  2557.     const newQty = Math.max(0, currentQty + delta);
  2558.     
  2559.     updateQuantity(productId, newQty);
  2560. }
  2561. function handleDecreaseOrRemove(productId) {
  2562.     const qtyInput = document.getElementById('qty-' + productId);
  2563.     if (!qtyInput) return;
  2564.     
  2565.     const currentQty = parseInt(qtyInput.value) || 0;
  2566.     
  2567.     if (currentQty === 1) {
  2568.         // Si la quantité est 1, supprimer le produit
  2569.         removeFromCart(productId);
  2570.     } else {
  2571.         // Sinon, diminuer la quantité
  2572.         changeQuantity(productId, -1);
  2573.     }
  2574. }
  2575. // Initialiser les données du panier
  2576. let cartData = {}; // Stocker les données du panier côté client
  2577. {% for item in items %}
  2578.     {% set image = (item.image is defined and item.image) ? item.image : asset('ui/img/category/s-p1.jpg') %}
  2579. cartData[{{ item.id }}] = {
  2580.     id: {{ item.id }},
  2581.     name: '{{ item.name }}',
  2582.     price: {{ item.price }},
  2583.     qty: {{ item.qty }},
  2584.     image: '{{ image }}',
  2585.     slug: '{{ item.slug }}'
  2586. };
  2587. {% endfor %}
  2588. function updateQuantity(productId, newQty) {
  2589.     const item = cartData[productId];
  2590.     
  2591.     if (!item) {
  2592.         console.error('Produit non trouvé:', productId);
  2593.         return;
  2594.     }
  2595.     
  2596.     // Validation de la quantité
  2597.     newQty = Math.max(0, parseInt(newQty) || 0);
  2598.     
  2599.     if (newQty === 0) {
  2600.         removeFromCart(productId);
  2601.         return;
  2602.     }
  2603.     
  2604.     if (newQty > 99) {
  2605.         showAlert('Quantité maximale', 'La quantité maximale est de 99 articles.', 'warning');
  2606.         return;
  2607.     }
  2608.     
  2609.     // Mettre à jour l'interface immédiatement (optimistic update)
  2610.     updateCartDisplay(productId, newQty);
  2611.     
  2612.     // Envoyer la requête au serveur
  2613.     fetch('{{ path(\"ui_cart_update\") }}', {
  2614.         method: 'POST',
  2615.         headers: { 
  2616.             'Content-Type': 'application/x-www-form-urlencoded',
  2617.             'X-Requested-With': 'XMLHttpRequest'
  2618.         },
  2619.         body: 'productId=' + productId + '&qty=' + newQty
  2620.     })
  2621.     .then(response => {
  2622.         console.log('🔍 Réponse HTTP:', response.status, response.statusText);
  2623.         // Vérifier si la réponse est OK avant de parser
  2624.         if (!response.ok) {
  2625.             throw new Error('Erreur HTTP ' + response.status + ': ' + response.statusText);
  2626.         }
  2627.         return response.json();
  2628.     })
  2629.     .then(data => {
  2630.         console.log('📦 Données reçues:', data);
  2631.         if (data.ok) {
  2632.             // Les données serveur confirment la mise à jour
  2633.             // Mettre à jour le sous-total avec les valeurs exactes du serveur
  2634.             if (data.subtotal !== undefined) {
  2635.                 updateSubtotalDisplay(data);
  2636.                 updateCartBadge(data.totalQty || 0);
  2637.             }
  2638.             console.log('✅ Panier mis à jour avec succès - Sous-total:', data.subtotal, 'HTG');
  2639.         } else {
  2640.             // En cas d'erreur, restaurer la valeur précédente
  2641.             const oldQty = item.qty;
  2642.             updateCartDisplay(productId, oldQty);
  2643.             showAlert('Erreur', data.message || 'Erreur lors de la mise à jour du panier.', 'error');
  2644.         }
  2645.     })
  2646.     .catch(error => {
  2647.         console.error('❌ Erreur détaillée:', error);
  2648.         console.error('❌ Type d\\'erreur:', error.constructor.name);
  2649.         console.error('❌ Message d\\'erreur:', error.message);
  2650.         // Restaurer la valeur précédente en cas d'erreur
  2651.         const oldQty = item.qty;
  2652.         updateCartDisplay(productId, oldQty);
  2653.         // Afficher un message d'erreur plus détaillé
  2654.         let errorMessage = 'Une erreur de connexion est survenue. Veuillez réessayer.';
  2655.         if (error.message.includes('HTTP')) {
  2656.             errorMessage = 'Erreur du serveur: ' + error.message;
  2657.         } else if (error.message.includes('JSON')) {
  2658.             errorMessage = 'Erreur de traitement des données. Veuillez recharger la page.';
  2659.         }
  2660.         showAlert('Erreur de connexion', errorMessage, 'error');
  2661.     });
  2662. }
  2663. function updateCartDisplay(productId, qty) {
  2664.     const item = cartData[productId];
  2665.     if (!item) return;
  2666.     
  2667.     // Mettre à jour les données locales
  2668.     item.qty = qty;
  2669.     
  2670.     // Mettre à jour la quantité dans l'input
  2671.     const qtyInput = document.getElementById('qty-' + productId);
  2672.     if (qtyInput) {
  2673.         qtyInput.value = qty;
  2674.     }
  2675.     
  2676.     // Mettre à jour le bouton de diminution/suppression
  2677.     const decreaseBtn = document.getElementById('decrease-btn-' + productId);
  2678.     if (decreaseBtn) {
  2679.         if (qty === 1) {
  2680.             // Changer en bouton de suppression (poubelle)
  2681.             decreaseBtn.innerHTML = '<i class=\"lnr lnr-trash\"></i>';
  2682.             decreaseBtn.classList.add('quantity-btn-remove');
  2683.             decreaseBtn.classList.remove('quantity-btn-decrease');
  2684.         } else {
  2685.             // Changer en bouton de diminution (moins)
  2686.             decreaseBtn.innerHTML = '<span>−</span>';
  2687.             decreaseBtn.classList.add('quantity-btn-decrease');
  2688.             decreaseBtn.classList.remove('quantity-btn-remove');
  2689.         }
  2690.     }
  2691.     
  2692.     // Mettre à jour le total du produit
  2693.     const totalElement = document.getElementById('total-' + productId);
  2694.     if (totalElement) {
  2695.         const itemTotal = (item.price * qty);
  2696.         totalElement.textContent = itemTotal.toLocaleString('fr-FR', {
  2697.             minimumFractionDigits: 2,
  2698.             maximumFractionDigits: 2
  2699.         }) + ' HTG';
  2700.     }
  2701.     
  2702.     // Mettre à jour les totaux généraux
  2703.     updateCartSummary();
  2704. }
  2705. function updateCartTotals(data) {
  2706.     // Utiliser la fonction unifiée pour mettre à jour les totaux
  2707.     updateSubtotalDisplay(data);
  2708. }
  2709. function updateCartSummary() {
  2710.     // Calculer les totaux côté client depuis cartData
  2711.     let subtotal = 0;
  2712.     let totalItems = 0;
  2713.     Object.values(cartData).forEach(item => {
  2714.         subtotal += item.price * item.qty;
  2715.         totalItems += item.qty;
  2716.     });
  2717.     // Mettre à jour l'affichage du sous-total
  2718.     const subtotalElement = document.getElementById('cart-subtotal');
  2719.     if (subtotalElement) {
  2720.         subtotalElement.textContent = subtotal.toLocaleString('fr-FR', {
  2721.             minimumFractionDigits: 2,
  2722.             maximumFractionDigits: 2
  2723.         }) + ' HTG';
  2724.     }
  2725.     // Mettre à jour l'affichage du total
  2726.     const totalElement = document.getElementById('cart-total');
  2727.     if (totalElement) {
  2728.         totalElement.textContent = subtotal.toLocaleString('fr-FR', {
  2729.             minimumFractionDigits: 2,
  2730.             maximumFractionDigits: 2
  2731.         }) + ' HTG';
  2732.     }
  2733.     // Mettre à jour le compteur d'articles
  2734.     const itemCountElement = document.getElementById('cart-item-count');
  2735.     if (itemCountElement) {
  2736.         itemCountElement.textContent = totalItems;
  2737.     }
  2738.     // Mettre à jour le label du sous-total
  2739.     const subtotalLabel = document.getElementById('cart-subtotal-label');
  2740.     if (subtotalLabel) {
  2741.         const itemText = totalItems + ' article' + (totalItems > 1 ? 's' : '');
  2742.         subtotalLabel.innerHTML = 'Sous-total (<span id=\"cart-item-count\">' + totalItems + '</span> ' + (totalItems > 1 ? 'articles' : 'article') + ')';
  2743.     }
  2744.     // Mettre à jour l'état du bouton checkout
  2745.     updateCheckoutButtonState();
  2746. }
  2747. // Fonction pour mettre à jour l'état du bouton checkout
  2748. function updateCheckoutButtonState() {
  2749.     const checkoutBtn = document.querySelector('.checkout-btn');
  2750.     const isCartEmpty = Object.keys(cartData).length === 0;
  2751.     if (checkoutBtn) {
  2752.         if (isCartEmpty) {
  2753.             checkoutBtn.classList.add('disabled');
  2754.             checkoutBtn.title = 'Votre panier est vide';
  2755.         } else {
  2756.             checkoutBtn.classList.remove('disabled');
  2757.             checkoutBtn.title = 'Procéder à la commande';
  2758.         }
  2759.     }
  2760. }
  2761. // Fonction pour mettre à jour le badge du panier
  2762. function updateCartBadge(totalQty) {
  2763.     const cartBadge = document.querySelector('.cart-badge');
  2764.     if (cartBadge) {
  2765.         cartBadge.textContent = totalQty || 0;
  2766.         console.log('🛒 Badge du panier mis à jour:', totalQty);
  2767.         // Animation du badge si la quantité change
  2768.         if (totalQty > 0) {
  2769.             cartBadge.style.animation = 'none';
  2770.             cartBadge.offsetHeight; // Trigger reflow
  2771.             cartBadge.style.animation = 'bounce 0.5s ease';
  2772.         }
  2773.     }
  2774. }
  2775. // Fonction améliorée pour mettre à jour le sous-total avec débogage
  2776. function updateSubtotalDisplay(data = null) {
  2777.     // Si des données serveur sont fournies, les utiliser (priorité absolue)
  2778.     if (data && data.subtotal !== undefined) {
  2779.         console.log('🔄 Mise à jour sous-total avec données serveur:', data.subtotal, 'HTG');
  2780.         const subtotalElement = document.getElementById('cart-subtotal');
  2781.         const totalElement = document.getElementById('cart-total');
  2782.         const formattedSubtotal = parseFloat(data.subtotal).toLocaleString('fr-FR', {
  2783.             minimumFractionDigits: 2,
  2784.             maximumFractionDigits: 2
  2785.         }) + ' HTG';
  2786.         if (subtotalElement) {
  2787.             subtotalElement.textContent = formattedSubtotal;
  2788.         }
  2789.         if (totalElement) {
  2790.             totalElement.textContent = formattedSubtotal;
  2791.         }
  2792.         // Mettre à jour le compteur d'articles
  2793.         const itemCountElement = document.getElementById('cart-item-count');
  2794.         if (itemCountElement && data.totalQty !== undefined) {
  2795.             const totalItems = data.totalQty;
  2796.             console.log('🔢 Mise à jour compteur articles:', totalItems, 'articles au total');
  2797.             const itemText = totalItems + ' article' + (totalItems > 1 ? 's' : '');
  2798.             const subtotalLabel = document.getElementById('cart-subtotal-label');
  2799.             if (subtotalLabel) {
  2800.                 subtotalLabel.innerHTML = 'Sous-total (<span id=\"cart-item-count\">' + totalItems + '</span> ' + (totalItems > 1 ? 'articles' : 'article') + ')';
  2801.                 console.log('📊 Label mis à jour:', subtotalLabel.innerHTML);
  2802.             }
  2803.         }
  2804.         // Vérification de cohérence (debug)
  2805.         let clientSubtotal = 0;
  2806.         let clientTotalItems = 0;
  2807.         Object.values(cartData).forEach(item => {
  2808.             clientSubtotal += parseFloat(item.price) * parseInt(item.qty);
  2809.             clientTotalItems += parseInt(item.qty);
  2810.         });
  2811.         const serverSubtotal = parseFloat(data.subtotal);
  2812.         if (Math.abs(clientSubtotal - serverSubtotal) > 0.01) {
  2813.             console.warn('⚠️ Incohérence détectée:', {
  2814.                 client: clientSubtotal.toFixed(2),
  2815.                 server: serverSubtotal.toFixed(2),
  2816.                 difference: Math.abs(clientSubtotal - serverSubtotal).toFixed(2)
  2817.             });
  2818.         }
  2819.     } else {
  2820.         // Calcul de secours côté client (si pas de données serveur)
  2821.         console.log('🔄 Calcul sous-total côté client (secours)');
  2822.         let subtotal = 0;
  2823.         let totalItems = 0;
  2824.         Object.values(cartData).forEach(item => {
  2825.             subtotal += parseFloat(item.price) * parseInt(item.qty);
  2826.             totalItems += parseInt(item.qty);
  2827.         });
  2828.         const formattedSubtotal = subtotal.toLocaleString('fr-FR', {
  2829.             minimumFractionDigits: 2,
  2830.             maximumFractionDigits: 2
  2831.         }) + ' HTG';
  2832.         // Mettre à jour l'affichage du sous-total
  2833.         const subtotalElement = document.getElementById('cart-subtotal');
  2834.         if (subtotalElement) {
  2835.             subtotalElement.textContent = formattedSubtotal;
  2836.         }
  2837.         const totalElement = document.getElementById('cart-total');
  2838.         if (totalElement) {
  2839.             totalElement.textContent = formattedSubtotal;
  2840.         }
  2841.         // Mettre à jour le label du sous-total
  2842.         const subtotalLabel = document.getElementById('cart-subtotal-label');
  2843.         if (subtotalLabel) {
  2844.             const itemText = totalItems + ' article' + (totalItems > 1 ? 's' : '');
  2845.             subtotalLabel.innerHTML = 'Sous-total (<span id=\"cart-item-count\">' + totalItems + '</span> ' + (totalItems > 1 ? 'articles' : 'article') + ')';
  2846.         }
  2847.     }
  2848. }
  2849. function removeFromCart(productId) {
  2850.     const item = cartData[productId];
  2851.     const itemName = item ? item.name : 'cet article';
  2852.     
  2853.     showConfirm(
  2854.         'Supprimer l\\'article',
  2855.         `Êtes-vous sûr de vouloir supprimer \"\${itemName}\" de votre panier ?`,
  2856.         function() {
  2857.             // Mettre à jour l'interface immédiatement
  2858.             const row = document.querySelector(`tr:has(#qty-\${productId})`);
  2859.             if (row) {
  2860.                 row.style.opacity = '0.5';
  2861.                 row.style.pointerEvents = 'none';
  2862.             }
  2863.             
  2864.             performRemoveFromCart(productId, row);
  2865.         },
  2866.         null,
  2867.         'warning'
  2868.     );
  2869. }
  2870. function performRemoveFromCart(productId, row) {
  2871.     
  2872.     fetch('{{ path(\"ui_cart_remove\") }}', {
  2873.         method: 'POST',
  2874.         headers: { 
  2875.             'Content-Type': 'application/x-www-form-urlencoded',
  2876.             'X-Requested-With': 'XMLHttpRequest'
  2877.         },
  2878.         body: 'productId=' + productId
  2879.     })
  2880.     .then(response => response.json())
  2881.     .then(data => {
  2882.         if (data.ok) {
  2883.             // Supprimer des données locales
  2884.             delete cartData[productId];
  2885.             
  2886.             // Supprimer la ligne du DOM
  2887.             const row = document.querySelector(`tr:has(#qty-\${productId})`);
  2888.             if (row) {
  2889.                 row.remove();
  2890.             }
  2891.             
  2892.             // Mettre à jour les totaux
  2893.             updateCartTotals(data);
  2894.             
  2895.             // Mettre à jour le résumé du panier
  2896.             updateCartSummary();
  2897.             
  2898.             // Afficher un message de succès
  2899.             showAlert('Article supprimé', 'L\\'article a été supprimé de votre panier avec succès.', 'success');
  2900.             
  2901.             // Vérifier si le panier est vide
  2902.             if (Object.keys(cartData).length === 0) {
  2903.                 setTimeout(function() {
  2904.                     location.reload();
  2905.                 }, 1500);
  2906.             }
  2907.         } else {
  2908.             // Restaurer l'affichage en cas d'erreur
  2909.             if (row) {
  2910.                 row.style.opacity = '1';
  2911.                 row.style.pointerEvents = 'auto';
  2912.             }
  2913.             showAlert('Erreur', data.message || 'Erreur lors de la suppression de l\\'article.', 'error');
  2914.         }
  2915.     })
  2916.     .catch(error => {
  2917.         console.error('Erreur:', error);
  2918.         // Restaurer l'affichage en cas d'erreur réseau
  2919.         if (row) {
  2920.             row.style.opacity = '1';
  2921.             row.style.pointerEvents = 'auto';
  2922.         }
  2923.         showAlert('Erreur de connexion', 'Une erreur de connexion est survenue. Veuillez réessayer.', 'error');
  2924.     });
  2925. }
  2926. // Script pour forcer l'application des styles des boutons de quantité et initialiser l'état du bouton checkout
  2927. document.addEventListener('DOMContentLoaded', function() {
  2928.     // Initialiser l'état du bouton checkout
  2929.     updateCheckoutButtonState();
  2930.     const quantityControls = document.querySelectorAll('.quantity-controls');
  2931.     quantityControls.forEach(function(control) {
  2932.         if (control) {
  2933.             // Forcer les styles sur le conteneur
  2934.             control.style.display = 'flex';
  2935.             control.style.alignItems = 'center';
  2936.             control.style.justifyContent = 'center';
  2937.             control.style.border = '1px solid #ddd';
  2938.             control.style.borderRadius = '4px';
  2939.             control.style.width = '120px';
  2940.             control.style.height = '40px';
  2941.             control.style.position = 'relative';
  2942.             control.style.background = 'white';
  2943.             control.style.overflow = 'hidden';
  2944.             // Forcer les styles sur les boutons
  2945.             const buttons = control.querySelectorAll('.quantity-btn');
  2946.             buttons.forEach(function(btn, index) {
  2947.                 btn.style.background = '#f8f8f8';
  2948.                 btn.style.border = 'none';
  2949.                 btn.style.width = '35px';
  2950.                 btn.style.height = '100%';
  2951.                 btn.style.cursor = 'pointer';
  2952.                 btn.style.fontSize = '18px';
  2953.                 btn.style.fontWeight = '600';
  2954.                 btn.style.color = '#333';
  2955.                 btn.style.display = 'flex';
  2956.                 btn.style.alignItems = 'center';
  2957.                 btn.style.justifyContent = 'center';
  2958.                 btn.style.padding = '0';
  2959.                 btn.style.margin = '0';
  2960.                 btn.style.lineHeight = '1';
  2961.                 btn.style.position = 'relative';
  2962.                 btn.style.zIndex = '1';
  2963.                 // Ajouter les bordures entre les boutons
  2964.                 if (index === 0) {
  2965.                     btn.style.borderRight = '1px solid #ddd';
  2966.                 } else if (index === buttons.length - 1) {
  2967.                     btn.style.borderLeft = '1px solid #ddd';
  2968.                 }
  2969.             });
  2970.             // Forcer les styles sur l'input
  2971.             const input = control.querySelector('.quantity-input');
  2972.             if (input) {
  2973.                 input.style.border = 'none';
  2974.                 input.style.width = '50px';
  2975.                 input.style.height = '100%';
  2976.                 input.style.textAlign = 'center';
  2977.                 input.style.fontSize = '15px';
  2978.                 input.style.fontWeight = '500';
  2979.                 input.style.padding = '0';
  2980.                 input.style.margin = '0';
  2981.                 input.style.background = 'white';
  2982.                 input.style.color = '#333';
  2983.                 input.style.outline = 'none';
  2984.                 input.style.boxShadow = 'none';
  2985.                 input.style.position = 'relative';
  2986.                 input.style.zIndex = '1';
  2987.             }
  2988.         }
  2989.     });
  2990. });
  2991. </script>
  2992. {% endblock %}""home/cart.html.twig""/home/u540977899/domains/maketou-ht.com/public_html/templates/home/cart.html.twig");
  2993.     }
  2994. }