TenantAtlas/apps/platform/resources/views/filament/widgets/dashboard/tenant-dashboard-overview.blade.php
Ahmed Darrazi beebbaefbe
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 5m58s
chore: commit all local changes
2026-05-03 16:00:44 +02:00

283 lines
18 KiB
PHP

@php
$overviewSecondaryListStackClasses = 'flex flex-col gap-2';
$overviewSecondaryListRowBaseClasses = 'min-w-0 rounded-xl border p-4 shadow-sm';
$overviewSecondaryListRowSurfaceClasses = 'border-gray-200 bg-white/80 dark:border-white/10 dark:bg-white/5';
$overviewSecondaryListInteractiveClasses = 'transition duration-150 hover:shadow-md hover:ring-1 hover:ring-gray-950/5 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50 dark:hover:ring-white/10';
@endphp
<div
@if ($pollingInterval)
wire:poll.{{ $pollingInterval }}
@endif
data-testid="tenant-dashboard-overview"
class="grid w-full min-w-0 gap-6 xl:grid-cols-12"
style="grid-column: 1 / -1;"
>
<!-- Left Column (Main) -->
<div data-testid="tenant-dashboard-overview-main" class="flex w-full min-w-0 flex-col gap-6 xl:col-span-8">
<!-- Recommended Actions -->
<x-filament::section :heading="__('localization.dashboard.overview.section_recommended_actions')">
@if ($recommendedActions === [])
<div data-testid="tenant-dashboard-recommended-actions-empty" class="rounded-xl border border-success-200 bg-success-50/80 p-5 dark:border-success-800 dark:bg-success-500/10">
<div class="text-sm font-semibold text-success-700 dark:text-success-300">{{ __('localization.dashboard.overview.empty_recommended_actions_headline') }}</div>
<p class="mt-2 text-sm leading-6 text-success-700/90 dark:text-success-200/90">
{{ __('localization.dashboard.overview.empty_recommended_actions_summary') }}
</p>
</div>
@else
<div data-testid="tenant-dashboard-recommended-actions" class="grid min-w-0 gap-4">
@foreach (array_slice($recommendedActions, 0, 3) as $index => $action)
<div data-testid="tenant-dashboard-recommended-action" data-action-key="{{ $action['key'] }}" class="flex min-w-0 items-start gap-4 rounded-xl border border-gray-200 bg-white p-5 shadow-sm dark:border-white/10 dark:bg-white/5 max-sm:flex-col max-sm:items-stretch">
<div data-testid="tenant-dashboard-recommended-action-priority" class="flex h-8 w-8 shrink-0 items-center justify-center rounded-full border border-gray-200 bg-gray-50 text-sm font-semibold text-gray-700 dark:border-white/10 dark:bg-white/5 dark:text-gray-200">
{{ $index + 1 }}
</div>
<div class="flex-1 min-w-0">
<div class="flex items-center gap-2">
@if (filled($action['icon'] ?? null))
<x-filament::icon
data-testid="tenant-dashboard-recommended-action-icon"
data-action-key="{{ $action['key'] }}"
data-icon="{{ $action['icon'] }}"
:icon="$action['icon']"
class="h-4 w-4 shrink-0 text-gray-400 dark:text-gray-500"
/>
@endif
<h3 class="min-w-0 text-sm font-semibold text-gray-950 dark:text-white">{{ $action['title'] }}</h3>
</div>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
<span class="font-medium text-gray-700 dark:text-gray-300">Reason:</span> {{ $action['reason'] }}
</p>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-500">
<span class="font-medium text-gray-700 dark:text-gray-300">Impact:</span> {{ $action['impact'] }}
</p>
</div>
@if (filled($action['actionUrl'] ?? null))
<div class="shrink-0 max-sm:ml-0 sm:ml-4">
<x-filament::button data-testid="tenant-dashboard-secondary-action" :href="$action['actionUrl']" tag="a" color="gray" size="sm">
{{ $action['actionLabel'] ?? 'Review' }}
</x-filament::button>
</div>
@endif
</div>
@endforeach
</div>
@endif
</x-filament::section>
<!-- Governance Status -->
<x-filament::section :heading="__('localization.dashboard.overview.section_governance_status')">
<div class="{{ $overviewSecondaryListStackClasses }}">
@foreach ($governanceStatus as $status)
@php
$isGovernanceStatusInteractive = filled($status['actionUrl'] ?? null);
$governanceStatusClasses = $isGovernanceStatusInteractive
? "{$overviewSecondaryListRowBaseClasses} {$overviewSecondaryListRowSurfaceClasses} {$overviewSecondaryListInteractiveClasses} flex items-start justify-between gap-4"
: "{$overviewSecondaryListRowBaseClasses} {$overviewSecondaryListRowSurfaceClasses} flex items-start justify-between gap-4";
@endphp
@if ($isGovernanceStatusInteractive)
<a
data-testid="tenant-dashboard-governance-status"
data-overview-row-style="secondary-list-row"
data-status-key="{{ $status['key'] ?? '' }}"
data-governance-interactive="true"
href="{{ $status['actionUrl'] }}"
class="{{ $governanceStatusClasses }}"
>
<div class="min-w-0">
<div class="flex items-center gap-2 min-w-0">
@if (filled($status['icon'] ?? null))
<x-filament::icon
data-testid="tenant-dashboard-governance-status-icon"
data-status-key="{{ $status['key'] ?? '' }}"
data-icon="{{ $status['icon'] }}"
:icon="$status['icon']"
class="h-4 w-4 shrink-0 text-gray-400 dark:text-gray-500"
/>
@endif
<div class="truncate text-sm font-semibold text-gray-900 dark:text-white">{{ $status['label'] }}</div>
</div>
<div class="mt-1 text-xs text-gray-500 dark:text-gray-400">{{ $status['description'] }}</div>
</div>
<div class="ml-4 shrink-0 pt-0.5">
<x-filament::badge :color="$status['tone']">{{ $status['value'] }}</x-filament::badge>
</div>
</a>
@else
<div
data-testid="tenant-dashboard-governance-status"
data-overview-row-style="secondary-list-row"
data-status-key="{{ $status['key'] ?? '' }}"
data-governance-interactive="false"
class="{{ $governanceStatusClasses }}"
>
<div class="min-w-0">
<div class="flex items-center gap-2 min-w-0">
@if (filled($status['icon'] ?? null))
<x-filament::icon
data-testid="tenant-dashboard-governance-status-icon"
data-status-key="{{ $status['key'] ?? '' }}"
data-icon="{{ $status['icon'] }}"
:icon="$status['icon']"
class="h-4 w-4 shrink-0 text-gray-400 dark:text-gray-500"
/>
@endif
<div class="truncate text-sm font-semibold text-gray-900 dark:text-white">{{ $status['label'] }}</div>
</div>
<div class="mt-1 text-xs text-gray-500 dark:text-gray-400">{{ $status['description'] }}</div>
</div>
<div class="ml-4 shrink-0 pt-0.5">
<x-filament::badge :color="$status['tone']">{{ $status['value'] }}</x-filament::badge>
</div>
</div>
@endif
@endforeach
</div>
</x-filament::section>
<!-- Recent Operations -->
<x-filament::section :heading="__('localization.dashboard.overview.section_recent_operations')">
@if ($recentOperations === [])
<div data-testid="tenant-dashboard-recent-operations-empty" class="rounded-xl border border-gray-200 bg-gray-50 p-5 dark:border-white/10 dark:bg-white/5">
<div class="text-sm font-semibold text-gray-950 dark:text-white">{{ __('localization.dashboard.overview.empty_recent_operations_headline') }}</div>
<p class="mt-2 text-sm leading-6 text-gray-600 dark:text-gray-400">
{{ __('localization.dashboard.overview.empty_recent_operations_summary') }}
</p>
</div>
@else
<div class="flex flex-col gap-3">
@foreach (array_slice($recentOperations, 0, 4) as $operation)
@php
$operationTone = match ($operation['outcomeTone']) {
'danger' => 'border-danger-200 bg-danger-50/10 dark:border-danger-800 dark:bg-danger-500/5',
'warning' => 'border-warning-200 bg-warning-50/10 dark:border-warning-800 dark:bg-warning-500/5',
default => $overviewSecondaryListRowSurfaceClasses,
};
@endphp
<a
data-testid="tenant-dashboard-recent-operation"
data-overview-row-style="secondary-list-row"
href="{{ $operation['url'] }}"
class="{{ $overviewSecondaryListRowBaseClasses }} {{ $overviewSecondaryListInteractiveClasses }} {{ $operationTone }}"
>
<div class="flex items-start justify-between gap-3">
<div class="min-w-0">
<div class="flex items-center gap-2">
@if (filled($operation['icon'] ?? null))
<x-filament::icon
data-testid="tenant-dashboard-recent-operation-icon"
data-operation-id="{{ $operation['id'] }}"
data-icon="{{ $operation['icon'] }}"
:icon="$operation['icon']"
class="h-4 w-4 shrink-0 text-gray-400 dark:text-gray-500"
/>
@endif
<div class="text-sm font-semibold text-gray-950 dark:text-white">{{ $operation['type'] }}</div>
<x-filament::badge :color="$operation['statusTone']">{{ $operation['statusLabel'] }}</x-filament::badge>
<x-filament::badge :color="$operation['outcomeTone']">{{ $operation['outcomeLabel'] }}</x-filament::badge>
</div>
<div class="mt-1 text-xs text-gray-500 dark:text-gray-400">
{{ $operation['summary'] }}
</div>
</div>
<div class="shrink-0 text-xs font-medium text-gray-500 dark:text-gray-400">
@if ($operation['createdAt']) {{ $operation['createdAt'] }} @endif
</div>
</div>
</a>
@endforeach
</div>
@endif
</x-filament::section>
</div>
<!-- Right Column (Aside) -->
<div data-testid="tenant-dashboard-overview-aside" class="flex w-full min-w-0 flex-col gap-6 xl:col-span-4">
@foreach ($readinessCards as $card)
@php
$cardMeta = array_values(array_filter($card['meta'] ?? []));
$headline = $card['headline'] ?? null;
$cardProgress = array_values(array_filter($card['progress'] ?? []));
@endphp
<div data-testid="tenant-dashboard-readiness-card" data-readiness-key="{{ $card['key'] }}" class="min-w-0 rounded-xl border border-gray-200 bg-white p-4 shadow-sm dark:border-white/10 dark:bg-white/5">
<div class="flex items-start justify-between gap-3">
<div class="min-w-0">
<div class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ $card['title'] }}</div>
@if (filled($headline))
<div class="mt-1 text-base font-semibold text-gray-950 dark:text-white">{{ $headline }}</div>
@else
<div class="mt-1 text-base font-semibold text-gray-950 dark:text-white">{{ $card['status'] }}</div>
@endif
</div>
<x-filament::badge :color="$card['tone']">{{ $card['status'] }}</x-filament::badge>
</div>
<p class="mt-3 text-sm leading-6 text-gray-600 dark:text-gray-400">{{ $card['body'] }}</p>
@if ($cardProgress !== [])
<div class="mt-3 space-y-3">
@foreach ($cardProgress as $progress)
@php
$progressBarColor = match ($progress['tone'] ?? 'primary') {
'success' => 'var(--success-500)',
'warning' => 'var(--warning-500)',
'danger' => 'var(--danger-500)',
default => 'var(--primary-500)',
};
@endphp
<div data-progress-key="{{ $progress['key'] }}" class="space-y-1.5">
<div class="flex items-center justify-between gap-3 text-xs">
<span class="truncate text-gray-500 dark:text-gray-400">{{ $progress['label'] }}</span>
<span class="shrink-0 font-medium text-gray-700 dark:text-gray-200">{{ $progress['valueLabel'] }}</span>
</div>
<div class="overflow-hidden rounded-full bg-gray-100 dark:bg-white/10" style="height: 0.5rem;">
<div
class="block h-full rounded-full"
role="progressbar"
aria-label="{{ $progress['label'] }}"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="{{ $progress['percent'] }}"
aria-valuetext="{{ $progress['valueLabel'] }}"
style="width: {{ $progress['percent'] }}%; background-color: {{ $progressBarColor }};"
></div>
</div>
</div>
@endforeach
</div>
@endif
@if ($cardMeta !== [])
<div class="mt-3 grid gap-2 text-xs">
@foreach ($cardMeta as $item)
<div class="flex items-center justify-between gap-3 rounded-lg bg-gray-50/80 px-3 py-2 text-gray-600 dark:bg-white/5 dark:text-gray-300">
<span class="truncate text-gray-500 dark:text-gray-400">{{ $item['label'] }}</span>
<span class="shrink-0 font-medium text-gray-700 dark:text-gray-200">{{ $item['value'] }}</span>
</div>
@endforeach
</div>
@endif
@if (filled($card['actionLabel'] ?? null))
<div class="mt-4">
@if (filled($card['actionUrl'] ?? null))
<x-filament::button data-testid="tenant-dashboard-secondary-action" tag="a" :href="$card['actionUrl']" size="sm" color="gray">
{{ $card['actionLabel'] }}
</x-filament::button>
@else
<x-filament::button data-testid="tenant-dashboard-secondary-action" size="sm" color="gray" disabled>
{{ $card['actionLabel'] }}
</x-filament::button>
@endif
</div>
@endif
</div>
@endforeach
</div>
</div>