Files
fotospiel-app/resources/views/filament/events/join-link.blade.php
Codex Agent 15e19d4e8b
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
tests / ui (push) Has been cancelled
Add join token analytics dashboard and align Filament views
2026-01-04 18:21:59 +01:00

173 lines
6.8 KiB
PHP

@php
use Filament\Support\Enums\GridDirection;
use Filament\Support\Icons\Heroicon;
use Illuminate\View\ComponentAttributeBag;
$stacked = (new ComponentAttributeBag())->grid(['default' => 1], GridDirection::Column);
$tokensGrid = (new ComponentAttributeBag())->grid(['default' => 1], GridDirection::Column);
$linkGrid = (new ComponentAttributeBag())->grid(['default' => 1, 'md' => 2]);
$metricsGrid = (new ComponentAttributeBag())->grid(['default' => 1, 'sm' => 2, 'xl' => 4]);
$layoutsGrid = (new ComponentAttributeBag())->grid(['default' => 1, 'md' => 2]);
@endphp
<div {{ $stacked }}>
<x-filament::section
:heading="__('admin.events.join_link.event_label')"
:description="$event->name"
:icon="Heroicon::InformationCircle"
>
<x-slot name="afterHeader">
<x-filament::button
tag="a"
href="{{ url('/event-admin/events/' . $event->slug) }}"
target="_blank"
rel="noreferrer"
color="warning"
size="sm"
:icon="Heroicon::ArrowTopRightOnSquare"
>
{{ __('admin.events.join_link.open_admin') }}
</x-filament::button>
</x-slot>
<x-filament::badge color="warning" :icon="Heroicon::ExclamationTriangle">
{{ __('admin.events.join_link.deprecated_notice', ['slug' => $event->slug]) }}
</x-filament::badge>
</x-filament::section>
@if ($tokens->isEmpty())
<x-filament::empty-state
:heading="__('admin.events.join_link.no_tokens')"
:icon="Heroicon::Key"
/>
@else
<div {{ $tokensGrid }}>
@foreach ($tokens as $token)
<x-filament::card
:heading="$token['label'] ?? __('admin.events.join_link.token_default', ['id' => $token['id']])"
:description="__('admin.events.join_link.token_usage', [
'usage' => $token['usage_count'],
'limit' => $token['usage_limit'] ?? '∞',
])"
>
<x-slot name="afterHeader">
@if ($token['is_active'])
<x-filament::badge color="success" :icon="Heroicon::CheckCircle">
{{ __('admin.events.join_link.token_active') }}
</x-filament::badge>
@else
<x-filament::badge color="gray" :icon="Heroicon::PauseCircle">
{{ __('admin.events.join_link.token_inactive') }}
</x-filament::badge>
@endif
</x-slot>
<div {{ $stacked }}>
<x-filament::badge color="gray" :icon="Heroicon::Link">
{{ __('admin.events.join_link.link_label') }}: {{ $token['url'] }}
</x-filament::badge>
<div {{ $linkGrid }}>
<x-filament::button
x-data
@click.prevent="navigator.clipboard.writeText('{{ $token['url'] }}')"
color="gray"
size="xs"
:icon="Heroicon::ClipboardDocument"
>
{{ __('admin.events.join_link.copy_link') }}
</x-filament::button>
</div>
</div>
@php
$analytics = $token['analytics'] ?? [];
@endphp
@if (!empty($analytics))
<div {{ $metricsGrid }}>
<x-filament::card compact>
<x-filament::badge color="success" :icon="Heroicon::CheckCircle">
{{ __('admin.events.analytics.success_total') }}:
{{ number_format($analytics['success_total'] ?? 0) }}
</x-filament::badge>
</x-filament::card>
<x-filament::card compact>
<x-filament::badge color="danger" :icon="Heroicon::XCircle">
{{ __('admin.events.analytics.failure_total') }}:
{{ number_format($analytics['failure_total'] ?? 0) }}
</x-filament::badge>
</x-filament::card>
<x-filament::card compact>
<x-filament::badge color="warning" :icon="Heroicon::ExclamationTriangle">
{{ __('admin.events.analytics.rate_limited_total') }}:
{{ number_format($analytics['rate_limited_total'] ?? 0) }}
</x-filament::badge>
</x-filament::card>
<x-filament::card compact>
<div {{ $stacked }}>
<x-filament::badge color="gray" :icon="Heroicon::Clock">
{{ __('admin.events.analytics.recent_24h') }}:
{{ number_format($analytics['recent_24h'] ?? 0) }}
</x-filament::badge>
@if (!empty($analytics['last_seen_at']))
<x-filament::badge color="gray" :icon="Heroicon::Eye">
{{ __('admin.events.analytics.last_seen_at', ['date' => \Carbon\Carbon::parse($analytics['last_seen_at'])->isoFormat('LLL')]) }}
</x-filament::badge>
@endif
</div>
</x-filament::card>
</div>
@endif
@if (!empty($token['layouts']))
<x-filament::section :heading="__('admin.events.join_link.layouts_heading')" :icon="Heroicon::QrCode">
<div {{ $layoutsGrid }}>
@foreach ($token['layouts'] as $layout)
<x-filament::card
:heading="$layout['name']"
:description="$layout['subtitle'] ?? null"
>
<div {{ $stacked }}>
@foreach ($layout['download_urls'] as $format => $href)
<x-filament::button
tag="a"
href="{{ $href }}"
target="_blank"
rel="noreferrer"
color="warning"
size="xs"
:icon="Heroicon::ArrowDownTray"
>
{{ strtoupper($format) }}
</x-filament::button>
@endforeach
</div>
</x-filament::card>
@endforeach
</div>
</x-filament::section>
@elseif(!empty($token['layouts_url']))
<x-filament::button
tag="a"
href="{{ $token['layouts_url'] }}"
target="_blank"
rel="noreferrer"
color="warning"
size="xs"
:icon="Heroicon::QrCode"
>
{{ __('admin.events.join_link.layouts_fallback') }}
</x-filament::button>
@endif
@if ($token['expires_at'])
<x-filament::badge color="gray" :icon="Heroicon::Clock">
{{ __('admin.events.join_link.token_expiry', ['date' => \Carbon\Carbon::parse($token['expires_at'])->isoFormat('LLL')]) }}
</x-filament::badge>
@endif
</x-filament::card>
@endforeach
</div>
@endif
</div>