TenantAtlas/apps/platform/resources/views/filament/pages/governance/governance-inbox.blade.php
Ahmed Darrazi b1962ece80
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 1m42s
feat: productize governance inbox decision-first workbench
2026-05-18 18:13:00 +02:00

330 lines
21 KiB
PHP

<x-filament-panels::page>
@php
$scope = $this->appliedScope();
$sections = $this->sections();
$emptyState = $this->calmEmptyState();
$workbench = $this->decisionWorkbench();
$selectedItem = $workbench['selected_item'] ?? null;
$diagnostics = $workbench['diagnostics'] ?? [];
@endphp
<div class="space-y-6">
<div class="space-y-3" data-testid="governance-inbox-secondary-filters">
<div class="flex flex-wrap gap-2 text-sm text-gray-600 dark:text-gray-300">
@if (filled($scope['workspace_label'] ?? null))
<span class="inline-flex items-center rounded-md bg-gray-100 px-2.5 py-1 text-xs font-medium text-gray-700 dark:bg-gray-800 dark:text-gray-200">
Workspace: {{ $scope['workspace_label'] }}
</span>
@endif
<span class="inline-flex items-center rounded-md bg-gray-100 px-2.5 py-1 text-xs font-medium text-gray-700 dark:bg-gray-800 dark:text-gray-200">
Scope: {{ $scope['family_label'] ?? 'All attention' }}
</span>
<span class="inline-flex items-center rounded-md bg-gray-100 px-2.5 py-1 text-xs font-medium text-gray-700 dark:bg-gray-800 dark:text-gray-200">
Visible items: {{ $scope['total_count'] ?? 0 }}
</span>
@if (filled($scope['tenant_label'] ?? null))
<span class="inline-flex items-center rounded-md bg-warning-50 px-2.5 py-1 text-xs font-medium text-warning-700 dark:bg-warning-500/10 dark:text-warning-300">
Environment: {{ $scope['tenant_label'] }}
</span>
@endif
</div>
@if ($this->hasTenantPrefilter())
@include('filament.partials.workspace-hub-environment-filter-chip', [
'label' => $scope['tenant_label'] ?? null,
'clearUrl' => $this->pageUrl(['environment_id' => null, 'family' => null]),
])
@endif
<div class="flex flex-wrap gap-2" data-testid="governance-inbox-family-filters">
<a
href="{{ $this->pageUrl(['family' => null]) }}"
class="inline-flex items-center gap-2 rounded-md border px-2.5 py-1 text-xs font-medium transition {{ $this->family === null ? 'border-primary-300 bg-primary-50 text-primary-700 dark:border-primary-700/60 dark:bg-primary-950/40 dark:text-primary-300' : 'border-gray-200 text-gray-700 hover:border-gray-300 dark:border-gray-700 dark:text-gray-200 dark:hover:border-gray-600' }}"
>
All attention
<span class="rounded-md bg-black/5 px-2 py-0.5 text-xs dark:bg-white/10">{{ $scope['total_count'] ?? 0 }}</span>
</a>
@foreach ($this->availableFamilies() as $family)
<a
href="{{ $this->pageUrl(['family' => $family['key']]) }}"
class="inline-flex items-center gap-2 rounded-md border px-2.5 py-1 text-xs font-medium transition {{ $this->isActiveFamily($family['key']) ? 'border-primary-300 bg-primary-50 text-primary-700 dark:border-primary-700/60 dark:bg-primary-950/40 dark:text-primary-300' : 'border-gray-200 text-gray-700 hover:border-gray-300 dark:border-gray-700 dark:text-gray-200 dark:hover:border-gray-600' }}"
>
{{ $family['label'] }}
<span class="rounded-md bg-black/5 px-2 py-0.5 text-xs dark:bg-white/10">{{ $family['count'] }}</span>
</a>
@endforeach
</div>
</div>
<div class="grid grid-cols-1 gap-6 lg:grid-cols-[minmax(0,1fr)_22rem]" data-testid="governance-inbox-decision-workbench">
<section class="rounded-lg border border-gray-200 bg-white p-5 shadow-sm dark:border-gray-800 dark:bg-gray-900" data-testid="governance-inbox-priority-card">
<div class="flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
<div class="space-y-2">
<p class="text-xs font-medium uppercase text-gray-500 dark:text-gray-400">
Decision workbench
</p>
<h2 class="text-xl font-semibold text-gray-950 dark:text-white">
{{ $workbench['question'] }}
</h2>
</div>
@if ($selectedItem !== null)
<span class="inline-flex w-fit items-center rounded-lg bg-warning-50 px-2.5 py-1 text-xs font-medium text-warning-700 dark:bg-warning-500/10 dark:text-warning-300">
{{ $selectedItem['status_label'] }}
</span>
@endif
</div>
@if ($selectedItem === null)
<div class="mt-5 rounded-lg border border-dashed border-gray-300 bg-gray-50 p-5 dark:border-gray-700 dark:bg-gray-950/40" data-testid="governance-inbox-empty-decision-state">
<h3 class="text-base font-semibold text-gray-950 dark:text-white">
{{ $emptyState['title'] }}
</h3>
<p class="mt-1 text-sm leading-6 text-gray-600 dark:text-gray-300">
{{ $emptyState['body'] }}
</p>
@if (filled($emptyState['action_label'] ?? null) && filled($emptyState['action_url'] ?? null))
<div class="mt-4">
<x-filament::button tag="a" color="gray" href="{{ $emptyState['action_url'] }}">
{{ $emptyState['action_label'] }}
</x-filament::button>
</div>
@endif
</div>
@else
<div class="mt-5 space-y-5">
<div class="space-y-2">
<div class="flex flex-wrap items-center gap-2">
<span class="inline-flex items-center rounded-lg bg-gray-100 px-2.5 py-1 text-xs font-medium text-gray-700 dark:bg-gray-800 dark:text-gray-200">
{{ $selectedItem['section_label'] }}
</span>
<span class="inline-flex items-center rounded-lg bg-gray-100 px-2.5 py-1 text-xs font-medium text-gray-700 dark:bg-gray-800 dark:text-gray-200">
Environment: {{ $selectedItem['environment_label'] }}
</span>
</div>
<h3 class="text-lg font-semibold text-gray-950 dark:text-white">
{{ $selectedItem['title'] }}
</h3>
<p class="text-sm leading-6 text-gray-600 dark:text-gray-300">
{{ $selectedItem['decision_label'] }}
</p>
</div>
<dl class="grid grid-cols-1 gap-3 md:grid-cols-2">
<div class="rounded-lg border border-gray-200 p-3 dark:border-gray-800">
<dt class="text-xs font-medium text-gray-500 dark:text-gray-400">Reason</dt>
<dd class="mt-1 text-sm leading-6 text-gray-800 dark:text-gray-100">{{ $selectedItem['reason_label'] }}</dd>
</div>
<div class="rounded-lg border border-gray-200 p-3 dark:border-gray-800">
<dt class="text-xs font-medium text-gray-500 dark:text-gray-400">Impact</dt>
<dd class="mt-1 text-sm leading-6 text-gray-800 dark:text-gray-100">{{ $selectedItem['impact_label'] }}</dd>
</div>
<div class="rounded-lg border border-gray-200 p-3 dark:border-gray-800">
<dt class="text-xs font-medium text-gray-500 dark:text-gray-400">Owner</dt>
<dd class="mt-1 text-sm leading-6 text-gray-800 dark:text-gray-100">{{ $selectedItem['owner_label'] }}</dd>
</div>
<div class="rounded-lg border border-gray-200 p-3 dark:border-gray-800">
<dt class="text-xs font-medium text-gray-500 dark:text-gray-400">Due</dt>
<dd class="mt-1 text-sm leading-6 text-gray-800 dark:text-gray-100">{{ $selectedItem['due_label'] }}</dd>
</div>
</dl>
<div class="grid grid-cols-1 gap-3 md:grid-cols-2">
<div class="rounded-lg border border-gray-200 p-3 dark:border-gray-800">
<p class="text-xs font-medium text-gray-500 dark:text-gray-400">Evidence</p>
<p class="mt-1 text-sm leading-6 text-gray-800 dark:text-gray-100">{{ $selectedItem['evidence_label'] }}</p>
</div>
<div class="rounded-lg border border-gray-200 p-3 dark:border-gray-800">
<p class="text-xs font-medium text-gray-500 dark:text-gray-400">Accepted risk</p>
<p class="mt-1 text-sm leading-6 text-gray-800 dark:text-gray-100">{{ $selectedItem['exception_label'] }}</p>
</div>
</div>
@if (filled($selectedItem['primary_action_url'] ?? null))
<div class="flex flex-col gap-2 rounded-lg border border-gray-200 p-3 dark:border-gray-800 sm:flex-row sm:items-center sm:justify-between">
<div>
<p class="text-xs font-medium text-gray-500 dark:text-gray-400">Primary next action</p>
<p class="mt-1 text-sm leading-6 text-gray-800 dark:text-gray-100">{{ $selectedItem['primary_action_label'] }}</p>
</div>
<x-filament::button
tag="a"
href="{{ $selectedItem['primary_action_url'] }}"
icon="heroicon-o-arrow-top-right-on-square"
>
{{ $selectedItem['primary_action_label'] }}
</x-filament::button>
</div>
@endif
</div>
@endif
</section>
<aside class="rounded-lg border border-gray-200 bg-white p-5 shadow-sm dark:border-gray-800 dark:bg-gray-900" data-testid="governance-inbox-decision-detail">
<div class="space-y-4">
<div class="space-y-1">
<p class="text-xs font-medium uppercase text-gray-500 dark:text-gray-400">Decision summary</p>
<h2 class="text-base font-semibold text-gray-950 dark:text-white">
{{ $selectedItem['title'] ?? 'No selected decision' }}
</h2>
</div>
@if ($selectedItem !== null)
<div class="space-y-3 text-sm">
<div>
<p class="text-xs font-medium text-gray-500 dark:text-gray-400">Impact</p>
<p class="mt-1 text-gray-800 dark:text-gray-100">{{ $selectedItem['impact_label'] }}</p>
</div>
<div>
<p class="text-xs font-medium text-gray-500 dark:text-gray-400">Evidence path</p>
@if (filled($selectedItem['evidence_path_url'] ?? null))
<a href="{{ $selectedItem['evidence_path_url'] }}" class="mt-1 inline-flex items-center gap-1 text-sm font-medium text-primary-600 hover:underline dark:text-primary-300">
{{ $selectedItem['evidence_path_label'] }}
<x-filament::icon icon="heroicon-m-arrow-top-right-on-square" class="h-4 w-4" />
</a>
@else
<p class="mt-1 text-gray-800 dark:text-gray-100">{{ $selectedItem['evidence_path_label'] }}</p>
@endif
</div>
<div>
<p class="text-xs font-medium text-gray-500 dark:text-gray-400">Accepted risk</p>
<p class="mt-1 text-gray-800 dark:text-gray-100">{{ $selectedItem['exception_label'] }}</p>
</div>
<div>
<p class="text-xs font-medium text-gray-500 dark:text-gray-400">Owner / due</p>
<p class="mt-1 text-gray-800 dark:text-gray-100">{{ $selectedItem['owner_label'] }} · {{ $selectedItem['due_label'] }}</p>
</div>
</div>
@if (filled($selectedItem['primary_action_url'] ?? null))
<div class="space-y-2">
<p class="text-xs font-medium text-gray-500 dark:text-gray-400">Primary next action</p>
<x-filament::button
tag="a"
color="gray"
href="{{ $selectedItem['primary_action_url'] }}"
icon="heroicon-o-arrow-top-right-on-square"
class="w-full"
>
{{ $selectedItem['primary_action_label'] }}
</x-filament::button>
</div>
@endif
@else
<div class="space-y-3 text-sm">
<div>
<p class="text-xs font-medium text-gray-500 dark:text-gray-400">Impact</p>
<p class="mt-1 text-gray-800 dark:text-gray-100">Unavailable</p>
</div>
<div>
<p class="text-xs font-medium text-gray-500 dark:text-gray-400">Owner / due</p>
<p class="mt-1 text-gray-800 dark:text-gray-100">Unavailable</p>
</div>
<div>
<p class="text-xs font-medium text-gray-500 dark:text-gray-400">Evidence path</p>
<p class="mt-1 text-gray-800 dark:text-gray-100">Unavailable</p>
</div>
<div>
<p class="text-xs font-medium text-gray-500 dark:text-gray-400">Accepted risk</p>
<p class="mt-1 text-gray-800 dark:text-gray-100">Unavailable</p>
</div>
<div>
<p class="text-xs font-medium text-gray-500 dark:text-gray-400">Primary next action</p>
<p class="mt-1 text-gray-800 dark:text-gray-100">No action available</p>
</div>
</div>
@endif
<details class="rounded-lg border border-gray-200 p-3 dark:border-gray-800" data-testid="governance-inbox-diagnostics">
<summary class="cursor-pointer text-sm font-medium text-gray-700 dark:text-gray-200">
{{ $diagnostics['label'] ?? 'Diagnostics' }} · {{ $diagnostics['state'] ?? 'Collapsed' }}
</summary>
<p class="mt-3 text-sm leading-6 text-gray-600 dark:text-gray-300">
{{ $diagnostics['body'] ?? 'Diagnostics are not default-visible.' }}
</p>
</details>
</div>
</aside>
</div>
@if ($sections !== [])
<div class="space-y-4" data-testid="governance-inbox-queue-context">
<div class="flex flex-col gap-1">
<h2 class="text-lg font-semibold text-gray-950 dark:text-white">Queue context</h2>
<p class="text-sm leading-6 text-gray-600 dark:text-gray-300">
Secondary source-family context remains available after the priority decision.
</p>
</div>
@foreach ($sections as $section)
<div class="rounded-lg border border-gray-200 bg-white p-5 dark:border-gray-800 dark:bg-gray-900">
<div class="flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between">
<div class="space-y-2">
<div class="flex flex-wrap items-center gap-2">
<h3 class="text-base font-semibold text-gray-950 dark:text-white">{{ $section['label'] }}</h3>
<span class="inline-flex items-center rounded-lg bg-gray-100 px-2.5 py-1 text-xs font-medium text-gray-700 dark:bg-gray-800 dark:text-gray-200">
{{ $section['count'] }}
</span>
</div>
<p class="max-w-3xl text-sm leading-6 text-gray-600 dark:text-gray-300">{{ $section['summary'] }}</p>
</div>
<x-filament::button tag="a" color="gray" href="{{ $section['dominant_action_url'] }}">
{{ $section['dominant_action_label'] }}
</x-filament::button>
</div>
@if ($section['count'] === 0)
<div class="mt-4 rounded-lg border border-dashed border-gray-300 bg-gray-50 p-4 text-sm leading-6 text-gray-600 dark:border-gray-700 dark:bg-gray-950/50 dark:text-gray-300">
{{ $section['empty_state'] }}
</div>
@else
<ul class="mt-4 grid gap-3">
@foreach ($section['entries'] as $entry)
<li class="rounded-lg border border-gray-200 p-4 dark:border-gray-800">
<div class="flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between">
<div class="space-y-1.5">
@if (filled($entry['tenant_label'] ?? null))
<div class="text-xs font-medium uppercase text-gray-500 dark:text-gray-400">
{{ $entry['tenant_label'] }}
</div>
@endif
<div class="flex flex-wrap items-center gap-2">
<a href="{{ $entry['destination_url'] }}" class="text-sm font-semibold text-gray-950 hover:text-primary-600 dark:text-white dark:hover:text-primary-300">
{{ $entry['headline'] }}
</a>
<span class="inline-flex items-center rounded-lg bg-gray-100 px-2.5 py-1 text-xs font-medium text-gray-700 dark:bg-gray-800 dark:text-gray-200">
{{ $entry['status_label'] }}
</span>
</div>
@if (filled($entry['subline'] ?? null))
<p class="text-sm leading-6 text-gray-600 dark:text-gray-300">{{ $entry['subline'] }}</p>
@endif
</div>
<x-filament::button tag="a" color="gray" size="sm" href="{{ $entry['destination_url'] }}">
Open source
</x-filament::button>
</div>
</li>
@endforeach
</ul>
@endif
</div>
@endforeach
</div>
@endif
</div>
</x-filament-panels::page>