templates/product/list.html.twig line 1

Open in your IDE?
  1. {% extends 'base.html.twig' %}
  2. {% set menuMode = 'catalog' %}
  3. {% set title = 'Каталог' %}
  4. {% block stylesheets %}
  5.   {{ parent() }}
  6.   <style>
  7.     .table-catalog {
  8.       font-size: 11px;
  9.     }
  10.     .card-filter .form-label {
  11.       font-size: 12px;
  12.       margin-bottom: 0.2rem;
  13.     }
  14.     .card-filter .form-control-sm {
  15.       font-size: 11px;
  16.     }
  17.     .card-filter .form-check-label {
  18.       font-size: 12px;
  19.     }
  20.     .selection-wrapper {
  21.       position: fixed;
  22.       bottom: 40px;
  23.       right: 15px;
  24.       background: #212529;
  25.       color: white;
  26.       padding: 10px;
  27.       border-radius: 10px;
  28.       opacity: 0.7;
  29.       max-width: 20rem;
  30.     }
  31.     .selection-wrapper:hover {
  32.       opacity: 1;
  33.     }
  34.   </style>
  35. {% endblock %}
  36. {% block main %}
  37.   <div class="container-fluid">
  38.     <div class="row">
  39.       <div class="col-md-2">
  40.         <div class="card">
  41.           <div class="card-header">Фильтрация</div>
  42.           <div class="card-body card-filter">
  43.             <form method="GET">
  44.               <div class="row">
  45.                 <div class="col-md-12">
  46.                   <div class="mb-1">
  47.                     <label for="filter_name" class="form-label">Наименование</label>
  48.                     <input type="text" class="form-control form-control-sm" id="filter_name" name="name" value="{{ app.request.get('name') }}">
  49.                   </div>
  50.                 </div>
  51.                 <div class="col-md-6">
  52.                   <div class="mb-1">
  53.                     <label for="filter_provider_sku" class="form-label">Артикул поставщика</label>
  54.                     <input type="text" class="form-control form-control-sm" id="filter_provider_sku" name="provider_sku" value="{{ app.request.get('provider_sku') }}">
  55.                   </div>
  56.                 </div>
  57.                 <div class="col-md-6">
  58.                   <div class="mb-1">
  59.                     <label for="filter_site_sku" class="form-label">Артикул на сайте</label>
  60.                     <input type="text" class="form-control form-control-sm" id="filter_site_sku" name="site_sku" value="{{ app.request.get('site_sku') }}">
  61.                   </div>
  62.                 </div>
  63.                 <div class="col-md-12">
  64.                   <div class="mb-1">
  65.                     <label for="filter_site_sku" class="form-label">Бренд</label>
  66.                     <select class="form-select form-select-sm" id="filter-brand" name="brand">
  67.                       <option value="">Не выбран</option>
  68.                       {% for brand in brands %}
  69.                         <option value="{{ brand }}" {% if app.request.get('brand', '') == brand %}selected{% endif %}>{{ brand }}</option>
  70.                       {% endfor %}
  71.                     </select>
  72.                   </div>
  73.                 </div>
  74.                 <div class="col-md-12">
  75.                   <div class="mb-1">
  76.                     <label class="form-label">Наличие у поставщика</label>
  77.                     <div class="form-check">
  78.                       <input class="form-check-input" type="radio" name="availability" value="" {% if app.request.get('availability', '') == '' %}checked{% endif %} id="filter_availability_all">
  79.                       <label class="form-check-label" for="filter_availability_all">Все товары</label>
  80.                     </div>
  81.                     <div class="form-check">
  82.                       <input class="form-check-input" type="radio" name="availability" value="1" {% if app.request.get('availability', '') == '1' %}checked{% endif %} id="filter_availability_1">
  83.                       <label class="form-check-label" for="filter_availability_1">Только в наличии</label>
  84.                     </div>
  85.                     <div class="form-check">
  86.                       <input class="form-check-input" type="radio" name="availability" value="0" {% if app.request.get('availability', '') == '0' %}checked{% endif %} id="filter_availability_0">
  87.                       <label class="form-check-label" for="filter_availability_0">Только не в наличии</label>
  88.                     </div>
  89.                   </div>
  90.                 </div>
  91.                 <div class="col-md-12">
  92.                   <div class="mb-2">
  93.                     <label class="form-label">Привязка к сайту</label>
  94.                     <div class="form-check">
  95.                       <input class="form-check-input" type="radio" name="connected" value="" {% if app.request.get('connected', '') == '' %}checked{% endif %} id="filter_connected_all">
  96.                       <label class="form-check-label" for="filter_connected_all">Все товары</label>
  97.                     </div>
  98.                     <div class="form-check">
  99.                       <input class="form-check-input" type="radio" name="connected" value="1" {% if app.request.get('connected', '') == '1' %}checked{% endif %} id="filter_connected_1">
  100.                       <label class="form-check-label" for="filter_connected_1">Только привязанные</label>
  101.                     </div>
  102.                     <div class="form-check">
  103.                       <input class="form-check-input" type="radio" name="connected" value="0" {% if app.request.get('connected', '') == '0' %}checked{% endif %} id="filter_connected_0">
  104.                       <label class="form-check-label" for="filter_connected_0">Только не привязанные</label>
  105.                     </div>
  106.                   </div>
  107.                 </div>
  108.                 <div class="col-md-12">
  109.                   <div class="d-grid gap-2">
  110.                     <button type="submit" class="btn btn-sm btn-primary">Применить</button>
  111.                   </div>
  112.                 </div>
  113.               </div>
  114.             </form>
  115.           </div>
  116.         </div>
  117.         <div class="card mt-2">
  118.           <div class="card-header">Категории</div>
  119.           <div class="card-body p-0">
  120.             <div class="list-group list-group-flush">
  121.               {% if chosenCategory is not null %}
  122.                 {% set url = path(app.request.attributes.get('_route'),
  123.                   app.request.query|merge({c: chosenCategory.parent.id|default(null)})) %}
  124.                 <a href="{{ url }}" class="list-group-item list-group-item-action active" aria-current="true"><-- Назад</a>
  125.               {% endif %}
  126.               {% for item in children %}
  127.                 {% set url = path(app.request.attributes.get('_route'),
  128.                   app.request.query|merge({c: item.id})) %}
  129.                 <a href="{{ url }}" class="list-group-item list-group-item-action">{{ item.name }}</a>
  130.               {% endfor %}
  131.             </div>
  132.           </div>
  133.         </div>
  134.       </div>
  135.       <div class="col-md-10">
  136.         <div class="card">
  137.           <div class="card-header">Товары ({{ pagination.totalItemCount }} шт.)</div>
  138.           <div class="card-body">
  139.             <div class="mb-2">
  140.               {% for provider in providers %}
  141.                 {% if provider != selectedProvider %}
  142.                   <a class="btn btn-sm btn-outline-primary" href="{{ path('product_list', {provider: provider.id}) }}">{{ provider.name }}</a>
  143.                 {% else %}
  144.                   <a class="btn btn-sm btn-primary" href="{{ path('product_list') }}">{{ provider.name }}</a>
  145.                 {% endif %}
  146.               {% endfor %}
  147.             </div>
  148.             <table class="table table-sm table-bordered table-catalog">
  149.               <thead>
  150.                 <tr>
  151.                   <th>
  152.                     <input type="checkbox" class="js-select-all">
  153.                   </th>
  154.                   <th>ID</th>
  155.                   <th>Наименование</th>
  156.                   <th>Партномер</th>
  157.                   <th>Всего поставщиков</th>
  158.                   <th colspan="3">Оптимальный поставщик</th>
  159.                   <th colspan="3">Привязка к сайту</th>
  160.                 </tr>
  161.                 <tr>
  162.                   <th></th>
  163.                   <th></th>
  164.                   <th></th>
  165.                   <th></th>
  166.                   <th></th>
  167.                   <th>Поставщик</th>
  168.                   <th>Цена</th>
  169.                   <th>Количество</th>
  170.                   <th>ID товара</th>
  171.                   <th>ID варианта</th>
  172.                   <th>SKU</th>
  173.                 </tr>
  174.               </thead>
  175.               <tbody>
  176.                 {% for product in pagination %}
  177.                   {% set availability = priceCalculator.getOptimalAvailability(product) %}
  178.                   <tr>
  179.                     <td>
  180.                       <input type="checkbox" data-id="{{ product.id }}" {% if product.id in app.session.get('selected', []) %}checked{% endif %} class="js-select-product">
  181.                     </td>
  182.                     <td>{{ product.id }}</td>
  183.                     <td><a href="{{ path('product_view', {id: product.id}) }}">{{ product.name }}</a></td>
  184.                     <td>{{ (product.availabilities|first).providerPartnumber|default('') }}</td>
  185.                     <td>{{ product.availabilities|length }}</td>
  186.                     {% if availability is not null %}
  187.                       <td>{{ availability.provider.name }}</td>
  188.                       <td>{{ priceCalculator.calculatePriceForAvailability(availability) }}</td>
  189.                       <td>{{ availability.stock }}</td>
  190.                     {% else %}
  191.                       <td colspan="3" class="text-center">- - -</td>
  192.                     {% endif %}
  193.                     {% if product.connection is not null %}
  194.                       <td>{{ product.connection.insalesProductId }}</td>
  195.                       <td>{{ product.connection.insalesVariantId }}</td>
  196.                       <td>{{ product.connection.insalesSku }}</td>
  197.                     {% else %}
  198.                       <td colspan="3" class="text-center">- - -</td>
  199.                     {% endif %}
  200.                   </tr>
  201.                 {% endfor %}
  202.               </tbody>
  203.             </table>
  204.             <div class="navigation">
  205.               {{ knp_pagination_render(pagination) }}
  206.             </div>
  207.           </div>
  208.         </div>
  209.       </div>
  210.     </div>
  211.   </div>
  212.   <div class="selection-wrapper">
  213.     Выбрано: <span id="selected-count">{{ app.session.get('selected', [])|length }}</span> шт.
  214.     <hr class="m-0 my-2">
  215.     <div class="row">
  216.       <div class="col-md-12">
  217.         <div class="d-grid gap-2">
  218.           <a href="#" class="btn btn-sm btn-block btn-danger js-selected-flush my-1">Очистить</a>
  219.         </div>
  220.       </div>
  221.       <div class="col-md-12">
  222.         <div class="d-grid gap-2">
  223.           <a href="{{ path('product_export_selected') }}" class="btn btn-sm btn-block btn-primary my-1">Экспорт по оптим. поставщикам</a>
  224.         </div>
  225.       </div>
  226.       {% if selectedProvider is defined and selectedProvider is not null %}
  227.         <div class="col-md-12">
  228.           <div class="d-grid gap-2">
  229.             <a href="{{ path('product_export_selected', {provider_id: selectedProvider.id}) }}" class="btn btn-sm btn-block btn-primary my-1">Экспорт по {{ selectedProvider.name }}</a>
  230.           </div>
  231.         </div>
  232.       {% endif %}
  233.     </div>
  234.   </div>
  235. {% endblock %}
  236. {% block javascripts %}
  237.   {{ parent() }}
  238.   <script>
  239.     (function() {
  240.       const $selectAllProducts = $('.js-select-all');
  241.       const $selectProduct = $('.js-select-product');
  242.       const $selectedFlush = $('.js-selected-flush');
  243.       const $selectedCount = $('#selected-count');
  244.       $selectAllProducts.on('click', function() {
  245.         $selectProduct.each(function() {
  246.           $(this).prop('checked', !$(this).prop('checked')).trigger('change');
  247.         });
  248.       });
  249.       $selectedFlush.on('click', function () {
  250.         $.get('/api/productSelection/flush', function(res) {
  251.           $selectedCount.text(0);
  252.           $selectProduct.each(function() {
  253.             $(this).prop('checked', false);
  254.           });
  255.         });
  256.       });
  257.       $selectProduct.on('change', function () {
  258.         const $el = $(this);
  259.         const id = $el.attr('data-id');
  260.         $.get('/api/productSelection/changeState', {id: $el.attr('data-id')}, function(response) {
  261.           $selectedCount.text(response.COUNT);
  262.         });
  263.       });
  264.     })();
  265.   </script>
  266. {% endblock %}