Files
fotospiel-app/app/Filament/Tenant/Pages/InviteStudio.php

188 lines
5.1 KiB
PHP

<?php
namespace App\Filament\Tenant\Pages;
use App\Models\Event;
use App\Models\EventJoinToken;
use App\Services\EventJoinTokenService;
use App\Support\JoinTokenLayoutRegistry;
use App\Support\TenantOnboardingState;
use BackedEnum;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\URL;
class InviteStudio extends Page
{
protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-qr-code';
protected string $view = 'filament.tenant.pages.invite-studio';
protected static ?string $navigationLabel = 'Einladungen & QR';
protected static ?string $slug = 'invite-studio';
protected static ?string $title = 'Einladungen & QR-Codes';
protected static ?int $navigationSort = 50;
public ?int $selectedEventId = null;
public string $tokenLabel = '';
public array $tokens = [];
public array $layouts = [];
protected static bool $shouldRegisterNavigation = true;
public function mount(): void
{
$tenant = TenantOnboardingState::tenant();
abort_if(! $tenant, 403);
if (! TenantOnboardingState::completed($tenant)) {
$this->redirect(TenantOnboarding::getUrl());
return;
}
$firstEventId = $tenant->events()->orderBy('date')->value('id');
$this->selectedEventId = $firstEventId;
$this->layouts = $this->buildLayouts();
if ($this->selectedEventId) {
$this->loadEventContext();
}
}
public static function shouldRegisterNavigation(): bool
{
return TenantOnboardingState::completed();
}
public function updatedSelectedEventId(): void
{
$this->loadEventContext();
}
public function createInvite(EventJoinTokenService $service): void
{
$this->validate([
'selectedEventId' => ['required', 'exists:events,id'],
'tokenLabel' => ['nullable', 'string', 'max:120'],
]);
$tenant = TenantOnboardingState::tenant();
abort_if(! $tenant, 403);
$event = $tenant->events()->whereKey($this->selectedEventId)->first();
if (! $event) {
Notification::make()
->title('Event konnte nicht gefunden werden')
->danger()
->send();
return;
}
$label = $this->tokenLabel ?: 'Einladung '.now()->format('d.m.');
$layoutPreference = Arr::get($tenant->settings ?? [], 'branding.preferred_invite_layout');
$service->createToken($event, [
'label' => $label,
'metadata' => [
'preferred_layout' => $layoutPreference,
],
'created_by' => auth()->id(),
]);
$this->tokenLabel = '';
$this->loadEventContext();
Notification::make()
->title('Neuer Einladungslink erstellt')
->success()
->send();
}
protected function loadEventContext(): void
{
$tenant = TenantOnboardingState::tenant();
if (! $tenant || ! $this->selectedEventId) {
$this->tokens = [];
return;
}
$event = $tenant->events()->whereKey($this->selectedEventId)->first();
if (! $event) {
$this->tokens = [];
return;
}
$this->tokens = $event->joinTokens()
->orderByDesc('created_at')
->get()
->map(fn (EventJoinToken $token) => $this->mapToken($event, $token))
->toArray();
}
protected function mapToken(Event $event, EventJoinToken $token): array
{
$downloadUrls = JoinTokenLayoutRegistry::toResponse(function (string $layoutId, string $format) use ($event, $token) {
return route('api.v1.tenant.events.join-tokens.layouts.download', [
'event' => $event->slug,
'joinToken' => $token->getKey(),
'layout' => $layoutId,
'format' => $format,
]);
});
return [
'id' => $token->getKey(),
'label' => $token->label ?? 'Einladungslink',
'url' => URL::to('/e/'.$token->token),
'created_at' => optional($token->created_at)->format('d.m.Y H:i'),
'usage_count' => $token->usage_count,
'usage_limit' => $token->usage_limit,
'active' => $token->isActive(),
'downloads' => $downloadUrls,
];
}
protected function buildLayouts(): array
{
return collect(JoinTokenLayoutRegistry::all())
->map(fn (array $layout) => [
'id' => $layout['id'],
'name' => $layout['name'],
'subtitle' => $layout['subtitle'] ?? '',
'description' => $layout['description'] ?? '',
])
->toArray();
}
public function getEventsProperty(): Collection
{
$tenant = TenantOnboardingState::tenant();
if (! $tenant) {
return collect();
}
return $tenant->events()->orderBy('date')->get();
}
}