Replace BadgeColumn with editable SelectColumn, add Quick Edit action with time input fields, add column headers to leaderboard, and enable 5s polling

This commit is contained in:
ut-masekela
2026-03-25 08:42:13 +02:00
parent adc85b2b88
commit 6520926351
2 changed files with 94 additions and 16 deletions

View File

@@ -117,15 +117,9 @@ public static function table(Table $table): Table
->placeholder('—')
->fontFamily('mono')
->alignCenter(),
Tables\Columns\BadgeColumn::make('status')
->formatStateUsing(fn (string $state): string => Participant::statuses()[$state] ?? $state)
->colors([
'gray' => 'ready',
'info' => 'running',
'success' => 'finished',
'warning' => 'pit',
'danger' => 'dnf',
]),
Tables\Columns\SelectColumn::make('status')
->options(Participant::statuses())
->selectablePlaceholder(false),
Tables\Columns\TextColumn::make('updated_at')
->label('Updated')
->dateTime('H:i:s')
@@ -137,14 +131,69 @@ public static function table(Table $table): Table
->options(Participant::statuses()),
])
->actions([
Tables\Actions\EditAction::make(),
Tables\Actions\Action::make('quickEdit')
->label('Quick Edit')
->icon('heroicon-o-bolt')
->color('warning')
->modalHeading(fn ($record) => 'Quick Edit: ' . $record->name)
->modalWidth('md')
->form([
Forms\Components\Select::make('status')
->options(Participant::statuses())
->required(),
Forms\Components\Grid::make(3)
->schema([
Forms\Components\TextInput::make('time_minutes')
->label('Min')
->numeric()
->minValue(0)
->maxValue(59)
->placeholder('MM'),
Forms\Components\TextInput::make('time_seconds')
->label('Sec')
->numeric()
->minValue(0)
->maxValue(59)
->placeholder('SS'),
Forms\Components\TextInput::make('time_milliseconds')
->label('Ms')
->numeric()
->minValue(0)
->maxValue(999)
->placeholder('ms'),
]),
])
->fillForm(fn ($record) => [
'status' => $record->status,
'time_minutes' => $record->best_time_ms ? floor($record->best_time_ms / 60000) : null,
'time_seconds' => $record->best_time_ms ? floor(($record->best_time_ms % 60000) / 1000) : null,
'time_milliseconds' => $record->best_time_ms ? $record->best_time_ms % 1000 : null,
])
->action(function ($record, array $data) {
$minutes = $data['time_minutes'] ?? null;
$seconds = $data['time_seconds'] ?? null;
$milliseconds = $data['time_milliseconds'] ?? null;
$bestTimeMs = null;
if ($minutes !== null || $seconds !== null || $milliseconds !== null) {
$bestTimeMs = ((int)$minutes * 60000) + ((int)$seconds * 1000) + (int)$milliseconds;
}
$record->update([
'status' => $data['status'],
'best_time_ms' => $bestTimeMs,
]);
}),
Tables\Actions\EditAction::make()
->label('Full Edit'),
Tables\Actions\DeleteAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
])
->poll('5s');
}
public static function getRelations(): array

View File

@@ -99,8 +99,32 @@
</div>
</header>
<!-- Column Header -->
<div class="bg-[#111111] border-b border-gray-800">
<div class="w-full px-3 sm:px-4 lg:px-6 flex items-center h-8 sm:h-9 lg:h-10">
<!-- POS column -->
<div class="w-14 sm:w-16 lg:w-20 flex-shrink-0 flex items-center justify-center">
<span class="text-xs sm:text-sm lg:text-base text-white/60 uppercase tracking-wider">POS</span>
</div>
<!-- DRIVER column -->
<div class="flex-1 flex items-center px-4 lg:px-6">
<div class="flex-1">
<span class="text-xs sm:text-sm lg:text-base text-white/60 uppercase tracking-wider">DRIVER</span>
</div>
<!-- STATUS column -->
<div class="w-20 sm:w-24 lg:w-28 text-center">
<span class="text-xs sm:text-sm lg:text-base text-white/60 uppercase tracking-wider">STATUS</span>
</div>
<!-- TIME column -->
<div class="w-24 sm:w-28 lg:w-36 text-right">
<span class="text-xs sm:text-sm lg:text-base text-white/60 uppercase tracking-wider">TIME</span>
</div>
</div>
</div>
</div>
<!-- Leaderboard -->
<main class="w-full px-3 sm:px-4 lg:px-6 py-4 lg:py-6">
<main class="w-full px-3 sm:px-4 lg:px-6 py-3 lg:py-4">
@if($participants->isEmpty())
<div class="text-center py-20 lg:py-32">
@@ -156,7 +180,7 @@
<!-- Main Bar (Light) -->
<div class="bar-light flex-1 flex items-center px-4 lg:px-6">
<!-- Number + Name -->
<!-- Driver (Number + Name) -->
<div class="flex-1 min-w-0 flex items-center gap-2 lg:gap-4">
@if($participant->number)
<span class="tabular text-sm sm:text-base lg:text-xl text-gray-500">
@@ -166,16 +190,21 @@
<span class="text-lg sm:text-xl lg:text-3xl text-gray-900 uppercase tracking-wide truncate">
{{ $participant->name }}
</span>
</div>
<!-- Status -->
<div class="w-20 sm:w-24 lg:w-28 flex items-center justify-center flex-shrink-0">
@if($statusBadge)
<span class="px-2 py-0.5 lg:px-2.5 lg:py-1 {{ $statusBadge[0] }} text-xs lg:text-sm rounded flex-shrink-0">
<span class="px-2 py-0.5 lg:px-2.5 lg:py-1 {{ $statusBadge[0] }} text-xs lg:text-sm rounded">
{{ $statusBadge[1] }}
</span>
@else
<span class="text-xs lg:text-sm text-gray-400">READY</span>
@endif
</div>
<!-- Time -->
<div class="flex-shrink-0 text-right">
<div class="w-24 sm:w-28 lg:w-36 flex-shrink-0 text-right">
@if($timeDisplay)
<span class="tabular text-lg sm:text-xl lg:text-3xl text-gray-900">
{{ $timeDisplay }}