generated from theradcoza/Laravel-Docker-Dev-Template
Add leaderboard route with participants, and configure Shell brand colors in Tailwind
This commit is contained in:
193
src/app/Filament/Resources/ParticipantResource.php
Normal file
193
src/app/Filament/Resources/ParticipantResource.php
Normal file
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources;
|
||||
|
||||
use App\Filament\Resources\ParticipantResource\Pages;
|
||||
use App\Models\Participant;
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class ParticipantResource extends Resource
|
||||
{
|
||||
protected static ?string $model = Participant::class;
|
||||
|
||||
protected static ?string $navigationIcon = 'heroicon-o-flag';
|
||||
|
||||
protected static ?string $navigationGroup = 'Leaderboard';
|
||||
|
||||
protected static ?int $navigationSort = 1;
|
||||
|
||||
public static function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
Forms\Components\Section::make('Participant Information')
|
||||
->schema([
|
||||
Forms\Components\TextInput::make('name')
|
||||
->required()
|
||||
->maxLength(255)
|
||||
->placeholder('Enter participant name'),
|
||||
Forms\Components\TextInput::make('car_number')
|
||||
->label('Car Number')
|
||||
->numeric()
|
||||
->minValue(1)
|
||||
->maxValue(999)
|
||||
->placeholder('e.g., 44'),
|
||||
])->columns(2),
|
||||
|
||||
Forms\Components\Section::make('Timing')
|
||||
->schema([
|
||||
Forms\Components\Grid::make(4)
|
||||
->schema([
|
||||
Forms\Components\TextInput::make('time_minutes')
|
||||
->label('Minutes')
|
||||
->numeric()
|
||||
->minValue(0)
|
||||
->maxValue(59)
|
||||
->default(0)
|
||||
->placeholder('00')
|
||||
->dehydrated(false)
|
||||
->afterStateHydrated(function ($component, $state, $record) {
|
||||
if ($record && $record->time_ms) {
|
||||
$component->state(floor($record->time_ms / 60000));
|
||||
}
|
||||
}),
|
||||
Forms\Components\TextInput::make('time_seconds')
|
||||
->label('Seconds')
|
||||
->numeric()
|
||||
->minValue(0)
|
||||
->maxValue(59)
|
||||
->default(0)
|
||||
->placeholder('00')
|
||||
->dehydrated(false)
|
||||
->afterStateHydrated(function ($component, $state, $record) {
|
||||
if ($record && $record->time_ms) {
|
||||
$component->state(floor(($record->time_ms % 60000) / 1000));
|
||||
}
|
||||
}),
|
||||
Forms\Components\TextInput::make('time_milliseconds')
|
||||
->label('Milliseconds')
|
||||
->numeric()
|
||||
->minValue(0)
|
||||
->maxValue(999)
|
||||
->default(0)
|
||||
->placeholder('000')
|
||||
->dehydrated(false)
|
||||
->afterStateHydrated(function ($component, $state, $record) {
|
||||
if ($record && $record->time_ms) {
|
||||
$component->state($record->time_ms % 1000);
|
||||
}
|
||||
}),
|
||||
Forms\Components\Select::make('status')
|
||||
->options([
|
||||
'pending' => 'Pending',
|
||||
'completed' => 'Completed',
|
||||
'dnf' => 'DNF',
|
||||
])
|
||||
->default('pending')
|
||||
->required(),
|
||||
]),
|
||||
Forms\Components\Hidden::make('time_ms'),
|
||||
])
|
||||
->description('Enter time as MM:SS.ms (e.g., 01:23.456)'),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
Tables\Columns\TextColumn::make('position')
|
||||
->label('P')
|
||||
->state(function ($record, $rowLoop) {
|
||||
return $rowLoop->iteration;
|
||||
})
|
||||
->alignCenter()
|
||||
->weight('bold'),
|
||||
Tables\Columns\TextColumn::make('car_number')
|
||||
->label('#')
|
||||
->alignCenter()
|
||||
->placeholder('-')
|
||||
->sortable(),
|
||||
Tables\Columns\TextColumn::make('name')
|
||||
->searchable()
|
||||
->sortable()
|
||||
->weight('bold'),
|
||||
Tables\Columns\TextColumn::make('formatted_time')
|
||||
->label('Time')
|
||||
->placeholder('No time')
|
||||
->fontFamily('mono')
|
||||
->alignCenter(),
|
||||
Tables\Columns\BadgeColumn::make('status')
|
||||
->colors([
|
||||
'warning' => 'pending',
|
||||
'success' => 'completed',
|
||||
'danger' => 'dnf',
|
||||
]),
|
||||
Tables\Columns\TextColumn::make('updated_at')
|
||||
->label('Last Update')
|
||||
->dateTime('M j, H:i')
|
||||
->sortable(),
|
||||
])
|
||||
->defaultSort('time_ms', 'asc')
|
||||
->filters([
|
||||
Tables\Filters\SelectFilter::make('status')
|
||||
->options([
|
||||
'pending' => 'Pending',
|
||||
'completed' => 'Completed',
|
||||
'dnf' => 'DNF',
|
||||
]),
|
||||
])
|
||||
->actions([
|
||||
Tables\Actions\EditAction::make(),
|
||||
Tables\Actions\DeleteAction::make(),
|
||||
])
|
||||
->bulkActions([
|
||||
Tables\Actions\BulkActionGroup::make([
|
||||
Tables\Actions\DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => Pages\ListParticipants::route('/'),
|
||||
'create' => Pages\CreateParticipant::route('/create'),
|
||||
'edit' => Pages\EditParticipant::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
|
||||
public static function mutateFormDataBeforeCreate(array $data): array
|
||||
{
|
||||
return static::calculateTimeMs($data);
|
||||
}
|
||||
|
||||
public static function mutateFormDataBeforeSave(array $data): array
|
||||
{
|
||||
return static::calculateTimeMs($data);
|
||||
}
|
||||
|
||||
protected static function calculateTimeMs(array $data): array
|
||||
{
|
||||
$minutes = (int) ($data['time_minutes'] ?? 0);
|
||||
$seconds = (int) ($data['time_seconds'] ?? 0);
|
||||
$milliseconds = (int) ($data['time_milliseconds'] ?? 0);
|
||||
|
||||
if ($minutes > 0 || $seconds > 0 || $milliseconds > 0) {
|
||||
$data['time_ms'] = ($minutes * 60000) + ($seconds * 1000) + $milliseconds;
|
||||
} else {
|
||||
$data['time_ms'] = null;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\ParticipantResource\Pages;
|
||||
|
||||
use App\Filament\Resources\ParticipantResource;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
|
||||
class CreateParticipant extends CreateRecord
|
||||
{
|
||||
protected static string $resource = ParticipantResource::class;
|
||||
|
||||
protected function mutateFormDataBeforeCreate(array $data): array
|
||||
{
|
||||
$minutes = (int) ($data['time_minutes'] ?? 0);
|
||||
$seconds = (int) ($data['time_seconds'] ?? 0);
|
||||
$milliseconds = (int) ($data['time_milliseconds'] ?? 0);
|
||||
|
||||
if ($minutes > 0 || $seconds > 0 || $milliseconds > 0) {
|
||||
$data['time_ms'] = ($minutes * 60000) + ($seconds * 1000) + $milliseconds;
|
||||
} else {
|
||||
$data['time_ms'] = null;
|
||||
}
|
||||
|
||||
unset($data['time_minutes'], $data['time_seconds'], $data['time_milliseconds']);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function getRedirectUrl(): string
|
||||
{
|
||||
return $this->getResource()::getUrl('index');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\ParticipantResource\Pages;
|
||||
|
||||
use App\Filament\Resources\ParticipantResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
|
||||
class EditParticipant extends EditRecord
|
||||
{
|
||||
protected static string $resource = ParticipantResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\DeleteAction::make(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function mutateFormDataBeforeSave(array $data): array
|
||||
{
|
||||
$minutes = (int) ($data['time_minutes'] ?? 0);
|
||||
$seconds = (int) ($data['time_seconds'] ?? 0);
|
||||
$milliseconds = (int) ($data['time_milliseconds'] ?? 0);
|
||||
|
||||
if ($minutes > 0 || $seconds > 0 || $milliseconds > 0) {
|
||||
$data['time_ms'] = ($minutes * 60000) + ($seconds * 1000) + $milliseconds;
|
||||
} else {
|
||||
$data['time_ms'] = null;
|
||||
}
|
||||
|
||||
unset($data['time_minutes'], $data['time_seconds'], $data['time_milliseconds']);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function getRedirectUrl(): string
|
||||
{
|
||||
return $this->getResource()::getUrl('index');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\ParticipantResource\Pages;
|
||||
|
||||
use App\Filament\Resources\ParticipantResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
|
||||
class ListParticipants extends ListRecords
|
||||
{
|
||||
protected static string $resource = ParticipantResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\CreateAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user