Es gibt nun task collections und vordefinierte tasks für alle. Onboarding verfeinert und webseite-carousel gefixt (logging später entfernen!)
187 lines
5.1 KiB
PHP
187 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 Filament\Notifications\Notification;
|
|
use Filament\Pages\Page;
|
|
use BackedEnum;
|
|
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('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();
|
|
}
|
|
}
|