From 459ff23b5e6f869543de217a5517084a276e21e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20Ioni=C8=9B=C4=83?= Date: Thu, 20 Mar 2025 16:19:45 +0000 Subject: [PATCH] feat: link request stay --- app/Concerns/HasRequestStatus.php | 17 ++++++++++- .../BeneficiaryResource/Pages/ViewStay.php | 6 ++-- .../BeneficiaryResource/Schemas/StayForm.php | 29 +++++++++++++++++++ .../Schemas/StayInfolist.php | 8 +++++ .../Widgets/StaysWidget.php | 15 ++++++++++ .../Shelter/Resources/RequestResource.php | 15 ++++++++++ .../Schemas/RequestInfolist.php | 10 +++++++ app/Models/Request.php | 18 ++++++++++++ app/Models/Stay.php | 20 +++++++++++++ lang/en/app.php | 2 ++ 10 files changed, 135 insertions(+), 5 deletions(-) diff --git a/app/Concerns/HasRequestStatus.php b/app/Concerns/HasRequestStatus.php index 0175c42..ec3fa7e 100644 --- a/app/Concerns/HasRequestStatus.php +++ b/app/Concerns/HasRequestStatus.php @@ -37,7 +37,22 @@ public function scopeWhereReferred(Builder $query): Builder public function scopeWhereNewOrReferred(Builder $query): Builder { - return $query->whereIn('status', [RequestStatus::NEW, RequestStatus::REFERRED]); + return $query->whereIn('status', [ + RequestStatus::NEW, + RequestStatus::REFERRED, + ]); + } + + public function scopeWhereAllocatable(Builder $query): Builder + { + return $query + ->whereDoesntHave('stay') + ->whereIn('status', [ + RequestStatus::NEW, + RequestStatus::REFERRED, + RequestStatus::PENDING, + RequestStatus::ACCEPTED, + ]); } public function scopeWherePending(Builder $query): Builder diff --git a/app/Filament/Shelter/Resources/BeneficiaryResource/Pages/ViewStay.php b/app/Filament/Shelter/Resources/BeneficiaryResource/Pages/ViewStay.php index a602918..ee24399 100644 --- a/app/Filament/Shelter/Resources/BeneficiaryResource/Pages/ViewStay.php +++ b/app/Filament/Shelter/Resources/BeneficiaryResource/Pages/ViewStay.php @@ -37,11 +37,9 @@ public function mount(int|string $record): void public function getTitle(): string { return \sprintf( - '%s #%s %s–%s', + '%s %s', Str::ucfirst(__('app.stay.label.singular')), - $this->stay->id, - $this->stay->start_date->toFormattedDate(), - $this->stay->end_date->toFormattedDate() + $this->stay->title ); } diff --git a/app/Filament/Shelter/Resources/BeneficiaryResource/Schemas/StayForm.php b/app/Filament/Shelter/Resources/BeneficiaryResource/Schemas/StayForm.php index 3b47941..386ae3b 100644 --- a/app/Filament/Shelter/Resources/BeneficiaryResource/Schemas/StayForm.php +++ b/app/Filament/Shelter/Resources/BeneficiaryResource/Schemas/StayForm.php @@ -4,14 +4,18 @@ namespace App\Filament\Shelter\Resources\BeneficiaryResource\Schemas; +use App\Models\Request; +use Filament\Facades\Filament; use Filament\Forms\Components\Checkbox; use Filament\Forms\Components\DatePicker; use Filament\Forms\Components\Grid; use Filament\Forms\Components\Group; use Filament\Forms\Components\Hidden; +use Filament\Forms\Components\Select; use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; use Filament\Forms\Get; +use Illuminate\Support\Str; class StayForm { @@ -55,6 +59,31 @@ public static function getSchema(?int $beneficiary_id = null): array ->rows(5), ]), + Checkbox::make('has_request') + ->label(__('app.field.has_request')) + ->columnSpanFull() + ->live(), + + Select::make('request_id') + ->label(__('app.field.request')) + ->visible(fn (Get $get) => $get('has_request')) + ->columnSpanFull() + ->searchable() + ->preload() + ->required() + ->getSearchResultsUsing( + fn (string $search) => Request::query() + ->whereAllocatable() + ->where('shelter_id', Filament::getTenant()->getKey()) + ->where(function ($query) use ($search) { + $query->whereLike('id', Str::remove('#', $search) . '%') + ->orWhereLike('beneficiary->name', "%{$search}%"); + }) + ->get() + ->pluck('optionLabel', 'id') + ) + ->getOptionLabelUsing(fn ($value) => Request::find($value)->optionLabel()), + ]), ]; } diff --git a/app/Filament/Shelter/Resources/BeneficiaryResource/Schemas/StayInfolist.php b/app/Filament/Shelter/Resources/BeneficiaryResource/Schemas/StayInfolist.php index 90e6f40..bc58ff0 100644 --- a/app/Filament/Shelter/Resources/BeneficiaryResource/Schemas/StayInfolist.php +++ b/app/Filament/Shelter/Resources/BeneficiaryResource/Schemas/StayInfolist.php @@ -4,6 +4,7 @@ namespace App\Filament\Shelter\Resources\BeneficiaryResource\Schemas; +use App\Filament\Shelter\Resources\RequestResource; use App\Models\Stay; use Filament\Infolists\Components\Group; use Filament\Infolists\Components\Section; @@ -54,6 +55,13 @@ public static function getSchema(): array ->label(__('app.field.children_notes')), ]), + TextEntry::make('request.title') + ->visible(fn (Stay $record) => $record->has_request) + ->label(__('app.field.request')) + ->url(fn (Stay $record) => RequestResource::getUrl('view', [ + 'record' => $record->request_id, + ])) + ->color('primary'), ]), ]; } diff --git a/app/Filament/Shelter/Resources/BeneficiaryResource/Widgets/StaysWidget.php b/app/Filament/Shelter/Resources/BeneficiaryResource/Widgets/StaysWidget.php index 4bc4e16..ff0e8ac 100644 --- a/app/Filament/Shelter/Resources/BeneficiaryResource/Widgets/StaysWidget.php +++ b/app/Filament/Shelter/Resources/BeneficiaryResource/Widgets/StaysWidget.php @@ -6,6 +6,7 @@ use App\Filament\Shelter\Resources\BeneficiaryResource; use App\Filament\Shelter\Resources\BeneficiaryResource\Schemas\StayForm; +use App\Filament\Shelter\Resources\RequestResource; use App\Models\Beneficiary; use App\Models\Stay; use Filament\Tables\Actions\CreateAction; @@ -47,6 +48,20 @@ public function table(Table $table): Table ->label(__('app.field.shelter')) ->sortable() ->shrink(), + + TextColumn::make('request.title') + ->label(__('app.field.request')) + ->url(function (Stay $record) { + if (blank($record->request_id)) { + return null; + } + + return RequestResource::getUrl('view', [ + 'record' => $record->request_id, + ]); + }) + ->color('primary') + ->shrink(), ]) ->headerActions([ CreateAction::make() diff --git a/app/Filament/Shelter/Resources/RequestResource.php b/app/Filament/Shelter/Resources/RequestResource.php index e251ee8..5cdbe60 100644 --- a/app/Filament/Shelter/Resources/RequestResource.php +++ b/app/Filament/Shelter/Resources/RequestResource.php @@ -110,6 +110,21 @@ public static function table(Table $table): Table TextColumn::make('special_needs') ->label(__('app.field.special_needs')), + TextColumn::make('stay.title') + ->label(__('app.field.stay')) + ->url(function (Request $record) { + if (blank($record->stay)) { + return null; + } + + return BeneficiaryResource::getUrl('stay', [ + 'record' => $record->stay->beneficiary_id, + 'stay' => $record->stay->id, + ]); + }) + ->color('primary') + ->shrink(), + TextColumn::make('status') ->label(__('app.field.status')) ->badge(), diff --git a/app/Filament/Shelter/Resources/RequestResource/Schemas/RequestInfolist.php b/app/Filament/Shelter/Resources/RequestResource/Schemas/RequestInfolist.php index b3af1c7..370aab6 100644 --- a/app/Filament/Shelter/Resources/RequestResource/Schemas/RequestInfolist.php +++ b/app/Filament/Shelter/Resources/RequestResource/Schemas/RequestInfolist.php @@ -4,6 +4,7 @@ namespace App\Filament\Shelter\Resources\RequestResource\Schemas; +use App\Filament\Shelter\Resources\BeneficiaryResource; use App\Infolists\Components\Notice; use App\Infolists\Components\TableRepeatableEntry; use App\Models\Request; @@ -63,6 +64,15 @@ public static function getSchema(): array ->label(__('app.field.end_date')) ->date(), + TextEntry::make('stay.title') + ->visible(fn (Request $record) => $record->stay()->exists()) + ->label(__('app.field.stay')) + ->url(fn (Request $record) => BeneficiaryResource::getUrl('stay', [ + 'record' => $record->stay->beneficiary_id, + 'stay' => $record->stay->id, + ])) + ->color('primary'), + TextEntry::make('reason_rejected') ->label(__('app.field.reason_rejected')) ->visible(fn (Request $record) => $record->isRejected()), diff --git a/app/Models/Request.php b/app/Models/Request.php index 12c84ee..352f72e 100644 --- a/app/Models/Request.php +++ b/app/Models/Request.php @@ -13,9 +13,11 @@ use App\Enums\SpecialNeed; use Database\Factories\RequestFactory; use Illuminate\Database\Eloquent\Casts\AsEnumCollection; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasOne; use Spatie\LaravelData\DataCollection; class Request extends Model @@ -82,6 +84,11 @@ public function shelter(): BelongsTo return $this->belongsTo(Shelter::class); } + public function stay(): HasOne + { + return $this->hasOne(Stay::class); + } + public function referToShelter(Shelter $shelter, ?string $notes = null): void { $this->update([ @@ -107,4 +114,15 @@ public function tapActivity(Activity $activity, string $event): void $activity->event = 'referred'; $activity->description = 'referred'; } + + public function title(): Attribute + { + return Attribute::make( + fn () => \sprintf( + '#%s - %s', + $this->id, + $this->beneficiary->name, + ) + ); + } } diff --git a/app/Models/Stay.php b/app/Models/Stay.php index 80df1bf..2549332 100644 --- a/app/Models/Stay.php +++ b/app/Models/Stay.php @@ -26,6 +26,7 @@ class Stay extends Model 'start_date', 'end_date', 'beneficiary_id', + 'request_id', 'children_count', 'children_notes', 'notes', @@ -67,4 +68,23 @@ public function hasChildren(): Attribute get: fn (mixed $value, array $attributes) => filled($attributes['children_count']) || filled($attributes['children_notes']), ); } + + public function hasRequest(): Attribute + { + return Attribute::make( + get: fn (mixed $value, array $attributes) => filled($attributes['request_id']), + ); + } + + public function title(): Attribute + { + return Attribute::make( + fn () => \sprintf( + '#%s %s–%s', + $this->id, + $this->start_date->toFormattedDate(), + $this->end_date->toFormattedDate() + ) + ); + } } diff --git a/lang/en/app.php b/lang/en/app.php index c153961..a75cb93 100644 --- a/lang/en/app.php +++ b/lang/en/app.php @@ -46,6 +46,7 @@ 'group_size' => 'No.', 'group' => 'Group', 'has_children' => 'Accompanied by children', + 'has_request' => 'The stay is linked to an existing request', 'help' => 'Help text', 'id_number' => 'ID number', 'id_type' => 'ID type', @@ -79,6 +80,7 @@ 'request_group' => 'Request for a group', 'request_shelter' => 'Where do you seek accommodation?', 'request_somebody_else' => 'Request for somebody else', + 'request' => 'Request', 'requester' => 'Requester', 'required' => 'Required', 'residence_country' => 'Residence country',