## Summary - add tenant triage review-state persistence, fingerprinting, resolver logic, service layer, and migration for current affected-set tracking - surface review-state and affected-set progress across tenant registry, tenant dashboard arrival continuity, and workspace overview - extend RBAC, audit/badge support, specs, and test coverage for portfolio triage review-state workflows - suppress expected hidden-page background transport failures in the global unhandled rejection logger while keeping visible-page failures logged ## Validation - targeted Pest coverage added for tenant registry, workspace overview, arrival context, RBAC authorization, badges, fingerprinting, resolver behavior, and logger asset behavior - code formatted with `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` ## Notes - full suite was not re-run in this final step - branch includes the spec artifacts under `specs/189-portfolio-triage-review-state/` Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #220
134 lines
6.7 KiB
PHP
134 lines
6.7 KiB
PHP
@php
|
|
/** @var ?\App\Support\PortfolioTriage\PortfolioArrivalContext $context */
|
|
/** @var array<string, mixed>|null $reviewState */
|
|
@endphp
|
|
|
|
<div>
|
|
@if ($context)
|
|
@php
|
|
$familyColor = $context->concernFamily === 'backup_health' ? 'danger' : 'warning';
|
|
$stateColor = match ($context->concernState) {
|
|
'absent' => 'danger',
|
|
'stale', 'degraded', 'weakened', 'unvalidated' => 'warning',
|
|
default => 'gray',
|
|
};
|
|
$reviewStateColor = \App\Support\Badges\BadgeRenderer::color(\App\Support\Badges\BadgeDomain::TenantTriageReviewState)($reviewState['derived_state'] ?? null);
|
|
$reviewStateLabel = \App\Support\Badges\BadgeRenderer::label(\App\Support\Badges\BadgeDomain::TenantTriageReviewState)($reviewState['derived_state'] ?? null);
|
|
@endphp
|
|
|
|
<x-filament::section>
|
|
<x-slot name="heading">
|
|
<span class="flex items-center gap-2">
|
|
<x-filament::icon
|
|
icon="heroicon-m-arrow-trending-up"
|
|
class="h-5 w-5 text-warning-500"
|
|
/>
|
|
Triage arrival
|
|
</span>
|
|
</x-slot>
|
|
|
|
<div class="flex flex-col gap-4">
|
|
<div class="flex flex-wrap items-start justify-between gap-4">
|
|
<div class="min-w-0 flex-1">
|
|
<div class="flex flex-wrap gap-2">
|
|
<x-filament::badge color="gray" size="sm">
|
|
{{ $context->sourceLabel() }}
|
|
</x-filament::badge>
|
|
|
|
<x-filament::badge :color="$familyColor" size="sm">
|
|
{{ $context->concernFamilyLabel() }}
|
|
</x-filament::badge>
|
|
|
|
<x-filament::badge :color="$stateColor" size="sm">
|
|
{{ $context->concernStateLabel() }}
|
|
</x-filament::badge>
|
|
</div>
|
|
|
|
<div class="mt-3 text-sm font-semibold text-gray-950 dark:text-white">
|
|
Why this tenant opened
|
|
</div>
|
|
|
|
<div class="mt-1 text-sm leading-relaxed text-gray-600 dark:text-gray-300">
|
|
{{ $context->arrivalSummary }}
|
|
</div>
|
|
|
|
@if (is_array($reviewState) && ($reviewState['current_concern_present'] ?? false) === true)
|
|
<div class="mt-3 flex flex-wrap items-center gap-2">
|
|
<x-filament::badge :color="$reviewStateColor" size="sm">
|
|
{{ $reviewStateLabel }}
|
|
</x-filament::badge>
|
|
|
|
<span class="text-xs text-gray-500 dark:text-gray-400">
|
|
{{ $context->concernFamilyLabel() }} review state
|
|
@if (filled($reviewState['reviewed_by_user_name'] ?? null))
|
|
by {{ $reviewState['reviewed_by_user_name'] }}
|
|
@endif
|
|
@if (($reviewState['reviewed_at'] ?? null) instanceof \Illuminate\Support\Carbon)
|
|
· {{ $reviewState['reviewed_at']->diffForHumans() }}
|
|
@endif
|
|
</span>
|
|
</div>
|
|
@endif
|
|
|
|
@if (filled($context->currentTruthDelta))
|
|
<div class="mt-3 rounded-lg bg-gray-50 p-3 text-sm text-gray-700 dark:bg-white/5 dark:text-gray-200">
|
|
{{ $context->currentTruthDelta }}
|
|
</div>
|
|
@endif
|
|
|
|
@if (filled($context->claimBoundary))
|
|
<div class="mt-3 text-xs leading-relaxed text-gray-500 dark:text-gray-400">
|
|
{{ $context->claimBoundary }}
|
|
</div>
|
|
@endif
|
|
</div>
|
|
|
|
<div class="flex w-full flex-col gap-2 sm:w-auto sm:min-w-52 sm:items-end">
|
|
@if (filled($context->nextStep['url'] ?? null))
|
|
<x-filament::button
|
|
tag="a"
|
|
:href="$context->nextStep['url']"
|
|
size="sm"
|
|
color="warning"
|
|
>
|
|
{{ $context->nextStep['label'] }}
|
|
</x-filament::button>
|
|
@elseif (($context->nextStep['disabled'] ?? false) === true)
|
|
<div class="text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">
|
|
{{ $context->nextStep['label'] }}
|
|
</div>
|
|
@endif
|
|
|
|
@if (filled($context->returnTarget['url'] ?? null))
|
|
<x-filament::link :href="$context->returnTarget['url']" size="sm" class="font-medium">
|
|
{{ $context->returnTarget['label'] }}
|
|
</x-filament::link>
|
|
@endif
|
|
|
|
@if (filled($context->nextStep['helperText'] ?? null))
|
|
<div class="text-xs text-gray-500 dark:text-gray-400">
|
|
{{ $context->nextStep['helperText'] }}
|
|
</div>
|
|
@endif
|
|
|
|
@if (is_array($reviewState) && ($reviewState['current_concern_present'] ?? false) === true)
|
|
<div class="rounded-lg border border-gray-200 bg-white/80 p-3 text-xs text-gray-600 dark:border-white/10 dark:bg-white/5 dark:text-gray-300">
|
|
TenantPilot only. Review state tracks shared triage progress and never changes backup posture or recovery evidence.
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
|
|
@if (is_array($reviewState) && ($reviewState['current_concern_present'] ?? false) === true)
|
|
<div class="flex flex-wrap items-center gap-2 border-t border-gray-200 pt-4 dark:border-white/10">
|
|
{{ $this->markReviewedAction }}
|
|
{{ $this->markFollowUpNeededAction }}
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</x-filament::section>
|
|
|
|
<x-filament-actions::modals />
|
|
@endif
|
|
</div>
|