diff --git a/app/Filament/Admin/Resources/OrganizationResource/Actions/ListShelterAction.php b/app/Filament/Admin/Resources/OrganizationResource/Actions/ListShelterAction.php new file mode 100644 index 0000000..1ece397 --- /dev/null +++ b/app/Filament/Admin/Resources/OrganizationResource/Actions/ListShelterAction.php @@ -0,0 +1,45 @@ +visible(fn (Shelter $record) => $record->isUnlisted() && Filament::auth()->user()->can('update', $record)); + + $this->label(__('app.shelter.actions.list.button')); + + $this->color('success'); + + $this->icon('heroicon-o-eye'); + + $this->outlined(); + + $this->requiresConfirmation(); + + $this->modalHeading(__('app.shelter.actions.list.confirm.title')); + + $this->modalDescription(__('app.shelter.actions.list.confirm.description')); + + $this->action(function (Shelter $record) { + $record->list(); + $this->success(); + }); + + $this->successNotificationTitle(__('app.shelter.actions.list.confirm.success')); + } +} diff --git a/app/Filament/Admin/Resources/OrganizationResource/Actions/UnlistShelterAction.php b/app/Filament/Admin/Resources/OrganizationResource/Actions/UnlistShelterAction.php new file mode 100644 index 0000000..44d6f80 --- /dev/null +++ b/app/Filament/Admin/Resources/OrganizationResource/Actions/UnlistShelterAction.php @@ -0,0 +1,45 @@ +visible(fn (Shelter $record) => $record->isListed() && Filament::auth()->user()->can('update', $record)); + + $this->label(__('app.shelter.actions.unlist.button')); + + $this->color('danger'); + + $this->icon('heroicon-o-eye-slash'); + + $this->outlined(); + + $this->requiresConfirmation(); + + $this->modalHeading(__('app.shelter.actions.unlist.confirm.title')); + + $this->modalDescription(__('app.shelter.actions.unlist.confirm.description')); + + $this->action(function (Shelter $record) { + $record->unlist(); + $this->success(); + }); + + $this->successNotificationTitle(__('app.shelter.actions.unlist.confirm.success')); + } +} diff --git a/app/Filament/Admin/Resources/OrganizationResource/RelationManagers/SheltersRelationManager.php b/app/Filament/Admin/Resources/OrganizationResource/RelationManagers/SheltersRelationManager.php index df4f954..6d001fb 100644 --- a/app/Filament/Admin/Resources/OrganizationResource/RelationManagers/SheltersRelationManager.php +++ b/app/Filament/Admin/Resources/OrganizationResource/RelationManagers/SheltersRelationManager.php @@ -4,10 +4,13 @@ namespace App\Filament\Admin\Resources\OrganizationResource\RelationManagers; +use App\Filament\Admin\Resources\OrganizationResource\Actions\ListShelterAction; +use App\Filament\Admin\Resources\OrganizationResource\Actions\UnlistShelterAction; use App\Filament\Admin\Resources\OrganizationResource\Schemas\SheltersForm; use Filament\Forms\Form; use Filament\Resources\RelationManagers\RelationManager; use Filament\Tables; +use Filament\Tables\Columns\IconColumn; use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; @@ -26,6 +29,11 @@ public function table(Table $table): Table return $table ->recordTitleAttribute('name') ->columns([ + IconColumn::make('is_listed') + ->label(__('app.field.is_listed')) + ->boolean() + ->shrink(), + TextColumn::make('name') ->label(__('app.field.name')) ->searchable() @@ -50,7 +58,6 @@ public function table(Table $table): Table ->wrap() ->searchable() ->sortable(), - ]) ->filters([ // @@ -60,9 +67,17 @@ public function table(Table $table): Table ->createAnother(false), ]) ->actions([ - Tables\Actions\ViewAction::make(), - Tables\Actions\EditAction::make(), - Tables\Actions\DeleteAction::make(), + Tables\Actions\ActionGroup::make([ + Tables\Actions\ViewAction::make(), + + Tables\Actions\EditAction::make(), + + ListShelterAction::make(), + + UnlistShelterAction::make(), + + Tables\Actions\DeleteAction::make(), + ]), ]); } } diff --git a/app/Filament/Shelter/Resources/RequestResource/Widgets/ReferToShelterWidget.php b/app/Filament/Shelter/Resources/RequestResource/Widgets/ReferToShelterWidget.php index dd4e9ae..7e3f8cf 100644 --- a/app/Filament/Shelter/Resources/RequestResource/Widgets/ReferToShelterWidget.php +++ b/app/Filament/Shelter/Resources/RequestResource/Widgets/ReferToShelterWidget.php @@ -33,6 +33,7 @@ public function table(Table $table): Table return $table ->query( fn () => Shelter::query() + ->whereListed() ->whereNot('id', Filament::getTenant()->id) ->with('shelterVariables') ) diff --git a/app/Livewire/RequestPage.php b/app/Livewire/RequestPage.php index 3bc0120..52735e4 100644 --- a/app/Livewire/RequestPage.php +++ b/app/Livewire/RequestPage.php @@ -87,6 +87,7 @@ public function handle() public function form(Form $form): Form { $shelters = Shelter::query() + ->whereListed() ->get(['id', 'name', 'address']); return $form diff --git a/app/Models/Shelter.php b/app/Models/Shelter.php index ecce365..f82a933 100644 --- a/app/Models/Shelter.php +++ b/app/Models/Shelter.php @@ -8,6 +8,7 @@ use App\Concerns\LogsActivity; use App\Data\PersonData; use Database\Factories\ShelterFactory; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; @@ -32,6 +33,7 @@ class Shelter extends Model 'address', 'coordinator', 'notes', + 'is_listed', ]; protected function casts(): array @@ -39,6 +41,7 @@ protected function casts(): array return [ 'capacity' => 'integer', 'coordinator' => PersonData::class, + 'is_listed' => 'boolean', ]; } @@ -75,6 +78,15 @@ public function shelterVariables(): BelongsToMany return $this->belongsToMany(ShelterVariable::class); } + public function scopeWhereListed(Builder $query): Builder + { + return $query + ->where('is_listed', true) + ->whereHas('organization', function (Builder $query) { + $query->whereActive(); + }); + } + public function availableCapacity(): Attribute { return Attribute::make( @@ -83,4 +95,28 @@ public function availableCapacity(): Attribute ->count(), ); } + + public function isListed(): bool + { + return $this->is_listed; + } + + public function isUnlisted(): bool + { + return ! $this->isListed(); + } + + public function list(): bool + { + return $this->update([ + 'is_listed' => true, + ]); + } + + public function unlist(): bool + { + return $this->update([ + 'is_listed' => false, + ]); + } } diff --git a/database/factories/ShelterFactory.php b/database/factories/ShelterFactory.php index 00ef965..62f9fc8 100644 --- a/database/factories/ShelterFactory.php +++ b/database/factories/ShelterFactory.php @@ -41,6 +41,7 @@ public function definition(): array phone: fake()->e164PhoneNumber(), ), 'notes' => fake()->paragraph(), + 'is_listed' => fake()->boolean(), ]; } diff --git a/database/migrations/0001_01_04_000009_add_is_listed_column_to_shelters_table.php b/database/migrations/0001_01_04_000009_add_is_listed_column_to_shelters_table.php new file mode 100644 index 0000000..1d41a14 --- /dev/null +++ b/database/migrations/0001_01_04_000009_add_is_listed_column_to_shelters_table.php @@ -0,0 +1,19 @@ +boolean('is_listed') + ->default(false) + ->after('capacity'); + }); + } +}; diff --git a/lang/en/app.php b/lang/en/app.php index 5f4e6a1..89fb822 100644 --- a/lang/en/app.php +++ b/lang/en/app.php @@ -56,6 +56,7 @@ 'id' => 'ID', 'identifier' => 'Identifier', 'is_indefinite' => 'Indefinite end date', + 'is_listed' => 'Listed', 'label' => 'Label', 'latest_stay' => 'Latest stay', 'legal_documents' => 'Legal documents', @@ -258,6 +259,24 @@ 'plural' => 'shelters', ], 'profile' => 'Profile', + 'actions' => [ + 'list' => [ + 'button' => 'List shelter', + 'confirm' => [ + 'description' => 'Once a shelter is listed, it will be displayed in the public request form and in the referral process. In order to eliminate the shelter from these lists, it needs to be unlisted.', + 'title' => 'List shelter', + 'success' => 'Shelter listed successfully.', + ], + ], + 'unlist' => [ + 'button' => 'Unlist shelter', + 'confirm' => [ + 'description' => 'Once a shelter is unlisted, it will no longer be displayed in the public request form or in the referral process. To include the shelter in these lists again, it needs to be listed.', + 'title' => 'Unlist shelter', + 'success' => 'Shelter unlisted successfully.', + ], + ], + ], ], 'user' => [ 'label' => [