var/cache/dev/twig/a4/a4e17f34812ef56cebb6be73f1bda9ce927e0632bfb2b2ced9d13e89f5973d0a.php line 42

Open in your IDE?
  1. <?php
  2. use Twig\Environment;
  3. use Twig\Error\LoaderError;
  4. use Twig\Error\RuntimeError;
  5. use Twig\Extension\SandboxExtension;
  6. use Twig\Markup;
  7. use Twig\Sandbox\SecurityError;
  8. use Twig\Sandbox\SecurityNotAllowedTagError;
  9. use Twig\Sandbox\SecurityNotAllowedFilterError;
  10. use Twig\Sandbox\SecurityNotAllowedFunctionError;
  11. use Twig\Source;
  12. use Twig\Template;
  13. /* Product/list.twig */
  14. class __TwigTemplate_165ae04c1e9ac2af0f98e24f2a4eebe0f24f4a6c7d72193e747a93898e624c15 extends \Eccube\Twig\Template
  15. {
  16.     private $source;
  17.     private $macros = [];
  18.     public function __construct(Environment $env)
  19.     {
  20.         parent::__construct($env);
  21.         $this->source = $this->getSourceContext();
  22.         $this->blocks = [
  23.             'stylesheet' => [$this, 'block_stylesheet'],
  24.             'javascript' => [$this, 'block_javascript'],
  25.             'main' => [$this, 'block_main'],
  26.         ];
  27.         $this->sandbox = $this->env->getExtension('\Twig\Extension\SandboxExtension');
  28.         $this->checkSecurity();
  29.     }
  30.     protected function doGetParent(array $context)
  31.     {
  32.         // line 11
  33.         return "default_frame.twig";
  34.     }
  35.     protected function doDisplay(array $context, array $blocks = [])
  36.     {
  37.         $macros = $this->macros;
  38.         $__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  39.         $__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e->enter($__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "template", "Product/list.twig"));
  40.         $__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02 = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  41.         $__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02->enter($__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "template", "Product/list.twig"));
  42.         // line 13
  43.         $context["body_class"] = "product_page";
  44.         // line 11
  45.         $this->parent = $this->loadTemplate("default_frame.twig", "Product/list.twig", 11);
  46.         $this->parent->display($context, array_merge($this->blocks, $blocks));
  47.         
  48.         $__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e->leave($__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e_prof);
  49.         
  50.         $__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02->leave($__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02_prof);
  51.     }
  52.     // line 16
  53.     public function block_stylesheet($context, array $blocks = [])
  54.     {
  55.         $macros = $this->macros;
  56.         $__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  57.         $__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e->enter($__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "stylesheet"));
  58.         $__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02 = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  59.         $__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02->enter($__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "stylesheet"));
  60.         // line 17
  61.         echo "    <link rel=\"stylesheet\" href=\"";
  62.         echo twig_escape_filter($this->env, $this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("assets/css/product-list.css"), "html", null, true);
  63.         echo "\">
  64. ";
  65.         
  66.         $__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02->leave($__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02_prof);
  67.         
  68.         $__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e->leave($__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e_prof);
  69.     }
  70.     // line 20
  71.     public function block_javascript($context, array $blocks = [])
  72.     {
  73.         $macros = $this->macros;
  74.         $__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  75.         $__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e->enter($__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "javascript"));
  76.         $__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02 = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  77.         $__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02->enter($__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "javascript"));
  78.         // line 21
  79.         echo "<script>
  80. (function() {
  81.     // Lấy URL hiện tại và tạo URLSearchParams
  82.     function getCurrentUrlParams() {
  83.         const urlParams = new URLSearchParams(window.location.search);
  84.         return urlParams;
  85.     }
  86.     // Cập nhật URL với category filters và reload
  87.     function updateCategoryFilters() {
  88.         const checkboxes = document.querySelectorAll('.filter-option__checkbox');
  89.         const urlParams = getCurrentUrlParams();
  90.         // Xóa tất cả category_filter[] cũ (có thể có nhiều giá trị)
  91.         const keysToDelete = [];
  92.         urlParams.forEach(function(value, key) {
  93.             if (key === 'category_filter[]' || key.startsWith('category_filter')) {
  94.                 keysToDelete.push(key);
  95.             }
  96.         });
  97.         keysToDelete.forEach(function(key) {
  98.             urlParams.delete(key);
  99.         });
  100.         // Thu thập category theo từng block tiêu chí.
  101.         // Trong cùng block là OR, giữa các block sẽ được backend xử lý là AND.
  102.         const selectedCategoriesByGroup = {};
  103.         checkboxes.forEach(function(checkbox) {
  104.             if (checkbox.checked) {
  105.                 const groupId = checkbox.dataset.groupId;
  106.                 if (!selectedCategoriesByGroup[groupId]) {
  107.                     selectedCategoriesByGroup[groupId] = [];
  108.                 }
  109.                 selectedCategoriesByGroup[groupId].push(checkbox.value);
  110.             }
  111.         });
  112.         Object.keys(selectedCategoriesByGroup).forEach(function(groupId) {
  113.             selectedCategoriesByGroup[groupId].forEach(function(categoryId) {
  114.                 urlParams.append('category_filter[' + groupId + '][]', categoryId);
  115.             });
  116.         });
  117.         // Reset về trang 1 khi filter
  118.         urlParams.set('pageno', '1');
  119.         // Tạo URL mới
  120.         const queryString = urlParams.toString();
  121.         const newUrl = queryString
  122.             ? window.location.pathname + '?' + queryString
  123.             : window.location.pathname;
  124.         // Reload page với query params mới
  125.         window.location.href = newUrl;
  126.     }
  127.     // Khôi phục trạng thái checkbox từ URL và xử lý nút search
  128.     document.addEventListener('DOMContentLoaded', function() {
  129.         const checkboxes = document.querySelectorAll('.filter-option__checkbox');
  130.         const searchButton = document.querySelector('.btn-search');
  131.         // Khôi phục trạng thái checkbox từ URL
  132.         const urlParams = getCurrentUrlParams();
  133.         const selectedCategories = [];
  134.         urlParams.forEach(function(value, key) {
  135.             if (key.startsWith('category_filter[')) {
  136.                 selectedCategories.push(value);
  137.             }
  138.         });
  139.         checkboxes.forEach(function(checkbox) {
  140.             // Set checked nếu category ID có trong URL
  141.             if (selectedCategories.includes(checkbox.value)) {
  142.                 checkbox.checked = true;
  143.             }
  144.             // Không lắng nghe sự kiện change trên checkbox nữa
  145.         });
  146.         // Lắng nghe sự kiện click trên nút search
  147.         if (searchButton) {
  148.             searchButton.addEventListener('click', function() {
  149.                 updateCategoryFilters();
  150.             });
  151.         }
  152.     });
  153. })();
  154. </script>
  155. ";
  156.         
  157.         $__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02->leave($__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02_prof);
  158.         
  159.         $__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e->leave($__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e_prof);
  160.     }
  161.     // line 110
  162.     public function block_main($context, array $blocks = [])
  163.     {
  164.         $macros = $this->macros;
  165.         $__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  166.         $__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e->enter($__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "main"));
  167.         $__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02 = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  168.         $__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02->enter($__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "main"));
  169.         // line 111
  170.         echo "
  171.  <body>
  172.   <!-- breadcrumb section -->
  173.   <div class=\"breadcrumb-section\">
  174.     <div class=\"container-1360 border-box px-40\">
  175.       <nav class=\"breadcrumb\">
  176.         <a href=\"";
  177.         // line 117
  178.         echo $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getUrl("homepage");
  179.         echo "\" class=\"breadcrumb__item text-black\">ホーム</a>
  180.         <img src=\"";
  181.         // line 118
  182.         echo twig_escape_filter($this->env, $this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("assets/img/default/icons/icon-breadcrumb-arrow.svg"), "html", null, true);
  183.         echo "\" alt=\">\" class=\"breadcrumb__separator\">
  184.         <a href=\"";
  185.         // line 119
  186.         echo $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getUrl("product_list");
  187.         echo "\" class=\"breadcrumb__item text-black\">商品一覧</a>
  188.       </nav>
  189.     </div>
  190.   </div>
  191.   <!-- product list section -->
  192.   <div class=\"container-1200\">
  193.     <div class=\"product-list-wrapper\">
  194.       <div class=\"product-list-left\">
  195.         ";
  196.         // line 128
  197.         if ((array_key_exists("searchable_categories", $context) && (twig_length_filter($this->env, (isset($context["searchable_categories"]) || array_key_exists("searchable_categories", $context) ? $context["searchable_categories"] : (function () { throw new RuntimeError('Variable "searchable_categories" does not exist.', 128, $this->source); })())) > 0))) {
  198.             // line 129
  199.             echo "          ";
  200.             $context['_parent'] = $context;
  201.             $context['_seq'] = twig_ensure_traversable((isset($context["searchable_categories"]) || array_key_exists("searchable_categories", $context) ? $context["searchable_categories"] : (function () { throw new RuntimeError('Variable "searchable_categories" does not exist.', 129, $this->source); })()));
  202.             foreach ($context['_seq'] as $context["_key"] => $context["group"]) {
  203.                 // line 130
  204.                 echo "            <div class=\"filter-group\">
  205.               <div class=\"filter-group__header\">";
  206.                 // line 131
  207.                 echo twig_escape_filter($this->env, $this->sandbox->ensureToStringAllowed(twig_get_attribute($this->env, $this->source, twig_get_attribute($this->env, $this->source, $context["group"], "parent", [], "any", false, false, true, 131), "name", [], "any", false, false, true, 131), 131, $this->source), "html", null, true);
  208.                 echo "</div>
  209.               <div class=\"filter-group__options\">
  210.                 ";
  211.                 // line 133
  212.                 if ((twig_length_filter($this->env, twig_get_attribute($this->env, $this->source, $context["group"], "children", [], "any", false, false, true, 133)) > 0)) {
  213.                     // line 134
  214.                     echo "                  ";
  215.                     $context['_parent'] = $context;
  216.                     $context['_seq'] = twig_ensure_traversable(twig_get_attribute($this->env, $this->source, $context["group"], "children", [], "any", false, false, true, 134));
  217.                     foreach ($context['_seq'] as $context["_key"] => $context["child"]) {
  218.                         // line 135
  219.                         echo "                    <label class=\"filter-option\">
  220.                       <input type=\"checkbox\"
  221.                              class=\"filter-option__checkbox\"
  222.                              name=\"category_filter[";
  223.                         // line 138
  224.                         echo twig_escape_filter($this->env, $this->sandbox->ensureToStringAllowed(twig_get_attribute($this->env, $this->source, twig_get_attribute($this->env, $this->source, $context["group"], "parent", [], "any", false, false, true, 138), "id", [], "any", false, false, true, 138), 138, $this->source), "html", null, true);
  225.                         echo "][]\"
  226.                              value=\"";
  227.                         // line 139
  228.                         echo twig_escape_filter($this->env, $this->sandbox->ensureToStringAllowed(twig_get_attribute($this->env, $this->source, $context["child"], "id", [], "any", false, false, true, 139), 139, $this->source), "html", null, true);
  229.                         echo "\"
  230.                              data-category-id=\"";
  231.                         // line 140
  232.                         echo twig_escape_filter($this->env, $this->sandbox->ensureToStringAllowed(twig_get_attribute($this->env, $this->source, $context["child"], "id", [], "any", false, false, true, 140), 140, $this->source), "html", null, true);
  233.                         echo "\"
  234.                              data-group-id=\"";
  235.                         // line 141
  236.                         echo twig_escape_filter($this->env, $this->sandbox->ensureToStringAllowed(twig_get_attribute($this->env, $this->source, twig_get_attribute($this->env, $this->source, $context["group"], "parent", [], "any", false, false, true, 141), "id", [], "any", false, false, true, 141), 141, $this->source), "html", null, true);
  237.                         echo "\">
  238.                       <span class=\"filter-option__label\">";
  239.                         // line 142
  240.                         echo twig_escape_filter($this->env, $this->sandbox->ensureToStringAllowed(twig_get_attribute($this->env, $this->source, $context["child"], "name", [], "any", false, false, true, 142), 142, $this->source), "html", null, true);
  241.                         echo "</span>
  242.                     </label>
  243.                   ";
  244.                     }
  245.                     $_parent = $context['_parent'];
  246.                     unset($context['_seq'], $context['_iterated'], $context['_key'], $context['child'], $context['_parent'], $context['loop']);
  247.                     $context = array_intersect_key($context, $_parent) + $_parent;
  248.                     // line 145
  249.                     echo "                ";
  250.                 } else {
  251.                     // line 146
  252.                     echo "                  ";
  253.                     // line 147
  254.                     echo "                  <label class=\"filter-option\">
  255.                     <input type=\"checkbox\"
  256.                            class=\"filter-option__checkbox\"
  257.                            name=\"category_filter[";
  258.                     // line 150
  259.                     echo twig_escape_filter($this->env, $this->sandbox->ensureToStringAllowed(twig_get_attribute($this->env, $this->source, twig_get_attribute($this->env, $this->source, $context["group"], "parent", [], "any", false, false, true, 150), "id", [], "any", false, false, true, 150), 150, $this->source), "html", null, true);
  260.                     echo "][]\"
  261.                            value=\"";
  262.                     // line 151
  263.                     echo twig_escape_filter($this->env, $this->sandbox->ensureToStringAllowed(twig_get_attribute($this->env, $this->source, twig_get_attribute($this->env, $this->source, $context["group"], "parent", [], "any", false, false, true, 151), "id", [], "any", false, false, true, 151), 151, $this->source), "html", null, true);
  264.                     echo "\"
  265.                            data-category-id=\"";
  266.                     // line 152
  267.                     echo twig_escape_filter($this->env, $this->sandbox->ensureToStringAllowed(twig_get_attribute($this->env, $this->source, twig_get_attribute($this->env, $this->source, $context["group"], "parent", [], "any", false, false, true, 152), "id", [], "any", false, false, true, 152), 152, $this->source), "html", null, true);
  268.                     echo "\"
  269.                            data-group-id=\"";
  270.                     // line 153
  271.                     echo twig_escape_filter($this->env, $this->sandbox->ensureToStringAllowed(twig_get_attribute($this->env, $this->source, twig_get_attribute($this->env, $this->source, $context["group"], "parent", [], "any", false, false, true, 153), "id", [], "any", false, false, true, 153), 153, $this->source), "html", null, true);
  272.                     echo "\">
  273.                     <span class=\"filter-option__label\">";
  274.                     // line 154
  275.                     echo twig_escape_filter($this->env, $this->sandbox->ensureToStringAllowed(twig_get_attribute($this->env, $this->source, twig_get_attribute($this->env, $this->source, $context["group"], "parent", [], "any", false, false, true, 154), "name", [], "any", false, false, true, 154), 154, $this->source), "html", null, true);
  276.                     echo "</span>
  277.                   </label>
  278.                 ";
  279.                 }
  280.                 // line 157
  281.                 echo "              </div>
  282.             </div>
  283.           ";
  284.             }
  285.             $_parent = $context['_parent'];
  286.             unset($context['_seq'], $context['_iterated'], $context['_key'], $context['group'], $context['_parent'], $context['loop']);
  287.             $context = array_intersect_key($context, $_parent) + $_parent;
  288.             // line 160
  289.             echo "        ";
  290.         }
  291.         // line 161
  292.         echo "        <button class=\"btn-primary btn-search w-100\">
  293.             <span>検索する</span>
  294.             <svg class=\"btn-search-icon\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">
  295.             <rect width=\"24\" height=\"24\" rx=\"12\" fill=\"black\"/>
  296.             <path d=\"M16.252 12.001L16.249 12.0039L16.252 12.0068L11.7266 16.5312L10.5957 15.4004L13.1943 12.8027H7.72852V11.2031H13.1924L10.5957 8.60742L11.7266 7.47656L16.252 12.001Z\" fill=\"#FBE800\"/>
  297.             </svg>
  298.         </button>
  299.       </div>
  300.       <!-- bottom line -->
  301.       <div class=\"bottom-line container-mobile\"></div>
  302.       <!-- Product List Right -->
  303.       <div class=\"product-list-right\">
  304.         <div class=\"product-grid\" id=\"product-grid\">
  305.           ";
  306.         // line 174
  307.         if ((twig_get_attribute($this->env, $this->source, (isset($context["pagination"]) || array_key_exists("pagination", $context) ? $context["pagination"] : (function () { throw new RuntimeError('Variable "pagination" does not exist.', 174, $this->source); })()), "totalItemCount", [], "any", false, false, true, 174) > 0)) {
  308.             // line 175
  309.             echo "            ";
  310.             $context['_parent'] = $context;
  311.             $context['_seq'] = twig_ensure_traversable((isset($context["pagination"]) || array_key_exists("pagination", $context) ? $context["pagination"] : (function () { throw new RuntimeError('Variable "pagination" does not exist.', 175, $this->source); })()));
  312.             $context['loop'] = [
  313.               'parent' => $context['_parent'],
  314.               'index0' => 0,
  315.               'index'  => 1,
  316.               'first'  => true,
  317.             ];
  318.             if (is_array($context['_seq']) || (is_object($context['_seq']) && $context['_seq'] instanceof \Countable)) {
  319.                 $length = count($context['_seq']);
  320.                 $context['loop']['revindex0'] = $length - 1;
  321.                 $context['loop']['revindex'] = $length;
  322.                 $context['loop']['length'] = $length;
  323.                 $context['loop']['last'] = 1 === $length;
  324.             }
  325.             foreach ($context['_seq'] as $context["_key"] => $context["Product"]) {
  326.                 // line 176
  327.                 echo "              <div class=\"product-item\">
  328.                 <a href=\"";
  329.                 // line 177
  330.                 echo twig_escape_filter($this->env, $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getUrl("product_detail", ["id" => twig_get_attribute($this->env, $this->source, $context["Product"], "id", [], "any", false, false, true, 177)]), "html", null, true);
  331.                 echo "\" class=\"product-card-small\">
  332.                   <div class=\"product-card-small__image\">
  333.                     <img src=\"";
  334.                 // line 179
  335.                 echo twig_escape_filter($this->env, $this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl($this->extensions['Eccube\Twig\Extension\EccubeExtension']->getNoImageProduct($this->sandbox->ensureToStringAllowed(twig_get_attribute($this->env, $this->source, $context["Product"], "main_list_image", [], "any", false, false, true, 179), 179, $this->source)), "save_image"), "html", null, true);
  336.                 echo "\" alt=\"";
  337.                 echo twig_escape_filter($this->env, $this->sandbox->ensureToStringAllowed(twig_get_attribute($this->env, $this->source, $context["Product"], "name", [], "any", false, false, true, 179), 179, $this->source), "html", null, true);
  338.                 echo "\" ";
  339.                 if ((twig_get_attribute($this->env, $this->source, $context["loop"], "index", [], "any", false, false, true, 179) > 5)) {
  340.                     echo " loading=\"lazy\"";
  341.                 }
  342.                 echo ">
  343.                     <div class=\"product-card-small__arrow\">
  344.                         <img src=\"";
  345.                 // line 181
  346.                 echo twig_escape_filter($this->env, $this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("assets/img/default/icons/icon-heart.svg"), "html", null, true);
  347.                 echo "\" alt=\"Favorite\" loading=\"lazy\">
  348.                     </div>
  349.                   </div>
  350.                 </a>
  351.                 <div class=\"product-item__info\">
  352.                   <a href=\"";
  353.                 // line 186
  354.                 echo twig_escape_filter($this->env, $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getUrl("product_detail", ["id" => twig_get_attribute($this->env, $this->source, $context["Product"], "id", [], "any", false, false, true, 186)]), "html", null, true);
  355.                 echo "\">
  356.                     <h4 class=\"product-item__title\" data-bs-toggle=\"tooltip\" data-bs-placement=\"top\" title=\"";
  357.                 // line 187
  358.                 echo twig_escape_filter($this->env, $this->sandbox->ensureToStringAllowed(twig_get_attribute($this->env, $this->source, $context["Product"], "name", [], "any", false, false, true, 187), 187, $this->source), "html", null, true);
  359.                 echo "\">";
  360.                 echo twig_escape_filter($this->env, $this->sandbox->ensureToStringAllowed(twig_get_attribute($this->env, $this->source, $context["Product"], "name", [], "any", false, false, true, 187), 187, $this->source), "html", null, true);
  361.                 echo "</h4>
  362.                   </a>
  363.                   <div class=\"product-item__price\">
  364.                     <span class=\"price-symbol\">¥</span>
  365.                     <span class=\"price-amount\">
  366.                       ";
  367.                 // line 192
  368.                 if (twig_get_attribute($this->env, $this->source, $context["Product"], "hasProductClass", [], "any", false, false, true, 192)) {
  369.                     // line 193
  370.                     echo "                        ";
  371.                     if ((twig_get_attribute($this->env, $this->source, $context["Product"], "getPrice02IncTaxMin", [], "any", false, false, true, 193) == twig_get_attribute($this->env, $this->source, $context["Product"], "getPrice02IncTaxMax", [], "any", false, false, true, 193))) {
  372.                         // line 194
  373.                         echo "                          ";
  374.                         echo twig_escape_filter($this->env, twig_number_format_filter($this->env, $this->sandbox->ensureToStringAllowed(twig_get_attribute($this->env, $this->source, $context["Product"], "getPrice02IncTaxMin", [], "any", false, false, true, 194), 194, $this->source)), "html", null, true);
  375.                         echo "
  376.                         ";
  377.                     } else {
  378.                         // line 196
  379.                         echo "                          ";
  380.                         echo twig_escape_filter($this->env, twig_number_format_filter($this->env, $this->sandbox->ensureToStringAllowed(twig_get_attribute($this->env, $this->source, $context["Product"], "getPrice02IncTaxMin", [], "any", false, false, true, 196), 196, $this->source)), "html", null, true);
  381.                         echo " ~ ";
  382.                         echo twig_escape_filter($this->env, twig_number_format_filter($this->env, $this->sandbox->ensureToStringAllowed(twig_get_attribute($this->env, $this->source, $context["Product"], "getPrice02IncTaxMax", [], "any", false, false, true, 196), 196, $this->source)), "html", null, true);
  383.                         echo "
  384.                         ";
  385.                     }
  386.                     // line 198
  387.                     echo "                      ";
  388.                 } else {
  389.                     // line 199
  390.                     echo "                        ";
  391.                     echo twig_escape_filter($this->env, twig_number_format_filter($this->env, $this->sandbox->ensureToStringAllowed(twig_get_attribute($this->env, $this->source, $context["Product"], "getPrice02IncTaxMin", [], "any", false, false, true, 199), 199, $this->source)), "html", null, true);
  392.                     echo "
  393.                       ";
  394.                 }
  395.                 // line 201
  396.                 echo "                    </span>
  397.                     <span class=\"price-tax\">(税込)</span>
  398.                   </div>
  399.                 </div>
  400.               </div>
  401.             ";
  402.                 ++$context['loop']['index0'];
  403.                 ++$context['loop']['index'];
  404.                 $context['loop']['first'] = false;
  405.                 if (isset($context['loop']['length'])) {
  406.                     --$context['loop']['revindex0'];
  407.                     --$context['loop']['revindex'];
  408.                     $context['loop']['last'] = 0 === $context['loop']['revindex0'];
  409.                 }
  410.             }
  411.             $_parent = $context['_parent'];
  412.             unset($context['_seq'], $context['_iterated'], $context['_key'], $context['Product'], $context['_parent'], $context['loop']);
  413.             $context = array_intersect_key($context, $_parent) + $_parent;
  414.             // line 207
  415.             echo "          ";
  416.         } else {
  417.             // line 208
  418.             echo "            <span>";
  419.             echo twig_escape_filter($this->env, $this->extensions['Symfony\Bridge\Twig\Extension\TranslationExtension']->trans("front.product.search__product_not_found"), "html", null, true);
  420.             echo "</span>
  421.           ";
  422.         }
  423.         // line 210
  424.         echo "        </div>
  425.         <!-- Pagination -->
  426.         <div class=\"pagination-product-list-wrapper\">
  427.           <div class=\"pagination-product-list\" style=\"margin: 0 auto;\">
  428.             ";
  429.         // line 214
  430.         $this->loadTemplate("Block/_pagination.twig", "Product/list.twig", 214)->display(twig_array_merge($context, ["pages" => twig_get_attribute($this->env, $this->source, (isset($context["pagination"]) || array_key_exists("pagination", $context) ? $context["pagination"] : (function () { throw new RuntimeError('Variable "pagination" does not exist.', 214, $this->source); })()), "paginationData", [], "any", false, false, true, 214)]));
  431.         // line 215
  432.         echo "          </div>
  433.         </div>
  434.       </div>
  435.     </div>
  436.   </div>
  437.  </body>
  438. ";
  439.         
  440.         $__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02->leave($__internal_319393461309892924ff6e74d6d6e64287df64b63545b994e100d4ab223aed02_prof);
  441.         
  442.         $__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e->leave($__internal_085b0142806202599c7fe3b329164a92397d8978207a37e79d70b8c52599e33e_prof);
  443.     }
  444.     public function getTemplateName()
  445.     {
  446.         return "Product/list.twig";
  447.     }
  448.     public function isTraitable()
  449.     {
  450.         return false;
  451.     }
  452.     public function getDebugInfo()
  453.     {
  454.         return array (  468 => 215,  466 => 214,  460 => 210,  454 => 208,  451 => 207,  432 => 201,  426 => 199,  423 => 198,  415 => 196,  409 => 194,  406 => 193,  404 => 192,  394 => 187,  390 => 186,  382 => 181,  371 => 179,  366 => 177,  363 => 176,  345 => 175,  343 => 174,  328 => 161,  325 => 160,  317 => 157,  311 => 154,  307 => 153,  303 => 152,  299 => 151,  295 => 150,  290 => 147,  288 => 146,  285 => 145,  276 => 142,  272 => 141,  268 => 140,  264 => 139,  260 => 138,  255 => 135,  250 => 134,  248 => 133,  243 => 131,  240 => 130,  235 => 129,  233 => 128,  221 => 119,  217 => 118,  213 => 117,  205 => 111,  195 => 110,  98 => 21,  88 => 20,  75 => 17,  65 => 16,  54 => 11,  52 => 13,  39 => 11,);
  455.     }
  456.     public function getSourceContext()
  457.     {
  458.         return new Source("{#
  459. This file is part of EC-CUBE
  460. Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
  461. http://www.ec-cube.co.jp/
  462. For the full copyright and license information, please view the LICENSE
  463. file that was distributed with this source code.
  464. #}
  465. {% extends 'default_frame.twig' %}
  466. {% set body_class = 'product_page' %}
  467. {# style #}
  468. {% block stylesheet %}
  469.     <link rel=\"stylesheet\" href=\"{{ asset('assets/css/product-list.css') }}\">
  470. {% endblock %}
  471. {% block javascript %}
  472. <script>
  473. (function() {
  474.     // Lấy URL hiện tại và tạo URLSearchParams
  475.     function getCurrentUrlParams() {
  476.         const urlParams = new URLSearchParams(window.location.search);
  477.         return urlParams;
  478.     }
  479.     // Cập nhật URL với category filters và reload
  480.     function updateCategoryFilters() {
  481.         const checkboxes = document.querySelectorAll('.filter-option__checkbox');
  482.         const urlParams = getCurrentUrlParams();
  483.         // Xóa tất cả category_filter[] cũ (có thể có nhiều giá trị)
  484.         const keysToDelete = [];
  485.         urlParams.forEach(function(value, key) {
  486.             if (key === 'category_filter[]' || key.startsWith('category_filter')) {
  487.                 keysToDelete.push(key);
  488.             }
  489.         });
  490.         keysToDelete.forEach(function(key) {
  491.             urlParams.delete(key);
  492.         });
  493.         // Thu thập category theo từng block tiêu chí.
  494.         // Trong cùng block là OR, giữa các block sẽ được backend xử lý là AND.
  495.         const selectedCategoriesByGroup = {};
  496.         checkboxes.forEach(function(checkbox) {
  497.             if (checkbox.checked) {
  498.                 const groupId = checkbox.dataset.groupId;
  499.                 if (!selectedCategoriesByGroup[groupId]) {
  500.                     selectedCategoriesByGroup[groupId] = [];
  501.                 }
  502.                 selectedCategoriesByGroup[groupId].push(checkbox.value);
  503.             }
  504.         });
  505.         Object.keys(selectedCategoriesByGroup).forEach(function(groupId) {
  506.             selectedCategoriesByGroup[groupId].forEach(function(categoryId) {
  507.                 urlParams.append('category_filter[' + groupId + '][]', categoryId);
  508.             });
  509.         });
  510.         // Reset về trang 1 khi filter
  511.         urlParams.set('pageno', '1');
  512.         // Tạo URL mới
  513.         const queryString = urlParams.toString();
  514.         const newUrl = queryString
  515.             ? window.location.pathname + '?' + queryString
  516.             : window.location.pathname;
  517.         // Reload page với query params mới
  518.         window.location.href = newUrl;
  519.     }
  520.     // Khôi phục trạng thái checkbox từ URL và xử lý nút search
  521.     document.addEventListener('DOMContentLoaded', function() {
  522.         const checkboxes = document.querySelectorAll('.filter-option__checkbox');
  523.         const searchButton = document.querySelector('.btn-search');
  524.         // Khôi phục trạng thái checkbox từ URL
  525.         const urlParams = getCurrentUrlParams();
  526.         const selectedCategories = [];
  527.         urlParams.forEach(function(value, key) {
  528.             if (key.startsWith('category_filter[')) {
  529.                 selectedCategories.push(value);
  530.             }
  531.         });
  532.         checkboxes.forEach(function(checkbox) {
  533.             // Set checked nếu category ID có trong URL
  534.             if (selectedCategories.includes(checkbox.value)) {
  535.                 checkbox.checked = true;
  536.             }
  537.             // Không lắng nghe sự kiện change trên checkbox nữa
  538.         });
  539.         // Lắng nghe sự kiện click trên nút search
  540.         if (searchButton) {
  541.             searchButton.addEventListener('click', function() {
  542.                 updateCategoryFilters();
  543.             });
  544.         }
  545.     });
  546. })();
  547. </script>
  548. {% endblock %}
  549. {% block main %}
  550.  <body>
  551.   <!-- breadcrumb section -->
  552.   <div class=\"breadcrumb-section\">
  553.     <div class=\"container-1360 border-box px-40\">
  554.       <nav class=\"breadcrumb\">
  555.         <a href=\"{{ url('homepage') }}\" class=\"breadcrumb__item text-black\">ホーム</a>
  556.         <img src=\"{{ asset('assets/img/default/icons/icon-breadcrumb-arrow.svg') }}\" alt=\">\" class=\"breadcrumb__separator\">
  557.         <a href=\"{{ url('product_list') }}\" class=\"breadcrumb__item text-black\">商品一覧</a>
  558.       </nav>
  559.     </div>
  560.   </div>
  561.   <!-- product list section -->
  562.   <div class=\"container-1200\">
  563.     <div class=\"product-list-wrapper\">
  564.       <div class=\"product-list-left\">
  565.         {% if searchable_categories is defined and searchable_categories|length > 0 %}
  566.           {% for group in searchable_categories %}
  567.             <div class=\"filter-group\">
  568.               <div class=\"filter-group__header\">{{ group.parent.name }}</div>
  569.               <div class=\"filter-group__options\">
  570.                 {% if group.children|length > 0 %}
  571.                   {% for child in group.children %}
  572.                     <label class=\"filter-option\">
  573.                       <input type=\"checkbox\"
  574.                              class=\"filter-option__checkbox\"
  575.                              name=\"category_filter[{{ group.parent.id }}][]\"
  576.                              value=\"{{ child.id }}\"
  577.                              data-category-id=\"{{ child.id }}\"
  578.                              data-group-id=\"{{ group.parent.id }}\">
  579.                       <span class=\"filter-option__label\">{{ child.name }}</span>
  580.                     </label>
  581.                   {% endfor %}
  582.                 {% else %}
  583.                   {# Nếu parent category cũng có is_searchable và không có children, hiển thị parent #}
  584.                   <label class=\"filter-option\">
  585.                     <input type=\"checkbox\"
  586.                            class=\"filter-option__checkbox\"
  587.                            name=\"category_filter[{{ group.parent.id }}][]\"
  588.                            value=\"{{ group.parent.id }}\"
  589.                            data-category-id=\"{{ group.parent.id }}\"
  590.                            data-group-id=\"{{ group.parent.id }}\">
  591.                     <span class=\"filter-option__label\">{{ group.parent.name }}</span>
  592.                   </label>
  593.                 {% endif %}
  594.               </div>
  595.             </div>
  596.           {% endfor %}
  597.         {% endif %}
  598.         <button class=\"btn-primary btn-search w-100\">
  599.             <span>検索する</span>
  600.             <svg class=\"btn-search-icon\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">
  601.             <rect width=\"24\" height=\"24\" rx=\"12\" fill=\"black\"/>
  602.             <path d=\"M16.252 12.001L16.249 12.0039L16.252 12.0068L11.7266 16.5312L10.5957 15.4004L13.1943 12.8027H7.72852V11.2031H13.1924L10.5957 8.60742L11.7266 7.47656L16.252 12.001Z\" fill=\"#FBE800\"/>
  603.             </svg>
  604.         </button>
  605.       </div>
  606.       <!-- bottom line -->
  607.       <div class=\"bottom-line container-mobile\"></div>
  608.       <!-- Product List Right -->
  609.       <div class=\"product-list-right\">
  610.         <div class=\"product-grid\" id=\"product-grid\">
  611.           {% if pagination.totalItemCount > 0 %}
  612.             {% for Product in pagination %}
  613.               <div class=\"product-item\">
  614.                 <a href=\"{{ url('product_detail', {'id': Product.id}) }}\" class=\"product-card-small\">
  615.                   <div class=\"product-card-small__image\">
  616.                     <img src=\"{{ asset(Product.main_list_image|no_image_product, 'save_image') }}\" alt=\"{{ Product.name }}\" {% if loop.index > 5 %} loading=\"lazy\"{% endif %}>
  617.                     <div class=\"product-card-small__arrow\">
  618.                         <img src=\"{{ asset('assets/img/default/icons/icon-heart.svg') }}\" alt=\"Favorite\" loading=\"lazy\">
  619.                     </div>
  620.                   </div>
  621.                 </a>
  622.                 <div class=\"product-item__info\">
  623.                   <a href=\"{{ url('product_detail', {'id': Product.id}) }}\">
  624.                     <h4 class=\"product-item__title\" data-bs-toggle=\"tooltip\" data-bs-placement=\"top\" title=\"{{ Product.name }}\">{{ Product.name }}</h4>
  625.                   </a>
  626.                   <div class=\"product-item__price\">
  627.                     <span class=\"price-symbol\">¥</span>
  628.                     <span class=\"price-amount\">
  629.                       {% if Product.hasProductClass %}
  630.                         {% if Product.getPrice02IncTaxMin == Product.getPrice02IncTaxMax %}
  631.                           {{ Product.getPrice02IncTaxMin|number_format }}
  632.                         {% else %}
  633.                           {{ Product.getPrice02IncTaxMin|number_format }} ~ {{ Product.getPrice02IncTaxMax|number_format }}
  634.                         {% endif %}
  635.                       {% else %}
  636.                         {{ Product.getPrice02IncTaxMin|number_format }}
  637.                       {% endif %}
  638.                     </span>
  639.                     <span class=\"price-tax\">(税込)</span>
  640.                   </div>
  641.                 </div>
  642.               </div>
  643.             {% endfor %}
  644.           {% else %}
  645.             <span>{{ 'front.product.search__product_not_found'|trans }}</span>
  646.           {% endif %}
  647.         </div>
  648.         <!-- Pagination -->
  649.         <div class=\"pagination-product-list-wrapper\">
  650.           <div class=\"pagination-product-list\" style=\"margin: 0 auto;\">
  651.             {% include \"Block/_pagination.twig\" with {'pages': pagination.paginationData} %}
  652.           </div>
  653.         </div>
  654.       </div>
  655.     </div>
  656.   </div>
  657.  </body>
  658. {% endblock %}
  659. ", "Product/list.twig", "/var/www/html/app/template/default/Product/list.twig");
  660.     }
  661.     
  662.     public function checkSecurity()
  663.     {
  664.         static $tags = array("set" => 13, "if" => 128, "for" => 129, "include" => 214);
  665.         static $filters = array("escape" => 17, "length" => 128, "no_image_product" => 179, "number_format" => 194, "trans" => 208);
  666.         static $functions = array("asset" => 17, "url" => 117);
  667.         try {
  668.             $this->sandbox->checkSecurity(
  669.                 ['set', 'if', 'for', 'include'],
  670.                 ['escape', 'length', 'no_image_product', 'number_format', 'trans'],
  671.                 ['asset', 'url']
  672.             );
  673.         } catch (SecurityError $e) {
  674.             $e->setSourceContext($this->source);
  675.             if ($e instanceof SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) {
  676.                 $e->setTemplateLine($tags[$e->getTagName()]);
  677.             } elseif ($e instanceof SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) {
  678.                 $e->setTemplateLine($filters[$e->getFilterName()]);
  679.             } elseif ($e instanceof SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) {
  680.                 $e->setTemplateLine($functions[$e->getFunctionName()]);
  681.             }
  682.             throw $e;
  683.         }
  684.     }
  685. }