Skip to content

Commit 2c84329

Browse files
feat: introduce roleForDisplay for specialists, add parent case reactivation, and enhance status change actions
- Replaced `role` with `roleForDisplay` in queries and columns for accurate role management. - Added functionality to reactivate closed/archived cases with partial data pre-fill from parent cases. - Enhanced status change actions with improved validation and confirmation support.
1 parent 6727c48 commit 2c84329

File tree

15 files changed

+214
-33
lines changed

15 files changed

+214
-33
lines changed

app/Filament/Organizations/Resources/Cases/CaseResource.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public static function getRecordRouteBindingEloquentQuery(): Builder
5656
return parent::getRecordRouteBindingEloquentQuery()
5757
->with([
5858
'managerTeam.user',
59-
'managerTeam.role',
59+
'managerTeam.roleForDisplay',
6060
'lastMonitoring',
6161
'interventionPlan',
6262
'closeFile',
@@ -73,7 +73,7 @@ public static function getRecordRouteBindingEloquentQuery(): Builder
7373
'aggressors',
7474
'antecedents',
7575
'specialistsTeam.user',
76-
'specialistsTeam.role',
76+
'specialistsTeam.roleForDisplay',
7777
'evaluateDetails',
7878
'children',
7979
'detailedEvaluationSpecialists',

app/Filament/Organizations/Resources/Cases/Pages/CreateCase.php

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,52 @@ class CreateCase extends CreateRecord
4848
/** Beneficiary found in same center when validating CNP step (shows "CNP identificat" message + link). */
4949
public ?Beneficiary $cnpBeneficiaryInTenant = null;
5050

51+
/** Parent beneficiary when reactivating a closed/archived case (from ?parent= query param). */
52+
public ?Beneficiary $parentBeneficiary = null;
53+
54+
public function mount(): void
55+
{
56+
$parentId = (int) request('parent');
57+
if ($parentId > 0) {
58+
$this->parentBeneficiary = Beneficiary::find($parentId);
59+
}
60+
parent::mount();
61+
if ($this->parentBeneficiary !== null) {
62+
$this->fillFormFromParentBeneficiary();
63+
}
64+
}
65+
66+
protected function getStartStep(): int
67+
{
68+
return $this->parentBeneficiary !== null ? 3 : 1;
69+
}
70+
71+
protected function fillFormFromParentBeneficiary(): void
72+
{
73+
$parent = $this->parentBeneficiary;
74+
if ($parent === null) {
75+
return;
76+
}
77+
$data = [
78+
'consent' => true,
79+
'without_cnp' => false,
80+
'cnp' => $parent->cnp,
81+
'last_name' => $parent->last_name,
82+
'first_name' => $parent->first_name,
83+
'prior_name' => $parent->prior_name,
84+
'civil_status' => $parent->civil_status?->value,
85+
'gender' => $parent->gender?->value,
86+
'birthdate' => $this->formatBirthdateForForm($parent->birthdate),
87+
'birthplace' => $parent->birthplace,
88+
'ethnicity' => $parent->ethnicity?->value,
89+
'id_type' => $parent->id_type?->value,
90+
'id_serial' => $parent->id_serial,
91+
'id_number' => $parent->id_number,
92+
'initial_id' => $parent->initial_id ?? $parent->id,
93+
];
94+
$this->form->fill(array_merge($this->form->getRawState(), $data));
95+
}
96+
5197
public function getTitle(): string|Htmlable
5298
{
5399
return __('case.create.title');
@@ -278,6 +324,9 @@ protected function mutateFormDataBeforeCreate(array $data): array
278324
{
279325
unset($data['consent'], $data['without_cnp']);
280326
$data['status'] = $data['status'] ?? CaseStatus::ACTIVE;
327+
if ($this->parentBeneficiary !== null) {
328+
$data['initial_id'] = $this->parentBeneficiary->initial_id ?? $this->parentBeneficiary->id;
329+
}
281330

282331
$fillable = (new Beneficiary)->getFillable();
283332

@@ -306,8 +355,7 @@ protected function afterCreate(): void
306355
}
307356
}
308357

309-
310-
$roleIds=$state['case_team'] ?? [];
358+
$roleIds = $state['case_team'] ?? [];
311359
$currentUserId = auth()->id();
312360
if (! $currentUserId) {
313361
return;

app/Filament/Organizations/Resources/Cases/Pages/InterventionPlan/CreateCaseMonthlyPlan.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ public function form(Schema $schema): Schema
150150
Select::make('specialists')
151151
->label(__('intervention_plan.labels.specialists'))
152152
->multiple()
153-
->options(fn (): Collection => $this->getBeneficiary()?->specialistsTeam()->with('user', 'role')->get()->pluck('name_role', 'id') ?? collect())
153+
->options(fn (): Collection => $this->getBeneficiary()?->specialistsTeam()->with('user', 'roleForDisplay')->get()->pluck('name_role', 'id') ?? collect())
154154
->placeholder(__('intervention_plan.placeholders.specialists')),
155155
]),
156156
]);

