Add join token analytics dashboard and align Filament views
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
tests / ui (push) Has been cancelled

This commit is contained in:
Codex Agent
2026-01-04 18:21:59 +01:00
parent 48b1cfde09
commit 15e19d4e8b
17 changed files with 1176 additions and 310 deletions

View File

@@ -1,76 +1,90 @@
@php
use Filament\Support\Enums\GridDirection;
use Filament\Support\Icons\Heroicon;
use Illuminate\View\ComponentAttributeBag;
$statusColors = [
'healthy' => 'success',
'pending' => 'warning',
'degraded' => 'danger',
'unconfigured' => 'danger',
'unknown' => 'gray',
];
$statusIcons = [
'healthy' => Heroicon::CheckCircle,
'pending' => Heroicon::Clock,
'degraded' => Heroicon::ExclamationTriangle,
'unconfigured' => Heroicon::XCircle,
'unknown' => Heroicon::QuestionMarkCircle,
];
$cardsGrid = (new ComponentAttributeBag())->grid(['default' => 1, 'lg' => 2]);
$metricsGrid = (new ComponentAttributeBag())->grid(['default' => 1], GridDirection::Column);
@endphp
<x-filament-widgets::widget>
<x-filament::section heading="{{ __('admin.integrations_health.heading') }}">
<div class="grid gap-4 md:grid-cols-2">
<div {{ $cardsGrid }}>
@forelse($providers as $provider)
<div class="rounded-2xl border border-slate-200/70 bg-white/80 p-4 shadow-sm dark:border-white/10 dark:bg-slate-900/60">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-semibold text-slate-700 dark:text-slate-100">{{ $provider['label'] }}</p>
<p class="text-xs text-slate-500 dark:text-slate-400">
{{ $provider['config_label'] }}:
<span class="font-semibold {{ $provider['is_configured'] ? 'text-emerald-600 dark:text-emerald-400' : 'text-rose-600 dark:text-rose-400' }}">
{{ $provider['is_configured'] ? __('admin.integrations_health.configured') : __('admin.integrations_health.unconfigured') }}
</span>
</p>
</div>
<span @class([
'rounded-full px-3 py-1 text-xs font-semibold',
'bg-emerald-100 text-emerald-800' => $provider['status'] === 'healthy',
'bg-amber-100 text-amber-800' => $provider['status'] === 'pending',
'bg-rose-100 text-rose-800' => in_array($provider['status'], ['degraded', 'unconfigured']),
'bg-slate-100 text-slate-600' => $provider['status'] === 'unknown',
])>
<x-filament::card
:heading="$provider['label']"
:description="$provider['config_label']"
>
<x-slot name="afterHeader">
<x-filament::badge :color="$provider['is_configured'] ? 'success' : 'danger'">
{{ $provider['is_configured'] ? __('admin.integrations_health.configured') : __('admin.integrations_health.unconfigured') }}
</x-filament::badge>
<x-filament::badge
:color="$statusColors[$provider['status']] ?? 'gray'"
:icon="$statusIcons[$provider['status']] ?? Heroicon::QuestionMarkCircle"
>
{{ $provider['status_label'] }}
</span>
</div>
</x-filament::badge>
</x-slot>
<div class="mt-4 grid gap-2 text-xs text-slate-600 dark:text-slate-300">
<div class="flex items-center justify-between">
<span>{{ __('admin.integrations_health.last_received') }}</span>
<span class="font-semibold">
{{ optional(data_get($provider, 'last_event.received_at'))->diffForHumans() ?? '—' }}
</span>
</div>
<div class="flex items-center justify-between">
<span>{{ __('admin.integrations_health.last_processed') }}</span>
<span class="font-semibold">
{{ optional(data_get($provider, 'last_processed.processed_at'))->diffForHumans() ?? '—' }}
</span>
</div>
<div class="flex items-center justify-between">
<span>{{ __('admin.integrations_health.processing_lag') }}</span>
<span class="font-semibold">
{{ $provider['processing_lag']['label'] ?? '—' }}
</span>
</div>
<div class="flex items-center justify-between">
<span>{{ __('admin.integrations_health.pending_events') }}</span>
<span class="font-semibold">{{ number_format($provider['pending_count']) }}</span>
</div>
<div class="flex items-center justify-between">
<span>{{ __('admin.integrations_health.recent_failures') }}</span>
<span class="font-semibold">{{ number_format($provider['recent_failures']) }}</span>
</div>
<div class="flex items-center justify-between">
<span>{{ __('admin.integrations_health.queue_backlog') }}</span>
<span class="font-semibold">{{ number_format($provider['queue_backlog']) }}</span>
</div>
<div class="flex items-center justify-between">
<span>{{ __('admin.integrations_health.failed_jobs') }}</span>
<span class="font-semibold">{{ number_format($provider['failed_jobs']) }}</span>
</div>
<div {{ $metricsGrid }}>
<x-filament::badge color="gray" :icon="Heroicon::Clock">
{{ __('admin.integrations_health.last_received') }}:
{{ optional(data_get($provider, 'last_event.received_at'))->diffForHumans() ?? '—' }}
</x-filament::badge>
<x-filament::badge color="gray" :icon="Heroicon::ArrowPath">
{{ __('admin.integrations_health.last_processed') }}:
{{ optional(data_get($provider, 'last_processed.processed_at'))->diffForHumans() ?? '—' }}
</x-filament::badge>
<x-filament::badge color="gray" :icon="Heroicon::Clock">
{{ __('admin.integrations_health.processing_lag') }}:
{{ $provider['processing_lag']['label'] ?? '—' }}
</x-filament::badge>
<x-filament::badge color="gray" :icon="Heroicon::QueueList">
{{ __('admin.integrations_health.pending_events') }}:
{{ number_format($provider['pending_count']) }}
</x-filament::badge>
<x-filament::badge color="gray" :icon="Heroicon::ExclamationTriangle">
{{ __('admin.integrations_health.recent_failures') }}:
{{ number_format($provider['recent_failures']) }}
</x-filament::badge>
<x-filament::badge color="gray" :icon="Heroicon::RectangleStack">
{{ __('admin.integrations_health.queue_backlog') }}:
{{ number_format($provider['queue_backlog']) }}
</x-filament::badge>
<x-filament::badge color="gray" :icon="Heroicon::XCircle">
{{ __('admin.integrations_health.failed_jobs') }}:
{{ number_format($provider['failed_jobs']) }}
</x-filament::badge>
@if(! empty(data_get($provider, 'last_failed.error_message')))
<x-filament::badge color="danger" :icon="Heroicon::ExclamationTriangle">
{{ __('admin.integrations_health.last_error') }}:
{{ data_get($provider, 'last_failed.error_message') }}
</x-filament::badge>
@endif
</div>
@if(! empty(data_get($provider, 'last_failed.error_message')))
<div class="mt-3 rounded-lg bg-rose-50 px-3 py-2 text-xs text-rose-700 dark:bg-rose-900/30 dark:text-rose-200">
{{ __('admin.integrations_health.last_error') }}: {{ data_get($provider, 'last_failed.error_message') }}
</div>
@endif
</div>
</x-filament::card>
@empty
<p class="text-sm text-slate-500 dark:text-slate-300">
{{ __('admin.integrations_health.empty') }}
</p>
<x-filament::empty-state
:heading="__('admin.integrations_health.empty')"
:icon="Heroicon::QuestionMarkCircle"
/>
@endforelse
</div>
</x-filament::section>