TenantAtlas/apps/platform/resources/views/filament/widgets/dashboard/recovery-readiness.blade.php
ahmido f1a73490e4 feat: finalize dashboard recovery honesty (#215)
## Summary
- add a dedicated Recovery Readiness dashboard widget for backup posture and recovery evidence
- group Needs Attention items by domain and elevate the recovery call-to-action
- align restore-run and recovery posture tests with the extracted widget and continuity flows
- include the related spec artifacts for 184-dashboard-recovery-honesty

## Verification
- `cd /Users/ahmeddarrazi/Documents/projects/TenantAtlas/apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`
- `cd /Users/ahmeddarrazi/Documents/projects/TenantAtlas/apps/platform && ./vendor/bin/sail artisan test --compact --filter="DashboardKpisWidget|DashboardRecoveryPosture|TenantDashboardDbOnly|TenantpilotSeedBackupHealthBrowserFixtureCommand|NeedsAttentionWidget"`
- browser smoke verified on the calm, unvalidated, and weakened dashboard states

## Notes
- Livewire v4.0+ compliant with Filament v5
- no panel provider changes; Laravel 11+ provider registration remains in `bootstrap/providers.php`
- Recovery Readiness stays within the existing tenant dashboard asset strategy; no new Filament asset registration required

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #215
2026-04-08 23:21:36 +00:00

74 lines
3.1 KiB
PHP

<div
@if ($pollingInterval)
wire:poll.{{ $pollingInterval }}
@endif
>
<x-filament::section>
<x-slot name="heading">
<span class="flex items-center gap-2">
<x-filament::icon
icon="heroicon-m-shield-check"
class="h-5 w-5 text-gray-400 dark:text-gray-500"
/>
Recovery Readiness
</span>
</x-slot>
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
@foreach ([$backupPosture, $recoveryEvidence] as $stat)
@php
$colorClasses = match ($stat['color']) {
'danger' => 'border-danger-300 dark:border-danger-700',
'warning' => 'border-warning-300 dark:border-warning-700',
'success' => 'border-success-300 dark:border-success-700',
'info' => 'border-info-300 dark:border-info-700',
default => 'border-gray-200 dark:border-white/10',
};
$valueColorClasses = match ($stat['color']) {
'danger' => 'text-danger-600 dark:text-danger-400',
'warning' => 'text-warning-600 dark:text-warning-400',
'success' => 'text-success-600 dark:text-success-400',
'info' => 'text-info-600 dark:text-info-400',
default => 'text-gray-950 dark:text-white',
};
$descriptionColorClasses = match ($stat['color']) {
'danger' => 'text-danger-600 dark:text-danger-400',
'warning' => 'text-warning-600 dark:text-warning-400',
'success' => 'text-success-600 dark:text-success-400',
default => 'text-gray-600 dark:text-gray-300',
};
@endphp
@if ($stat['url'])
<a
href="{{ $stat['url'] }}"
class="{{ $colorClasses }} block rounded-xl border-l-4 bg-white p-5 shadow-sm transition hover:shadow-md dark:bg-gray-900"
>
@else
<div class="{{ $colorClasses }} rounded-xl border-l-4 bg-white p-5 shadow-sm dark:bg-gray-900">
@endif
<div class="text-sm font-medium text-gray-500 dark:text-gray-400">
{{ $stat['label'] }}
</div>
<div class="{{ $valueColorClasses }} mt-1 text-2xl font-bold tracking-tight">
{{ $stat['value'] }}
</div>
@if (filled($stat['description']))
<div class="{{ $descriptionColorClasses }} mt-2 text-sm leading-relaxed">
{{ $stat['description'] }}
</div>
@endif
@if ($stat['url'])
</a>
@else
</div>
@endif
@endforeach
</div>
</x-filament::section>
</div>