TenantAtlas/app/Filament/Resources/TenantResource/Pages/ListTenants.php
ahmido 3f6f80f7af feat: refine onboarding draft flow and RBAC diff UX (#171)
## Summary
- add the RBAC role definition diff UX upgrade as the first concrete consumer of the shared diff presentation foundation
- refine managed tenant onboarding draft routing, CTA labeling, and cancellation redirect behavior
- tighten related Filament and diff rendering regression coverage

## Testing
- updated focused Pest coverage for onboarding draft routing and lifecycle behavior
- updated focused Pest coverage for shared diff partials and RBAC finding rendering

## Notes
- Livewire v4.0+ compliance is preserved within the existing Filament v5 surfaces
- provider registration remains unchanged in bootstrap/providers.php
- no new Filament assets were added; existing deployment practice still relies on php artisan filament:assets when assets change

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #171
2026-03-14 20:09:54 +00:00

87 lines
2.3 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Filament\Resources\TenantResource\Pages;
use App\Filament\Resources\TenantResource;
use App\Models\User;
use App\Models\Workspace;
use App\Services\Onboarding\OnboardingDraftResolver;
use App\Support\Workspaces\WorkspaceContext;
use Filament\Actions;
use Filament\Resources\Pages\ListRecords;
class ListTenants extends ListRecords
{
protected static string $resource = TenantResource::class;
protected function getHeaderActions(): array
{
return [
$this->makeOnboardingEntryAction()
->visible(fn (): bool => $this->getTableRecords()->count() > 0),
];
}
protected function getTableEmptyStateActions(): array
{
return [
$this->makeOnboardingEntryAction(),
];
}
private function makeOnboardingEntryAction(): Actions\Action
{
return Actions\Action::make('add_tenant')
->label($this->onboardingEntryLabel())
->icon($this->onboardingEntryIcon())
->url(route('admin.onboarding'));
}
private function onboardingEntryLabel(): string
{
$draftCount = $this->accessibleResumableDraftCount();
return match (true) {
$draftCount === 1 => 'Continue onboarding',
$draftCount > 1 => 'Choose onboarding draft',
default => 'Add tenant',
};
}
private function onboardingEntryIcon(): string
{
$draftCount = $this->accessibleResumableDraftCount();
return match (true) {
$draftCount === 1 => 'heroicon-m-arrow-path',
$draftCount > 1 => 'heroicon-m-queue-list',
default => 'heroicon-m-plus',
};
}
private function accessibleResumableDraftCount(): int
{
$user = auth()->user();
if (! $user instanceof User) {
return 0;
}
$workspaceId = app(WorkspaceContext::class)->currentWorkspaceId(request());
if (! is_int($workspaceId)) {
return 0;
}
$workspace = Workspace::query()->whereKey($workspaceId)->first();
if (! $workspace instanceof Workspace) {
return 0;
}
return app(OnboardingDraftResolver::class)->resumableDraftsFor($user, $workspace)->count();
}
}