--- /dev/null
- <div class="row">
- <div class="d-flex justify-content-center">
- <button class="btn btn-light" type="button" data-bs-toggle="collapse"
- data-bs-target="#filter-container"
- aria-expanded="true">
- <span data-bs-collapse-icon="open">▲</span>
- <span data-bs-collapse-icon="closed">▼</span>
- </button>
- </div>
+<?php
+
+use kartik\grid\GridView;
+use kartik\select2\Select2;
+use yii\helpers\ArrayHelper;
+use yii\helpers\Html;
+use yii_app\helpers\DateHelper;
+use yii_app\records\Admin;
+use yii_app\records\AdminGroup;
+use yii_app\records\StoreCityList;
+use yii_app\records\StoreDynamic;
+use yii_app\records\StoreType;
+use sjaakp\bandoneon\Bandoneon;
+use yii\jui\Accordion;
+
+/* @var $categories \yii_app\records\Products1cNomenclature */
+
+
+use yii\data\ArrayDataProvider;
+
+$tooltipText = "Оффлайн: 50 Флаумак (off-line): 20 Флаумак (on-line): 10 Флаумак (market): 10 Изумительная (off-line): 30 Списания: 20"; ?>
+
+<h1 class="ms-3 mb-4"><?= Html::encode("Автопланограмма") ?></h1>
+<div class="autopolnogramma p-3 px-4">
+ <div class="filters">
+ <div class="row">
+ </div>
+ <div class="collapse show" id="filter-container">
+ <div class="row">
+ <div class="col-md d-flex">
+ <?= Select2::widget([
+ 'name' => 'year-filter',
+ 'data' => array_combine(range(date('Y') - 5, date('Y') + 5), range(date('Y') - 5, date('Y') + 5)),
+ 'options' => ['placeholder' => 'Год', 'id' => 'year'],
+ 'pluginOptions' => ['allowClear' => true],
+ ]) ?>
+ </div>
+ <div class="col-md d-flex">
+ <?= Select2::widget([
+ 'name' => 'city-filter',
+ 'data' => ArrayHelper::map(StoreCityList::findAll(['type' => StoreCityList::TYPE_CITY]), 'id', 'name'),
+ 'options' => ['placeholder' => 'Город', 'id' => 'city'],
+ 'pluginOptions' => ['allowClear' => true],
+ ]) ?>
+ </div>
+ <div class="col-md d-flex">
+ <?= Select2::widget([
+ 'name' => 'store-type-filter',
+ 'data' => ArrayHelper::map(StoreType::find()->orderBy('sequence_number')->all(), 'id', 'name'),
+ 'options' => ['placeholder' => 'Тип магазина', 'id' => 'store-type', 'style' => 'width: 110%;'],
+ 'pluginOptions' => ['allowClear' => true],
+ ]) ?>
+ </div>
+ <div class="col-md d-flex">
+ <?= Select2::widget([
+ 'name' => 'territorial-manager-filter',
+ 'data' => ArrayHelper::map(
+ array_merge(
+ Admin::findAll(['group_id' => AdminGroup::GROUP_BUSH_DIRECTOR]),
+ Admin::findAll(['id' => StoreDynamic::find()->andWhere(['category' => 3, 'active' => 1])->select('value_int')->column()])
+ ),
+ 'id',
+ 'name',
+ ),
+ 'options' => ['placeholder' => 'Тер. управляющий', 'id' => 'territorial-manger'],
+ 'pluginOptions' => ['allowClear' => true],
+ ]) ?>
+ </div>
+ <div class="col-md d-flex">
+ <?= Select2::widget([
+ 'name' => 'polnogramma-type-filter',
+ 'data' => ['min' => 'min', 'max' => 'max'],
+ 'options' => ['placeholder' => 'Тип п-ма', 'id' => 'polnogramma-type'],
+ 'pluginOptions' => ['allowClear' => true],
+ ]) ?>
+ </div>
+ <div class="col-md d-flex">
+ <?= Html::submitButton('Применить', ['class' => 'btn btn-apply btn-primary', 'style' => 'width:100%']); ?>
+ </div>
+ </div>
+ <div class="row py-3">
+ <div class="col-md d-flex">
+ <?= Select2::widget([
+ 'name' => 'week-filter',
+ 'data' => ['1' => '1', '2' => '2'],
+ 'options' => ['placeholder' => 'Неделя', 'id' => 'week'],
+ 'pluginOptions' => ['allowClear' => true],
+ ]) ?>
+ </div>
+ <div class="col-md d-flex">
+ <?= Select2::widget([
+ 'name' => 'region-filter',
+ 'data' => ArrayHelper::map(StoreCityList::findAll(['type' => StoreCityList::TYPE_REGION]), 'id', 'name'),
+ 'options' => ['placeholder' => 'Регион', 'id' => 'region'],
+ 'pluginOptions' => ['allowClear' => true],
+ ]) ?>
+ </div>
+ <div class="col-md d-flex">
+ </div>
+ <div class="col-md d-flex">
+ <?= Select2::widget([
+ 'name' => 'bush_chef_florist',
+ 'value' => null,
+ 'data' => ArrayHelper::map(Admin::findAll(['group_id' => AdminGroup::GROUP_BUSH_CHEF_FLORIST]), 'id', 'name'),
+ 'options' => [
+ 'placeholder' => 'Кустовой шеф-флорист',
+ 'class' => 'form-select',
+ 'id' => 'bush_chef_florist',
+ ],
+ 'pluginOptions' => [
+ 'allowClear' => true,
+ ],
+ ]); ?>
+ </div>
+ <div class="col-md d-flex">
+ </div>
+ <div class="col-md d-flex"></div>
+ </div>
+ <div class="row">
+ <div class="col-md d-flex">
+ <?= Html::label('Месяца-месяцы') ?>
+ </div>
+ <div class="col-md d-flex">
+ <?= Select2::widget([
+ 'name' => 'district-filter',
+ 'data' => ArrayHelper::map(StoreCityList::findAll(['type' => StoreCityList::TYPE_DISTRICT]), 'id', 'name'),
+ 'options' => ['placeholder' => 'Район', 'id' => 'district'],
+ 'pluginOptions' => ['allowClear' => true],
+ ]) ?>
+ </div>
+ <div class="col-md d-flex"></div>
+ <div class="col-md d-flex"></div>
+ <div class="col-md d-flex"></div>
+ <div class="col-md d-flex">
+ <?= Html::button('Сохранить', ['class' => 'btn btn-success btn-save', 'style' => 'width:100%']); ?>
+ </div>
+ </div>
- <div class="buttons d-flex">
- <?= Html::a('Auto', '#', ['class' => 'btn btn-success ml-auto']) ?>
- <?= Html::a('Corrected', '#', ['class' => 'btn btn-success ml-auto']) ?>
++ </div>
++ <div class="row">
++ <div class="d-flex justify-content-center">
++ <button class="btn btn-light" type="button" data-bs-toggle="collapse"
++ data-bs-target="#filter-container"
++ aria-expanded="true">
++ <span data-bs-collapse-icon="open">▲</span>
++ <span data-bs-collapse-icon="closed">▼</span>
++ </button>
+ </div>
+ </div>
+ </div>
+ <div class="table-wrapper">
+ <table class="table">
+ <thead>
+ <tr class="head">
+ <th scope="col" style="text-align: left !important;">
+ <?= Html::label("год: 2025 неделя: 05") ?><br>
+ <?= Html::label("январь - февраль") ?><br>
+ <?= Html::label("Тип п-ма:") ?><br>
+ <?= Html::label("Город:") ?><br>
+ <?= Html::label("Регион:") ?><br>
+ <?= Html::label("Район:") ?><br>
+ <?= Html::label("Тип магазина:") ?><br>
+ <?= Html::label("Тер. Уп.:") ?><br>
+ <?= Html::label("КШФ:") ?><br>
- let isVisible = this.parentElement.nextElementSibling?.style.display === "table-row";
++ <div class="buttons d-flex justify-content-end">
++ <?= Html::a('Auto', '#', ['class' => 'btn btn-success ms-1']) ?>
++ <?= Html::a('Corrected', '#', ['class' => 'btn btn-success ms-1']) ?>
+ </div>
+ </th>
+
+ <?php foreach ($stores as $store) { ?>
+ <th scope="col" class="fixed-column">
+ <?= Html::label($store, null, [
+ 'style' => 'writing-mode: sideways-lr; text-align: center; white-space: nowrap;
+ font-weight: bold; transform-origin: left bottom; padding-right: 7%;'
+ ]) ?>
+ </th>
+ <?php } ?>
+ </tr>
+ </thead>
+ <tbody>
+ <?php
+ $groupedCategories = [];
+
+ // Группируем данные по категориям и подкатегориям
+ foreach ($categories as $item) {
+ $groupedCategories[$item['category']][$item['subcategory']] = $item['products'];
+ }
+
+ foreach ($groupedCategories as $category => $subcategories): ?>
+ <tr>
+ <td class="category">
+ <a class="list-group-item list-group-item-action">
+ <?= Html::encode($category) ?> ▲
+ </a>
+ </td>
+ </tr>
+
+ <?php foreach ($subcategories as $subcategory => $products): ?>
+ <tr>
+ <td style="position: relative; display: flex; justify-content: flex-end;" class="subcategory">
+ <a class="list-group-item list-group-item-action" style="width: 95%;">
+ <?= Html::encode($subcategory) ?> ▶
+ </a>
+ </td>
+ </tr>
+ <?php
+ $products = is_string($products) ? json_decode($products, true) : $products;
+ ?>
+ <?php foreach ($products as $product): ?>
+ <tr>
+ <td style="position: relative; display: flex; justify-content: flex-end;">
+ <a class="list-group-item list-group-item-action" style="width: 90%;">
+ <?= Html::encode($product) ?>
+ </a>
+ </td>
+
+ <?php foreach ($stores as $store): ?>
+ <td class="items">
+ <div style="display: flex; align-items: center;">
+ <?= Html::input('text', '', 50, [
+ 'class' => 'btn btn-primary input',
+ 'data-bs-toggle' => 'tooltip',
+ 'data-bs-placement' => 'top',
+ 'title' => $tooltipText,
+ ]) ?>
+ <button style="border: none; background: transparent; cursor: pointer; margin-left: 5px;">
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20 11v5a1 1 0 0 1-2 0v-4H7.414l1.293 1.293a1 1 0 0 1-1.414 1.414l-3-3a1 1 0 0 1 0-1.416l3-3a1 1 0 1 1 1.414 1.416L7.414 10H19a1 1 0 0 1 1 1z"
+ fill="grey" stroke="none"/>
+ </svg>
+ </button>
+ </div>
+ </td>
+ <?php endforeach; ?>
+ </tr>
+ <?php endforeach; ?>
+ <?php endforeach; ?>
+ <?php endforeach; ?>
+ </tbody>
+ </table>
+ </div>
+</div>
+<script>
+ document.addEventListener("DOMContentLoaded", function () {
+ // Изначально скрываем все строки, кроме .category и .head
+ document.querySelectorAll("tr").forEach(row => {
+ if (!row.querySelector(".category") && !row.classList.contains("head")) {
+ row.style.display = "none";
+ }
+ });
+
+ // Обработчик кликов для категорий
+ document.querySelectorAll(".category").forEach(category => {
+ category.addEventListener("click", function () {
- // Закрываем все вложенные элементы (subcategory + items)
+ let nextRow = this.parentElement.nextElementSibling;
++ let isVisible = nextRow?.style.display === "table-row";
+
- // Если категория закрывалась, то открываем только подкатегории
++ // Закрываем все элементы внутри категории
+ while (nextRow && !nextRow.querySelector(".category")) {
+ nextRow.style.display = "none";
+ nextRow = nextRow.nextElementSibling;
+ }
+
- let activeSubcategory = null; // Текущая открытая подкатегория
-
++ // Если категория была закрыта — открываем подкатегории
+ if (!isVisible) {
+ nextRow = this.parentElement.nextElementSibling;
+ while (nextRow && !nextRow.querySelector(".category")) {
+ if (nextRow.querySelector(".subcategory")) {
+ nextRow.style.display = "table-row";
+ }
+ nextRow = nextRow.nextElementSibling;
+ }
+ }
+ });
+ });
+
- subcategory.addEventListener("click", function () {
- let isOpening = activeSubcategory !== this;
+ // Обработчик кликов для подкатегорий
+ document.querySelectorAll(".subcategory").forEach(subcategory => {
- // Закрываем текущую открытую подкатегорию и её items
- if (activeSubcategory) {
- let prevRow = activeSubcategory.parentElement.nextElementSibling;
- while (prevRow && !prevRow.querySelector(".subcategory") && !prevRow.querySelector(".category")) {
- prevRow.style.display = "none";
- prevRow = prevRow.nextElementSibling;
- }
- }
++ subcategory.addEventListener("click", function (event) {
++ event.stopPropagation(); // Чтобы клик по подкатегории не закрывал категорию
+
- // Если открываем новую, показываем её items
- if (isOpening) {
- let nextRow = this.parentElement.nextElementSibling;
- while (nextRow && !nextRow.querySelector(".subcategory") && !nextRow.querySelector(".category")) {
- nextRow.style.display = "table-row";
- nextRow = nextRow.nextElementSibling;
- }
- activeSubcategory = this;
- } else {
- activeSubcategory = null;
++ let nextRow = this.parentElement.nextElementSibling;
++ let isVisible = nextRow?.style.display === "table-row";
+
++ // Переключаем видимость только айтемов внутри этой подкатегории
++ while (nextRow && !nextRow.querySelector(".subcategory") && !nextRow.querySelector(".category")) {
++ nextRow.style.display = isVisible ? "none" : "table-row";
++ nextRow = nextRow.nextElementSibling;
+ }
+ });
+ });
+ });
+</script>
+
+<style>
+ /* Стили для таблицы */
+ .table {
+ width: 100%;
+ table-layout: fixed; /* Это позволяет фиксировать ширину колонок */
+ overflow-x: auto; /* Это позволяет прокручивать таблицу по горизонтали */
+ border-collapse: collapse; /* Чтобы не было промежутков между ячейками */
+ }
+
+ /* Первая колонка будет фиксированной */
+ .fixed-column {
+ width: 170px; /* Устанавливаем фиксированную ширину для первой колонки */
+ white-space: nowrap; /* Запрещаем перенос текста в ячейке */
+ border-right: 1px solid #ddd; /* Вертикальная линия между колонками */
+ }
+
+ /* Для остальных колонок можно установить фиксированную ширину, если нужно */
+ th, td {
+ width: 300px; /* Пример для остальных колонок */
+ text-align: center; /* Центрируем текст */
+ padding: 10px; /* Немного отступов для улучшения внешнего вида */
+ border-right: 1px solid #ddd; /* Вертикальная линия между колонками */
+ }
+
+ .items .input {
+ width: 100%;
+ }
+
+ .table-wrapper {
+ overflow-x: auto;
+ max-width: 100%;
+ position: relative;
+ }
+
+ .fixed-column {
+ position: sticky;
+ left: 0;
+ background: white;
+ z-index: 2;
+ border-right: 2px solid #ddd;
+ }
+</style>