diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 363e43c..d8fd46c 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -8,5 +8,3 @@ parameters: tmpDir: build/phpstan checkOctaneCompatibility: true checkModelProperties: true - checkMissingIterableValueType: false - diff --git a/resources/views/livewire/resource-picker.blade.php b/resources/views/livewire/resource-picker.blade.php index e1287fb..ccb1500 100644 --- a/resources/views/livewire/resource-picker.blade.php +++ b/resources/views/livewire/resource-picker.blade.php @@ -45,6 +45,23 @@ class="block w-full transition text-sm py-1 !ps-8 !pe-3 duration-75 border-none + @if(!empty($relationFilters)) + @foreach($relationFilters as $relation => $filters) +
+
Filter by {{ $relation }}
+
+ @foreach($filters as $filter) + + {{ $filter['name'] }} + + @endforeach +
+
+ @endforeach + @endif @endif
diff --git a/src/Livewire/ResourcePicker.php b/src/Livewire/ResourcePicker.php index 4795ddc..9475257 100644 --- a/src/Livewire/ResourcePicker.php +++ b/src/Livewire/ResourcePicker.php @@ -32,8 +32,12 @@ class ResourcePicker extends Component public ?int $maxItems = null; + public ?array $relationFilters = null; + public string $search = ''; + public array $selectedRelations = []; + public function mount( string $resourceClass, string $displayType, @@ -46,6 +50,7 @@ public function mount( int $gridColumns, ?int $minItems = null, ?int $maxItems = null, + ?array $relationFilters = null, ) { $this->resourceClass = $resourceClass; $this->displayType = $displayType; @@ -58,6 +63,7 @@ public function mount( $this->gridColumns = $gridColumns; $this->minItems = $minItems; $this->maxItems = $maxItems; + $this->relationFilters = $relationFilters; $this->items = $this->getItems(); } @@ -73,6 +79,7 @@ public function render() public function getItems(int $offset = 0) { return ResourceQuery::get($this->resourceClass, $this->search) + ->tap(fn ($query) => $this->searchRelations($query)) ->latest() ->offset($offset) ->limit(24) @@ -82,6 +89,7 @@ public function getItems(int $offset = 0) public function getItemCount() { return ResourceQuery::get($this->resourceClass, $this->search) + ->tap(fn ($query) => $this->searchRelations($query)) ->count(); } @@ -97,4 +105,49 @@ public function updatedSearch(): void { $this->items = $this->getItems(); } + + public function toggleRelation($relation, $id): void + { + $this->setSelectedRelation($relation, $id); + + $this->items = $this->getItems(); + } + + protected function searchRelations($query) + { + return collect($this->relationFilters)->each(function ($filters, $relation) use ($query) { + if (! empty($this->getSelectedRelations($relation))) { + $query->whereHas($relation, function ($q) use ($relation) { + $q->whereIn('id', $this->getSelectedRelations($relation)); + }); + } + }); + } + + protected function setSelectedRelation($relation, $id): void + { + if (! array_key_exists($relation, $this->selectedRelations)) { + $this->selectedRelations[$relation][] = $id; + + return; + } + + if (! in_array($id, $this->selectedRelations[$relation])) { + $this->selectedRelations[$relation][] = $id; + + return; + } + + $this->selectedRelations[$relation] = array_diff($this->selectedRelations[$relation], [$id]); + } + + protected function getSelectedRelations($relation) + { + return $this->selectedRelations[$relation] ?? []; + } + + public function isRelationFilterActive($relation, $id): bool + { + return in_array($id, $this->getSelectedRelations($relation)); + } }