modifyQueryUsing(fn (Builder $query) => $query->with('user')) ->columns([ Tables\Columns\TextColumn::make('user.name') ->label('User') ->searchable(), Tables\Columns\TextColumn::make('user.email') ->label('Email') ->toggleable(isToggledHiddenByDefault: true), Tables\Columns\TextColumn::make('role') ->badge() ->sortable(), Tables\Columns\TextColumn::make('source') ->badge() ->toggleable(isToggledHiddenByDefault: true), Tables\Columns\TextColumn::make('created_at')->since(), ]) ->headerActions([ Actions\Action::make('add_member') ->label('Add member') ->icon('heroicon-o-plus') ->visible(function (): bool { $tenant = $this->getOwnerRecord(); if (! $tenant instanceof Tenant) { return false; } return Gate::allows('tenant_membership.manage', $tenant); }) ->form([ Forms\Components\Select::make('user_id') ->label('User') ->required() ->searchable() ->options(fn () => User::query()->orderBy('name')->pluck('name', 'id')->all()), Forms\Components\Select::make('role') ->label('Role') ->required() ->options([ TenantRole::Owner->value => 'Owner', TenantRole::Manager->value => 'Manager', TenantRole::Operator->value => 'Operator', TenantRole::Readonly->value => 'Readonly', ]), ]) ->action(function (array $data, TenantMembershipManager $manager): void { $tenant = $this->getOwnerRecord(); if (! $tenant instanceof Tenant) { abort(404); } $actor = auth()->user(); if (! $actor instanceof User) { abort(403); } if (! Gate::allows('tenant_membership.manage', $tenant)) { abort(403); } $member = User::query()->find((int) $data['user_id']); if (! $member) { Notification::make()->title('User not found')->danger()->send(); return; } try { $manager->addMember( tenant: $tenant, actor: $actor, member: $member, role: TenantRole::from((string) $data['role']), source: 'manual', ); } catch (\Throwable $throwable) { Notification::make() ->title('Failed to add member') ->body($throwable->getMessage()) ->danger() ->send(); return; } Notification::make()->title('Member added')->success()->send(); $this->resetTable(); }), ]) ->actions([ Actions\Action::make('change_role') ->label('Change role') ->icon('heroicon-o-pencil') ->visible(function (): bool { $tenant = $this->getOwnerRecord(); if (! $tenant instanceof Tenant) { return false; } return Gate::allows('tenant_membership.manage', $tenant); }) ->form([ Forms\Components\Select::make('role') ->label('Role') ->required() ->options([ TenantRole::Owner->value => 'Owner', TenantRole::Manager->value => 'Manager', TenantRole::Operator->value => 'Operator', TenantRole::Readonly->value => 'Readonly', ]), ]) ->action(function (TenantMembership $record, array $data, TenantMembershipManager $manager): void { $tenant = $this->getOwnerRecord(); if (! $tenant instanceof Tenant) { abort(404); } $actor = auth()->user(); if (! $actor instanceof User) { abort(403); } if (! Gate::allows('tenant_membership.manage', $tenant)) { abort(403); } try { $manager->changeRole( tenant: $tenant, actor: $actor, membership: $record, newRole: TenantRole::from((string) $data['role']), ); } catch (\Throwable $throwable) { Notification::make() ->title('Failed to change role') ->body($throwable->getMessage()) ->danger() ->send(); return; } Notification::make()->title('Role updated')->success()->send(); $this->resetTable(); }), Actions\Action::make('remove') ->label('Remove') ->color('danger') ->icon('heroicon-o-x-mark') ->requiresConfirmation() ->visible(function (): bool { $tenant = $this->getOwnerRecord(); if (! $tenant instanceof Tenant) { return false; } return Gate::allows('tenant_membership.manage', $tenant); }) ->action(function (TenantMembership $record, TenantMembershipManager $manager): void { $tenant = $this->getOwnerRecord(); if (! $tenant instanceof Tenant) { abort(404); } $actor = auth()->user(); if (! $actor instanceof User) { abort(403); } if (! Gate::allows('tenant_membership.manage', $tenant)) { abort(403); } try { $manager->removeMember($tenant, $actor, $record); } catch (\Throwable $throwable) { Notification::make() ->title('Failed to remove member') ->body($throwable->getMessage()) ->danger() ->send(); return; } Notification::make()->title('Member removed')->success()->send(); $this->resetTable(); }), ]) ->bulkActions([]); } }