128 lines
4.1 KiB
PHP
128 lines
4.1 KiB
PHP
<?php
|
|
|
|
namespace App\Filament\Clusters\DailyOps\Pages;
|
|
|
|
use App\Filament\Clusters\DailyOps\DailyOpsCluster;
|
|
use App\Filament\Widgets\JoinTokenOverviewWidget;
|
|
use App\Filament\Widgets\JoinTokenTopTokensWidget;
|
|
use App\Filament\Widgets\JoinTokenTrendWidget;
|
|
use App\Models\Event;
|
|
use BackedEnum;
|
|
use Filament\Forms\Components\Select;
|
|
use Filament\Pages\Dashboard;
|
|
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
|
|
use Filament\Schemas\Components\Section;
|
|
use Filament\Schemas\Schema;
|
|
use UnitEnum;
|
|
|
|
class JoinTokenAnalyticsDashboard extends Dashboard
|
|
{
|
|
use HasFiltersForm;
|
|
|
|
protected static ?string $cluster = DailyOpsCluster::class;
|
|
|
|
protected static string $routePath = 'join-token-analytics';
|
|
|
|
protected static null|string|BackedEnum $navigationIcon = 'heroicon-o-chart-bar';
|
|
|
|
protected static null|string|UnitEnum $navigationGroup = null;
|
|
|
|
protected static ?int $navigationSort = 12;
|
|
|
|
public static function getNavigationGroup(): UnitEnum|string|null
|
|
{
|
|
return __('admin.nav.security');
|
|
}
|
|
|
|
public static function getNavigationLabel(): string
|
|
{
|
|
return __('admin.join_token_analytics.navigation.label');
|
|
}
|
|
|
|
public function getHeading(): string
|
|
{
|
|
return __('admin.join_token_analytics.heading');
|
|
}
|
|
|
|
public function getSubheading(): ?string
|
|
{
|
|
return __('admin.join_token_analytics.subheading');
|
|
}
|
|
|
|
public function getColumns(): int|array
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
public function getWidgets(): array
|
|
{
|
|
return [
|
|
JoinTokenOverviewWidget::class,
|
|
JoinTokenTrendWidget::class,
|
|
JoinTokenTopTokensWidget::class,
|
|
];
|
|
}
|
|
|
|
public function filtersForm(Schema $schema): Schema
|
|
{
|
|
return $schema
|
|
->components([
|
|
Section::make()
|
|
->schema([
|
|
Select::make('range')
|
|
->label(__('admin.join_token_analytics.filters.range'))
|
|
->options(trans('admin.join_token_analytics.filters.range_options'))
|
|
->default('24h')
|
|
->native(false),
|
|
Select::make('event_id')
|
|
->label(__('admin.join_token_analytics.filters.event'))
|
|
->placeholder(__('admin.join_token_analytics.filters.event_placeholder'))
|
|
->searchable()
|
|
->getSearchResultsUsing(fn (string $search): array => $this->searchEvents($search))
|
|
->getOptionLabelUsing(fn ($value): ?string => $this->resolveEventLabel($value))
|
|
->native(false),
|
|
])
|
|
->columns(2),
|
|
]);
|
|
}
|
|
|
|
private function searchEvents(string $search): array
|
|
{
|
|
return Event::query()
|
|
->with('tenant')
|
|
->when($search !== '', function ($query) use ($search) {
|
|
$query->where('slug', 'like', "%{$search}%")
|
|
->orWhere('name->de', 'like', "%{$search}%")
|
|
->orWhere('name->en', 'like', "%{$search}%");
|
|
})
|
|
->orderByDesc('date')
|
|
->limit(25)
|
|
->get()
|
|
->mapWithKeys(fn (Event $event) => [$event->id => $this->formatEventLabel($event)])
|
|
->all();
|
|
}
|
|
|
|
private function resolveEventLabel(mixed $value): ?string
|
|
{
|
|
if (! is_numeric($value)) {
|
|
return null;
|
|
}
|
|
|
|
$event = Event::query()
|
|
->with('tenant')
|
|
->find((int) $value);
|
|
|
|
return $event ? $this->formatEventLabel($event) : null;
|
|
}
|
|
|
|
private function formatEventLabel(Event $event): string
|
|
{
|
|
$locale = app()->getLocale();
|
|
$name = $event->name[$locale] ?? $event->name['de'] ?? $event->name['en'] ?? $event->slug ?? __('admin.common.unnamed');
|
|
$tenant = $event->tenant?->name ?? __('admin.common.unnamed');
|
|
$date = $event->date?->format('Y-m-d');
|
|
|
|
return $date ? "{$name} ({$tenant}) {$date}" : "{$name} ({$tenant})";
|
|
}
|
|
}
|