getRecord(); $user = auth()->user(); if (! $user instanceof User || ! $tenant instanceof Tenant || ! $record instanceof TenantReview) { abort(404); } if ((int) $record->tenant_id !== (int) $tenant->getKey()) { abort(404); } if (! $user->canAccessTenant($tenant)) { abort(404); } if (! $user->can('view', $record)) { abort(403); } } protected function getHeaderActions(): array { return [ Actions\Action::make('view_run') ->label('View run') ->icon('heroicon-o-eye') ->color('gray') ->hidden(fn (): bool => ! is_numeric($this->record->operation_run_id)) ->url(fn (): ?string => $this->record->operation_run_id ? OperationRunLinks::tenantlessView((int) $this->record->operation_run_id) : null), Actions\Action::make('view_export') ->label('View executive pack') ->icon('heroicon-o-document-arrow-down') ->color('gray') ->hidden(fn (): bool => ! $this->record->currentExportReviewPack) ->url(fn (): ?string => $this->record->currentExportReviewPack ? \App\Filament\Resources\ReviewPackResource::getUrl('view', ['record' => $this->record->currentExportReviewPack], tenant: $this->record->tenant) : null), Actions\Action::make('view_evidence') ->label('View evidence snapshot') ->icon('heroicon-o-shield-check') ->color('gray') ->hidden(fn (): bool => ! $this->record->evidenceSnapshot) ->url(fn (): ?string => $this->record->evidenceSnapshot ? \App\Filament\Resources\EvidenceSnapshotResource::getUrl('view', ['record' => $this->record->evidenceSnapshot], tenant: $this->record->tenant) : null), UiEnforcement::forAction( Actions\Action::make('refresh_review') ->label('Refresh review') ->icon('heroicon-o-arrow-path') ->hidden(fn (): bool => ! $this->record->isMutable()) ->requiresConfirmation() ->action(function (): void { $user = auth()->user(); if (! $user instanceof User) { abort(403); } try { app(TenantReviewService::class)->refresh($this->record, $user); } catch (\Throwable $throwable) { Notification::make()->danger()->title('Unable to refresh review')->body($throwable->getMessage())->send(); return; } Notification::make()->success()->title('Refresh review queued')->send(); }), ) ->requireCapability(Capabilities::TENANT_REVIEW_MANAGE) ->preserveVisibility() ->apply(), UiEnforcement::forAction( Actions\Action::make('publish_review') ->label('Publish review') ->icon('heroicon-o-check-badge') ->hidden(fn (): bool => ! $this->record->isMutable()) ->requiresConfirmation() ->action(function (): void { $user = auth()->user(); if (! $user instanceof User) { abort(403); } try { app(TenantReviewLifecycleService::class)->publish($this->record, $user); } catch (\Throwable $throwable) { Notification::make()->danger()->title('Unable to publish review')->body($throwable->getMessage())->send(); return; } $this->refreshFormData(['status', 'published_at', 'published_by_user_id', 'summary']); Notification::make()->success()->title('Review published')->send(); }), ) ->requireCapability(Capabilities::TENANT_REVIEW_MANAGE) ->preserveVisibility() ->apply(), UiEnforcement::forAction( Actions\Action::make('export_executive_pack') ->label('Export executive pack') ->icon('heroicon-o-arrow-down-tray') ->hidden(fn (): bool => ! in_array($this->record->status, [ TenantReviewStatus::Ready->value, TenantReviewStatus::Published->value, ], true)) ->action(fn (): mixed => TenantReviewResource::executeExport($this->record)), ) ->requireCapability(Capabilities::TENANT_REVIEW_MANAGE) ->preserveVisibility() ->apply(), Actions\ActionGroup::make([ UiEnforcement::forAction( Actions\Action::make('create_next_review') ->label('Create next review') ->icon('heroicon-o-document-duplicate') ->hidden(fn (): bool => ! $this->record->isPublished()) ->action(function (): void { $user = auth()->user(); if (! $user instanceof User) { abort(403); } try { $nextReview = app(TenantReviewLifecycleService::class)->createNextReview($this->record, $user); } catch (\Throwable $throwable) { Notification::make()->danger()->title('Unable to create next review')->body($throwable->getMessage())->send(); return; } $this->redirect(TenantReviewResource::tenantScopedUrl('view', ['record' => $nextReview], $nextReview->tenant)); }), ) ->requireCapability(Capabilities::TENANT_REVIEW_MANAGE) ->preserveVisibility() ->apply(), UiEnforcement::forAction( Actions\Action::make('archive_review') ->label('Archive review') ->icon('heroicon-o-archive-box') ->color('danger') ->hidden(fn (): bool => $this->record->statusEnum()->isTerminal()) ->requiresConfirmation() ->action(function (): void { $user = auth()->user(); if (! $user instanceof User) { abort(403); } app(TenantReviewLifecycleService::class)->archive($this->record, $user); $this->refreshFormData(['status', 'archived_at']); Notification::make()->success()->title('Review archived')->send(); }), ) ->requireCapability(Capabilities::TENANT_REVIEW_MANAGE) ->preserveVisibility() ->apply(), ]) ->label('More') ->icon('heroicon-m-ellipsis-vertical') ->color('gray'), ]; } }