app/Filament/Organizations/Resources/Cases/Pages/InterventionPlan/ViewCaseInterventionService.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public function mount(int|string $record): void
4343
->with([
4444
'organizationServiceWithoutStatusCondition.serviceWithoutStatusCondition',
4545
'specialist.user',
46-
'specialist.role',
46+
'specialist.roleForDisplay',
4747
])
4848
->firstOrFail();
4949

app/Filament/Organizations/Resources/Cases/Pages/InterventionPlan/ViewCaseMonthlyPlan.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ public function infolist(Schema $schema): Schema
143143

144144
return Specialist::query()
145145
->whereIn('id', $ids)
146+
->with(['user', 'roleForDisplay'])
146147
->get()
147148
->pluck('name_role')
148149
->implode(', ');

app/Filament/Organizations/Resources/Cases/Pages/InterventionPlan/Widgets/InterventionPlanBenefitsWidget.php

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
use App\Models\Benefit;
1010
use App\Models\BenefitService;
1111
use App\Models\BenefitType;
12+
use Filament\Actions\DeleteAction;
13+
use Filament\Actions\EditAction;
1214
use Filament\Forms\Components\CheckboxList;
1315
use Filament\Forms\Components\RichEditor;
1416
use Filament\Forms\Components\Select;
@@ -46,7 +48,7 @@ public function table(Table $table): Table
4648
->formatStateUsing(fn ($state, BenefitService $record): string => self::formatBenefitTypes($record)),
4749
TextColumn::make('award_methods')
4850
->label(__('intervention_plan.headings.award_methods'))
49-
->formatStateUsing(fn ($state): string => $state instanceof BaseCollection ? $state->map(fn ($e) => $e->getLabel())->join(', ') : ''),
51+
->formatStateUsing(fn ($state): string => self::formatAwardMethods($state)),
5052
TextColumn::make('description')
5153
->label(__('intervention_plan.headings.benefit_description'))
5254
->html()
@@ -85,6 +87,50 @@ public function table(Table $table): Table
8587
])
8688
->createAnother(false),
8789
])
90+
->recordActionsColumnLabel(__('intervention_plan.labels.actions'))
91+
->recordActions([
92+
EditAction::make()
93+
->label(__('intervention_plan.actions.edit_benefit'))
94+
->modalHeading(__('intervention_plan.headings.edit_benefit'))
95+
->fillForm(fn (BenefitService $record): array => [
96+
'benefit_id' => $record->benefit_id,
97+
'benefit_types' => $record->benefit_types ?? [],
98+
'award_methods' => $record->award_methods?->map(fn ($e) => $e->value)->all() ?? [],
99+
'description' => $record->description,
100+
])
101+
->schema([
102+
Select::make('benefit_id')
103+
->label(__('intervention_plan.labels.benefit_category'))
104+
->placeholder(__('intervention_plan.placeholders.benefit_category'))
105+
->options(Benefit::query()->active()->pluck('name', 'id')->all())
106+
->searchable()
107+
->preload()
108+
->live()
109+
->required(),
110+
CheckboxList::make('benefit_types')
111+
->label(__('intervention_plan.labels.benefit_types'))
112+
->options(fn (Get $get): array => self::getBenefitTypesOptions((int) $get('benefit_id')))
113+
->visible(fn (Get $get): bool => (int) $get('benefit_id') > 0),
114+
CheckboxList::make('award_methods')
115+
->label(__('intervention_plan.labels.award_methods'))
116+
->options(AwardMethod::options()),
117+
RichEditor::make('description')
118+
->label(__('intervention_plan.labels.benefit_description'))
119+
->placeholder(__('intervention_plan.placeholders.benefit_description'))
120+
->maxLength(1000),
121+
])
122+
->action(function (array $data, BenefitService $record): void {
123+
$record->update($data);
124+
})
125+
->extraModalFooterActions([
126+
DeleteAction::make()
127+
->label(__('intervention_plan.actions.delete_benefit'))
128+
->modalHeading(__('intervention_plan.headings.delete_benefit_modal'))
129+
->modalDescription(fn (BenefitService $record): string => $record->benefit?->name ?? '')
130+
->modalSubmitActionLabel(__('intervention_plan.actions.delete_benefit'))
131+
->cancelParentActions(),
132+
]),
133+
])
88134
->emptyStateHeading(__('intervention_plan.headings.empty_state_benefit_table'))
89135
->emptyStateDescription(__('intervention_plan.labels.empty_state_benefit_table'))
90136
->emptyStateIcon('heroicon-o-document');
@@ -125,6 +171,21 @@ private static function formatBenefitTypes(BenefitService $record): string
125171
return $types->whereIn('id', $ids)->pluck('name')->join(', ');
126172
}
127173

