Files
2026-05-09 17:32:17 +02:00

240 lines
8.1 KiB
PHP
Executable File

<?php
declare(strict_types=1);
namespace App\Filament\Pages\Radio;
use App\Models\RadioContest;
use Filament\Actions\Action;
use Filament\Forms\Components\DateTimePicker;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Schema;
final class ContestManagement extends Page implements HasForms
{
use InteractsWithForms;
#[\Override]
protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-trophy';
#[\Override]
protected static string|\UnitEnum|null $navigationGroup = 'Radio';
#[\Override]
protected static ?string $navigationLabel = null;
#[\Override]
public static function getNavigationLabel(): string
{
return __('Contests');
}
#[\Override]
protected static ?string $title = 'Competities Beheer';
#[\Override]
protected string $view = 'filament.pages.radio.contest-management';
/** @var array<string, mixed> */
public array $data = [];
public function mount(): void
{
$this->fillForm();
}
protected function fillForm(): void
{
$contests = RadioContest::orderBy('created_at', 'desc')->get();
$this->data['contests'] = $contests->toArray();
$this->data['active_contest'] = $contests->firstWhere('is_active', true)?->id;
}
public function form(Schema $schema): Schema
{
return $schema
->components([
Section::make('Nieuwe Competitie Aanmaken')
->description('Maak een nieuwe competitie aan')
->columns(1)
->headerActions([
Action::make('create_contest')
->label('Competitie Aanmaken')
->action('createContest')
->color('success'),
])
->schema([
TextInput::make('contest.title')
->label('Titel')
->required()
->placeholder('Bijv. Beste Song Suggestie'),
Textarea::make('contest.description')
->label('Beschrijving')
->rows(3)
->placeholder('Beschrijf de competitie regels...'),
TextInput::make('contest.prize')
->label('Prijs')
->required()
->placeholder('Bijv. VIP voor 1 maand'),
TextInput::make('contest.max_winners')
->label('Aantal Winnaars')
->numeric()
->default(1)
->placeholder('1'),
DateTimePicker::make('contest.starts_at')
->label('Start Datum/Tijd')
->required()
->default(now()),
DateTimePicker::make('contest.ends_at')
->label('Eind Datum/Tijd')
->required()
->default(now()->addDays(14)),
Toggle::make('contest.require_approval')
->label('Goedkeuring Vereist')
->default(false),
]),
Section::make('Actieve Competities')
->description('Beheer lopende competities')
->columns(1)
->schema([
Select::make('selected_contest')
->label('Selecteer Competitie')
->options(RadioContest::where('is_active', true)->pluck('title', 'id'))
->placeholder('Kies een competitie...')
->live(),
]),
Section::make('Acties')
->description('Competitie beheer')
->columns(2)
->schema([
Action::make('end_contest')
->label('Competitie Beëindigen')
->action('endContest')
->color('danger')
->requiresConfirmation(),
Action::make('declare_winners')
->label('Winnaars Bekend Maken')
->action('declareWinners')
->color('warning')
->requiresConfirmation(),
]),
Section::make('Afgelopen Competities')
->description('Bekijk resultaten van afgelopen competities')
->columns(1)
->schema([
Select::make('ended_contest')
->label('Selecteer Afgelopen Competitie')
->options(RadioContest::where('is_ended', true)->pluck('title', 'id'))
->placeholder('Kies een competitie...'),
]),
])
->statePath('data');
}
public function createContest(): void
{
$data = $this->data['contest'] ?? [];
$contest = RadioContest::create([
'title' => $data['title'],
'description' => $data['description'] ?? '',
'prize' => $data['prize'],
'max_winners' => $data['max_winners'] ?? 1,
'starts_at' => $data['starts_at'] ?? now(),
'ends_at' => $data['ends_at'] ?? now()->addDays(14),
'is_active' => true,
'is_ended' => false,
'winners_announced' => false,
'require_approval' => $data['require_approval'] ?? false,
]);
$this->fillForm();
Notification::make()
->success()
->title('Competitie Aangemaakt')
->body("Competitie '{$contest->title}' is succesvol aangemaakt!")
->send();
}
public function endContest(): void
{
$contestId = $this->data['selected_contest'] ?? null;
if (! $contestId) {
Notification::make()
->warning()
->title('Geen Competitie Geselecteerd')
->body('Selecteer eerst een competitie.')
->send();
return;
}
$contest = RadioContest::find($contestId);
$contest->update(['is_ended' => true, 'is_active' => false]);
$this->fillForm();
Notification::make()
->success()
->title('Competitie Beëindigd')
->body("Competitie '{$contest->title}' is beëindigd.")
->send();
}
public function declareWinners(): void
{
$contestId = $this->data['selected_contest'] ?? null;
if (! $contestId) {
Notification::make()
->warning()
->title('Geen Competitie Geselecteerd')
->body('Selecteer eerst een competitie.')
->send();
return;
}
$contest = RadioContest::find($contestId);
$entries = $contest->entries()->with('user')->get();
if ($entries->isEmpty()) {
Notification::make()
->warning()
->title('Geen Inzendingen')
->body('Er zijn nog geen inzendingen.')
->send();
return;
}
$winners = $entries->random(min($contest->max_winners, $entries->count()));
foreach ($winners as $winner) {
$winner->markAsWinner();
}
$contest->update(['winners_announced' => true]);
$this->fillForm();
Notification::make()
->success()
->title('Winnaars Bekend!')
->body(count($winners) . ' winnaars zijn geselecteerd!')
->send();
}
}