@props([ 'title', 'name' => null, 'options' => [], 'searchable' => false, 'selected' => [], 'inputName' => null, ]) @php $filterName = $name ?? Str::slug($title, '-'); // API-facing filter key: ifi-name → ifi_name, ip-wise → ip_wise, etc. $filterKey = str_replace('-', '_', $filterName); $selectedValues = collect($selected ?? [])->map(fn ($value) => (string) $value)->all(); $inputFieldName = $inputName ?? ($filterName . '[]'); $totalOptions = count($options); // Render first 50 options initially; the rest are loaded via AJAX on scroll. // Selected options are always included in the initial render so URL-preset // filters are shown checked regardless of their position in the list. $renderLimit = 50; // Partition: selected options first, then fill remaining slots with unselected $selectedOpts = array_values(array_filter($options, fn ($o) => in_array((string) $o, $selectedValues, true))); $unselectedOpts = array_values(array_filter($options, fn ($o) => !in_array((string) $o, $selectedValues, true))); $remainingSlots = max(0, $renderLimit - count($selectedOpts)); $displayOptions = array_merge($selectedOpts, array_slice($unselectedOpts, 0, $remainingSlots)); $loadedCount = count($displayOptions); $hasMore = $loadedCount < $totalOptions; // Next page index (1-based, size $renderLimit) $nextPage = $hasMore ? 2 : null; $isLargeDataset = $totalOptions > $renderLimit; $forceSearchable = $isLargeDataset ? true : ($searchable ?? false); $selectedCount = collect($displayOptions)->filter(fn ($option) => empty($selectedValues) || in_array((string) $option, $selectedValues, true))->count(); $isAllSelected = $loadedCount > 0 ? $selectedCount === $loadedCount : true; @endphp
@if ($forceSearchable)
@if ($isLargeDataset)
Showing {{ $loadedCount }} of {{ $totalOptions }}. Scroll to load more.
@endif
@endif