174+
private static function formatAwardMethods(mixed $state): string
175+
{
176+
if ($state === null) {
177+
return '';
178+
}
179+
if ($state instanceof BaseCollection) {
180+
return $state->map(fn ($e) => is_object($e) && method_exists($e, 'getLabel') ? $e->getLabel() : (string) $e)->join(', ');
181+
}
182+
if (is_iterable($state)) {
183+
return collect($state)->map(fn ($e) => is_object($e) && method_exists($e, 'getLabel') ? $e->getLabel() : (string) $e)->join(', ');
184+
}
185+
186+
return '';
187+
}
188+
128189
public static function canView(): bool
129190
{
130191
return true;

app/Filament/Organizations/Resources/Cases/Pages/InterventionPlan/Widgets/InterventionPlanServicesWidget.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public function table(Table $table): Table
3535
->query(
3636
$plan
3737
? $plan->services()
38-
->with(['organizationServiceWithoutStatusCondition.serviceWithoutStatusCondition', 'specialist.user', 'specialist.role'])
38+
->with(['organizationServiceWithoutStatusCondition.serviceWithoutStatusCondition', 'specialist.user', 'specialist.roleForDisplay'])
3939
->withCount(['beneficiaryInterventions', 'meetings'])
4040
->getQuery()
4141
: InterventionService::query()->whereRaw('1 = 0')
@@ -104,7 +104,7 @@ public function table(Table $table): Table
104104

105105
return $plan->beneficiary
106106
->specialistsTeam()
107-
->with(['user:id,first_name,last_name', 'role:id,name'])
107+
->with(['user:id,first_name,last_name', 'roleForDisplay:id,name'])
108108
->get()
109109
->mapWithKeys(fn (Specialist $s) => [$s->id => $s->name_role])
110110
->all();

app/Filament/Organizations/Resources/Cases/Pages/ViewCase.php

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@
55
namespace App\Filament\Organizations\Resources\Cases\Pages;
66

77
use App\Actions\BackAction;
8+
use App\Enums\CaseStatus;
89
use App\Filament\Organizations\Resources\Cases\CaseResource;
910
use App\Models\Beneficiary;
1011
use Filament\Actions\Action;
1112
use Filament\Actions\ActionGroup;
13+
use Filament\Forms\Components\Checkbox;
14+
use Filament\Forms\Components\Placeholder;
15+
use Filament\Notifications\Notification;
1216
use Filament\Resources\Pages\ViewRecord;
1317
use Illuminate\Contracts\Support\Htmlable;
1418

@@ -40,21 +44,47 @@ protected function getHeaderActions(): array
4044
ActionGroup::make([
4145
Action::make('reopen_case')
4246
->label(__('beneficiary.action.active'))
43-
->disabled(fn () => $record->status?->value === 'active'),
47+
->disabled(fn () => $this->isStatusChangeDisabled($record, CaseStatus::ACTIVE))
48+
->action(fn () => $this->changeStatus($record, CaseStatus::ACTIVE)),
4449
Action::make('move_to_monitoring')
4550
->label(__('beneficiary.action.monitored'))
46-
->disabled(fn () => $record->status?->value === 'monitored'),
51+
->disabled(fn () => $this->isStatusChangeDisabled($record, CaseStatus::MONITORED))
52+
->action(fn () => $this->changeStatus($record, CaseStatus::MONITORED)),
4753
Action::make('close_case')
4854
->label(__('beneficiary.action.closed'))
49-
->disabled(fn () => $record->status?->value === 'closed'),
55+
->disabled(fn () => $this->isStatusChangeDisabled($record, CaseStatus::CLOSED))
56+
->action(fn () => $this->changeStatus($record, CaseStatus::CLOSED)),
5057
Action::make('archive_case')
5158
->label(__('beneficiary.action.archived'))
52-
->disabled(fn () => $record->status?->value === 'archived'),
59+
->disabled(fn () => $this->isStatusChangeDisabled($record, CaseStatus::ARCHIVED))
60+
->action(fn () => $this->changeStatus($record, CaseStatus::ARCHIVED)),
5361
Action::make('reactivate_case')
54-
->label(__('beneficiary.action.reactivate')),
62+
->label(__('beneficiary.action.reactivate'))
63+
->disabled(fn () => $record->status !== CaseStatus::CLOSED && $record->status !== CaseStatus::ARCHIVED)
64+
->modalHeading(__('beneficiary.section.identity.headings.reactivate_modal'))
65+
->schema([
66+
Placeholder::make('reactivate_text_1')
67+
->hiddenLabel()
68+
->content(__('beneficiary.placeholder.reactivate_text_1')),
69+
Placeholder::make('reactivate_text_2')
70+
->hiddenLabel()
71+
->content(__('beneficiary.placeholder.reactivate_text_2')),
72+
Placeholder::make('reactivate_text_3')
73+
->hiddenLabel()
74+
->content(__('beneficiary.placeholder.reactivate_text_3')),
75+
Checkbox::make('confirm')
76+
->label(__('beneficiary.section.identity.labels.beneficiary_agreement'))
77+
->required(),
78+
])
79+
->modalSubmitActionLabel(__('beneficiary.action.reactivate_modal'))
80+
->action(fn () => $this->redirect(CaseResource::getUrl('create').'?parent='.$record->id)),
5581
Action::make('delete_case_file')
5682
->label(__('beneficiary.action.delete'))
57-
->color('danger'),
83+
->color('danger')
84+
->requiresConfirmation()
85+
->authorize('delete', $record)
86+
->action(fn () => $record->delete())
87+
->successRedirectUrl(CaseResource::getUrl('index')),
5888
])
5989
->label(__('case.view.case_actions'))
6090
->button()
@@ -63,6 +93,40 @@ protected function getHeaderActions(): array
6393
];
6494
}
6595

