|
|
@@ -7,20 +7,46 @@
|
|
|
<button type="button" class="btn btn-outline-secondary btn-sm w-100" id="sort-by-desc-{{$id}}"><i class="bi bi-arrow-down"></i>DESC</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <form class="dropdown-filter_{{$id}} mb-2">
|
|
|
- <div class="d-flex align-items-center mb-2">
|
|
|
- <input class="form-control me-2" id="search_{{$id}}" placeholder="Поиск">
|
|
|
- <button type="button" class="btn btn-outline-secondary btn-sm" id="sort-filter-{{$id}}" title="А-Я / Я-А">
|
|
|
- <i class="bi bi-sort-alpha-down" id="sort-filter-icon-{{$id}}"></i>
|
|
|
- </button>
|
|
|
+ @if($type === 'ranges')
|
|
|
+ @php
|
|
|
+ $inputType = $type === 'dates' ? 'date' : 'number';
|
|
|
+ $fromKey = $id . '_from';
|
|
|
+ $toKey = $id . '_to';
|
|
|
+ @endphp
|
|
|
+ <form class="dropdown-filter_{{$id}} mb-2">
|
|
|
+ <div class="mb-2">
|
|
|
+ <label class="form-label mb-0 small">От:</label>
|
|
|
+ <input type="{{ $inputType }}" class="form-control form-control-sm" id="range_from_{{$id}}"
|
|
|
+ value="{{ request()->filters[$fromKey] ?? '' }}"
|
|
|
+ @if($data) min="{{ $data['min'] }}" max="{{ $data['max'] }}" @endif>
|
|
|
+ </div>
|
|
|
+ <div class="mb-2">
|
|
|
+ <label class="form-label mb-0 small">До:</label>
|
|
|
+ <input type="{{ $inputType }}" class="form-control form-control-sm" id="range_to_{{$id}}"
|
|
|
+ value="{{ request()->filters[$toKey] ?? '' }}"
|
|
|
+ @if($data) min="{{ $data['min'] }}" max="{{ $data['max'] }}" @endif>
|
|
|
+ </div>
|
|
|
+ </form>
|
|
|
+ <div class="modal-footer d-flex justify-content-between" id="modal-footer_{{$id}}">
|
|
|
+ <button type="button" class="btn btn-outline-secondary btn-sm w-50 border-0" id="reset-filters_{{$id}}">Отмена</button>
|
|
|
+ <button type="button" class="btn btn-primary btn-sm w-50" id="accept-filter_{{$id}}">Применить</button>
|
|
|
</div>
|
|
|
- <div class="ps-1" id="filter-list-{{$id}}" style="max-height: 200px; overflow-y: scroll;">
|
|
|
+ @else
|
|
|
+ <form class="dropdown-filter_{{$id}} mb-2">
|
|
|
+ <div class="d-flex align-items-center mb-2">
|
|
|
+ <input class="form-control me-2" id="search_{{$id}}" placeholder="Поиск">
|
|
|
+ <button type="button" class="btn btn-outline-secondary btn-sm" id="sort-filter-{{$id}}" title="А-Я / Я-А">
|
|
|
+ <i class="bi bi-sort-alpha-down" id="sort-filter-icon-{{$id}}"></i>
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ <div class="ps-1" id="filter-list-{{$id}}" style="max-height: 200px; overflow-y: scroll;">
|
|
|
+ </div>
|
|
|
+ </form>
|
|
|
+ <div class="modal-footer d-flex justify-content-between" id="modal-footer_{{$id}}">
|
|
|
+ <button type="button" class="btn btn-outline-secondary reset-filters_{{$id}} btn-sm w-50 border-0" id="reset-filters_{{$id}}">Отмена</button>
|
|
|
+ <button type="button" class="btn btn-primary accept-filter_{{$id}} btn-sm w-50" id="accept-filter_{{$id}}">Применить</button>
|
|
|
</div>
|
|
|
- </form>
|
|
|
- <div class="modal-footer d-flex justify-content-between" id="modal-footer_{{$id}}">
|
|
|
- <button type="button" class="btn btn-outline-secondary reset-filters_{{$id}} btn-sm w-50 border-0" id="reset-filters_{{$id}}">Отмена</button>
|
|
|
- <button type="button" class="btn btn-primary accept-filter_{{$id}} btn-sm w-50" id="accept-filter_{{$id}}">Применить</button>
|
|
|
- </div>
|
|
|
+ @endif
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
@@ -44,109 +70,139 @@
|
|
|
}
|
|
|
|
|
|
waitForJQuery(async function () {
|
|
|
- const $container = $("#filter-list-{{$id}}");
|
|
|
- const $searchInput = $("#search_{{$id}}");
|
|
|
- const $sortBtn = $("#sort-filter-{{$id}}");
|
|
|
- const $sortIcon = $("#sort-filter-icon-{{$id}}");
|
|
|
- const urlParams = new URL(document.location.href);
|
|
|
- const existingFilter = urlParams.searchParams.get(`filters[{{$id}}]`);
|
|
|
- const selectedValues = existingFilter ? existingFilter.split("||") : [];
|
|
|
-
|
|
|
- let filterData = [];
|
|
|
- let sortAsc = true;
|
|
|
-
|
|
|
- function renderFilterList(data) {
|
|
|
- const html = data.map(item => `
|
|
|
- <div class="form-check">
|
|
|
- <input class="form-check-input" type="checkbox" value="${escapeHtml(item)}" id="flexCheckDefault_{{$id}}_${escapeHtml(item)}">
|
|
|
- <label class="form-check-label" for="flexCheckDefault_{{$id}}_${escapeHtml(item)}">
|
|
|
- ${escapeHtml(item)}
|
|
|
- </label>
|
|
|
- </div>
|
|
|
- `).join('');
|
|
|
- $container.html(html);
|
|
|
-
|
|
|
- selectedValues.forEach(value => {
|
|
|
- $container.find(`.form-check-input[value="${$.escapeSelector(value)}"]`).prop("checked", true);
|
|
|
+ @if($type === 'ranges')
|
|
|
+ $("#accept-filter_{{$id}}").on("click", function () {
|
|
|
+ let currentUrl = new URL(document.location.href);
|
|
|
+ const fromVal = $("#range_from_{{$id}}").val();
|
|
|
+ const toVal = $("#range_to_{{$id}}").val();
|
|
|
+
|
|
|
+ if (fromVal) {
|
|
|
+ currentUrl.searchParams.set('filters[{{$id}}_from]', fromVal);
|
|
|
+ } else {
|
|
|
+ currentUrl.searchParams.delete('filters[{{$id}}_from]');
|
|
|
+ }
|
|
|
+ if (toVal) {
|
|
|
+ currentUrl.searchParams.set('filters[{{$id}}_to]', toVal);
|
|
|
+ } else {
|
|
|
+ currentUrl.searchParams.delete('filters[{{$id}}_to]');
|
|
|
+ }
|
|
|
+
|
|
|
+ currentUrl.searchParams.delete('page');
|
|
|
+ document.location.href = currentUrl.href;
|
|
|
});
|
|
|
- }
|
|
|
|
|
|
- function sortData(asc) {
|
|
|
- const collator = new Intl.Collator('ru', { sensitivity: 'base', numeric: true });
|
|
|
- return [...filterData].sort((a, b) => {
|
|
|
- if (a === '-пусто-') return -1;
|
|
|
- if (b === '-пусто-') return 1;
|
|
|
- return asc ? collator.compare(a, b) : collator.compare(b, a);
|
|
|
+ $("#reset-filters_{{$id}}").on("click", function () {
|
|
|
+ let currentUrl = new URL(document.location.href);
|
|
|
+ currentUrl.searchParams.delete('filters[{{$id}}_from]');
|
|
|
+ currentUrl.searchParams.delete('filters[{{$id}}_to]');
|
|
|
+ currentUrl.searchParams.delete('page');
|
|
|
+ document.location.href = currentUrl.href;
|
|
|
});
|
|
|
- }
|
|
|
+ @else
|
|
|
+ const $container = $("#filter-list-{{$id}}");
|
|
|
+ const $searchInput = $("#search_{{$id}}");
|
|
|
+ const $sortBtn = $("#sort-filter-{{$id}}");
|
|
|
+ const $sortIcon = $("#sort-filter-icon-{{$id}}");
|
|
|
+ const urlParams = new URL(document.location.href);
|
|
|
+ const existingFilter = urlParams.searchParams.get(`filters[{{$id}}]`);
|
|
|
+ const selectedValues = existingFilter ? existingFilter.split("||") : [];
|
|
|
+
|
|
|
+ let filterData = [];
|
|
|
+ let sortAsc = true;
|
|
|
+
|
|
|
+ function renderFilterList(data) {
|
|
|
+ const html = data.map(item => `
|
|
|
+ <div class="form-check">
|
|
|
+ <input class="form-check-input" type="checkbox" value="${escapeHtml(item)}" id="flexCheckDefault_{{$id}}_${escapeHtml(item)}">
|
|
|
+ <label class="form-check-label" for="flexCheckDefault_{{$id}}_${escapeHtml(item)}">
|
|
|
+ ${escapeHtml(item)}
|
|
|
+ </label>
|
|
|
+ </div>
|
|
|
+ `).join('');
|
|
|
+ $container.html(html);
|
|
|
+
|
|
|
+ selectedValues.forEach(value => {
|
|
|
+ $container.find(`.form-check-input[value="${$.escapeSelector(value)}"]`).prop("checked", true);
|
|
|
+ });
|
|
|
+ }
|
|
|
|
|
|
- try {
|
|
|
- const response = await fetch(`{!! route('getFilters', ['column' => $id, 'table' => $table]) !!}`);
|
|
|
- const data = await response.json();
|
|
|
+ function sortData(asc) {
|
|
|
+ const collator = new Intl.Collator('ru', { sensitivity: 'base', numeric: true });
|
|
|
+ return [...filterData].sort((a, b) => {
|
|
|
+ if (a === '-пусто-') return -1;
|
|
|
+ if (b === '-пусто-') return 1;
|
|
|
+ return asc ? collator.compare(a, b) : collator.compare(b, a);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ const response = await fetch(`{!! route('getFilters', ['column' => $id, 'table' => $table]) !!}`);
|
|
|
+ const data = await response.json();
|
|
|
+
|
|
|
+ if (Array.isArray(data) && data.length) {
|
|
|
+ if(data[0] === null) data[0] = '-пусто-';
|
|
|
+ filterData = data;
|
|
|
+ const sortedData = sortData(sortAsc);
|
|
|
+ renderFilterList(sortedData);
|
|
|
+ } else {
|
|
|
+ $("#search_{{$id}}").parent().hide();
|
|
|
+ $("#modal-footer_{{$id}}").hide();
|
|
|
+ $container.html('<div class="text-muted">Нет данных</div>');
|
|
|
+ }
|
|
|
|
|
|
- if (Array.isArray(data) && data.length) {
|
|
|
- if(data[0] === null) data[0] = '-пусто-';
|
|
|
- filterData = data;
|
|
|
+ } catch (error) {
|
|
|
+ console.error("Ошибка при загрузке фильтров:", error);
|
|
|
+ $container.html('<div class="text-danger">Ошибка загрузки</div>');
|
|
|
+ }
|
|
|
+
|
|
|
+ $sortBtn.on("click", function (e) {
|
|
|
+ e.preventDefault();
|
|
|
+ sortAsc = !sortAsc;
|
|
|
+ $sortIcon.removeClass("bi-sort-alpha-down bi-sort-alpha-up")
|
|
|
+ .addClass(sortAsc ? "bi-sort-alpha-down" : "bi-sort-alpha-up");
|
|
|
const sortedData = sortData(sortAsc);
|
|
|
renderFilterList(sortedData);
|
|
|
- } else {
|
|
|
- $("#search_{{$id}}").parent().hide();
|
|
|
- $("#modal-footer_{{$id}}").hide();
|
|
|
- $container.html('<div class="text-muted">Нет данных</div>');
|
|
|
- }
|
|
|
+ });
|
|
|
|
|
|
- } catch (error) {
|
|
|
- console.error("Ошибка при загрузке фильтров:", error);
|
|
|
- $container.html('<div class="text-danger">Ошибка загрузки</div>');
|
|
|
- }
|
|
|
+ $("#accept-filter_{{$id}}").on("click", function () {
|
|
|
+ const checkedValues = $container.find(".form-check-input:checked")
|
|
|
+ .map(function () {
|
|
|
+ return $(this).val();
|
|
|
+ })
|
|
|
+ .get();
|
|
|
|
|
|
- $sortBtn.on("click", function (e) {
|
|
|
- e.preventDefault();
|
|
|
- sortAsc = !sortAsc;
|
|
|
- $sortIcon.removeClass("bi-sort-alpha-down bi-sort-alpha-up")
|
|
|
- .addClass(sortAsc ? "bi-sort-alpha-down" : "bi-sort-alpha-up");
|
|
|
- const sortedData = sortData(sortAsc);
|
|
|
- renderFilterList(sortedData);
|
|
|
- });
|
|
|
+ let currentUrl = new URL(document.location.href);
|
|
|
+ if(!checkedValues.join('||')) {
|
|
|
+ currentUrl.searchParams.delete('filters[{{$id}}]');
|
|
|
+ } else {
|
|
|
+ currentUrl.searchParams.set('filters[{{$id}}]', checkedValues.join('||'));
|
|
|
+ }
|
|
|
|
|
|
- $("#accept-filter_{{$id}}").on("click", function () {
|
|
|
- const checkedValues = $container.find(".form-check-input:checked")
|
|
|
- .map(function () {
|
|
|
- return $(this).val();
|
|
|
- })
|
|
|
- .get();
|
|
|
+ currentUrl.searchParams.delete('page');
|
|
|
+ document.location.href = currentUrl.href;
|
|
|
+ });
|
|
|
|
|
|
- let currentUrl = new URL(document.location.href);
|
|
|
- if(!checkedValues.join('||')) {
|
|
|
+ $("#reset-filters_{{$id}}").on("click", function () {
|
|
|
+ let currentUrl = new URL(document.location.href);
|
|
|
currentUrl.searchParams.delete('filters[{{$id}}]');
|
|
|
- } else {
|
|
|
- currentUrl.searchParams.set('filters[{{$id}}]', checkedValues.join('||'));
|
|
|
- }
|
|
|
-
|
|
|
- currentUrl.searchParams.delete('page');
|
|
|
- document.location.href = currentUrl.href;
|
|
|
- });
|
|
|
-
|
|
|
- $("#reset-filters_{{$id}}").on("click", function () {
|
|
|
- let currentUrl = new URL(document.location.href);
|
|
|
- currentUrl.searchParams.delete('filters[{{$id}}]');
|
|
|
- document.location.href = currentUrl.href;
|
|
|
- });
|
|
|
+ document.location.href = currentUrl.href;
|
|
|
+ });
|
|
|
|
|
|
- $searchInput.on("input", function () {
|
|
|
- const query = $(this).val().toLowerCase();
|
|
|
+ $searchInput.on("input", function () {
|
|
|
+ const query = $(this).val().toLowerCase();
|
|
|
|
|
|
- $container.find(".form-check").each(function () {
|
|
|
- const labelText = $(this).find("label").text().toLowerCase();
|
|
|
+ $container.find(".form-check").each(function () {
|
|
|
+ const labelText = $(this).find("label").text().toLowerCase();
|
|
|
|
|
|
- if (labelText.includes(query)) {
|
|
|
- $(this).show();
|
|
|
- } else {
|
|
|
- $(this).hide();
|
|
|
- $(this).find(".form-check-input").prop("checked", false);
|
|
|
- }
|
|
|
+ if (labelText.includes(query)) {
|
|
|
+ $(this).show();
|
|
|
+ } else {
|
|
|
+ $(this).hide();
|
|
|
+ $(this).find(".form-check-input").prop("checked", false);
|
|
|
+ }
|
|
|
+ });
|
|
|
});
|
|
|
- });
|
|
|
+ @endif
|
|
|
|
|
|
$('#sort-by-asc-{{$id}}').on('click', function () {
|
|
|
let columnName = '{{$id}}';
|