@props([ /** Catalog from EntityFilterCatalog::for($type). */ 'catalog' => [], /** ID for the form element (used by toolbar toggle target). */ 'id' => 'dynamic-filters', /** Form action — defaults to current URL. */ 'action' => null, /** Whether the filter panel starts open. Default: closed (toggle). */ 'open' => false, /** Localized search placeholder, optional. */ 'searchPlaceholder' => null, ]) @php $action = $action ?? url()->current(); // Active-filter chip list. Each entry { field, option_id, name, label_name }. $activeChips = []; foreach ($catalog as $entry) { if (empty($entry['selected'])) continue; $optionsById = []; foreach ($entry['options'] as $opt) { $optionsById[(int) $opt['id']] = $opt; } foreach ($entry['selected'] as $id) { $opt = $optionsById[(int) $id] ?? null; if (! $opt) continue; $activeChips[] = [ 'field' => $entry['field'], 'option_id' => (int) $id, 'name' => (string) ($opt['name'] ?? ''), 'label_name' => (string) ($entry['label_name'] ?? ''), ]; } } $hasAnyFilters = count($catalog) > 0; $searchValue = (string) request('q', ''); $hasAnyActive = $searchValue !== '' || count($activeChips) > 0; // Open by default if any filters are already active so the admin can // see what's selected; otherwise stay collapsed for a cleaner UI. $panelOpen = $open || count($activeChips) > 0; @endphp {{-- Filter UI — rectangular inputs, Select2 multi-selects, show/hide panel. Layout: Row 1: search input + "Filters" toggle (with count badge) Row 2: active filter chips (only when any are active) Row 3: panel with one Select2 per label group + Apply/Reset (collapsed by default; expands when toggle is clicked) Single
: every selection submits in one shot to GET. Sort + dir are preserved across submissions via hidden inputs. --}} {{-- Preserve sort/dir across filter submissions. --}} @foreach (['sort', 'dir'] as $k) @if (filled(request($k))) @endif @endforeach {{-- ─── Row 1: search + toggle ─────────────────────────────────── --}}
@if ($hasAnyFilters) @endif @if ($hasAnyActive) {{ __('admin.filters.reset') }} @endif
{{-- ─── Row 2: active filter chips ───────────────────────────────── --}} @if (count($activeChips) > 0)
{{ __('admin.filters.active') }} @foreach ($activeChips as $chip) @php // Build a URL minus this one (field, option_id). $newSelections = []; foreach ($catalog as $entry) { $kept = array_values(array_filter($entry['selected'], fn ($i) => ! ($entry['field'] === $chip['field'] && (int) $i === $chip['option_id']) )); if ($kept !== []) { $newSelections[$entry['field']] = $kept; } } $qs = array_merge( request()->only(['q', 'sort', 'dir']), $newSelections, ); $qs = array_filter($qs, fn ($v) => $v !== null && $v !== '' && $v !== []); $removeUrl = $action . (empty($qs) ? '' : '?' . http_build_query($qs)); @endphp {{ $chip['label_name'] }} · {{ $chip['name'] }} @endforeach
@endif {{-- ─── Row 3: filter panel (toggleable) ─────────────────────────── --}} @if ($hasAnyFilters)
@foreach ($catalog as $entry)
@endforeach
{{ __('admin.filters.reset') }}
@endif
@once @push('styles') @endpush @push('scripts') @endpush @endonce