96+
protected function isStatusChangeDisabled(Beneficiary $record, CaseStatus $targetStatus): bool
97+
{
98+
if ($record->status === $targetStatus) {
99+
return true;
100+
}
101+
if (CaseStatus::isValue($record->status, CaseStatus::ACTIVE) && $targetStatus === CaseStatus::ARCHIVED) {
102+
return true;
103+
}
104+
if (CaseStatus::isValue($record->status, CaseStatus::MONITORED) && $targetStatus === CaseStatus::ARCHIVED) {
105+
return true;
106+
}
107+
if (CaseStatus::isValue($record->status, CaseStatus::CLOSED) && $targetStatus === CaseStatus::MONITORED) {
108+
return true;
109+
}
110+
if (CaseStatus::isValue($record->status, CaseStatus::ARCHIVED)
111+
&& in_array($targetStatus, [CaseStatus::MONITORED, CaseStatus::ACTIVE], true)) {
112+
return true;
113+
}
114+
115+
return false;
116+
}
117+
118+
protected function changeStatus(Beneficiary $record, CaseStatus $status): void
119+
{
120+
$record->update(['status' => $status]);
121+
Notification::make()
122+
->title(__('beneficiary.notification.change_status.title'))
123+
->success()
124+
->body(__('beneficiary.notification.change_status.body', [
125+
'status' => $status->getLabel(),
126+
]))
127+
->send();
128+
}
129+
66130
public function getBreadcrumbs(): array
67131
{
68132
$record = $this->getRecord();

app/Filament/Organizations/Resources/Cases/Pages/Widgets/CaseTeamWidget.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ public function table(Table $table): Table
3434
return $table
3535
->query(
3636
$record
37-
? $record->specialistsTeam()->with(['role', 'user'])->getQuery()
37+
? $record->specialistsTeam()->with(['roleForDisplay', 'user'])->getQuery()
3838
: Specialist::query()->whereRaw('1 = 0')
3939
)
4040
->heading(__('case.view.case_team'))
4141
->columns([
42-
TextColumn::make('role.name')
42+
TextColumn::make('roleForDisplay.name')
4343
->label(__('beneficiary.section.specialists.labels.roles'))
4444
->placeholder(__('beneficiary.section.specialists.labels.empty_state_role')),
4545
TextColumn::make('user.full_name')

app/Filament/Organizations/Resources/Cases/Pages/Widgets/MonitoringWidget.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public function table(Table $table): Table
2626
return $table
2727
->query(
2828
$record
29-
? $record->monitoring()->with(['specialistsTeam.user', 'specialistsTeam.role'])->getQuery()
29+
? $record->monitoring()->with(['specialistsTeam.user', 'specialistsTeam.roleForDisplay'])->getQuery()
3030
: Monitoring::query()->whereRaw('1 = 0')
3131
)
3232
->heading(__('monitoring.headings.widget_table'))

0 commit comments

Comments
 (0)