columns([ TextColumn::make('service') ->badge() ->color(fn (string $state) => match ($state) { 'fuel_finder' => 'success', 'fred' => 'info', 'anthropic' => 'warning', default => 'gray', }) ->sortable(), TextColumn::make('method') ->badge() ->color('gray'), TextColumn::make('url') ->limit(60) ->tooltip(fn (ApiLog $record) => $record->url), TextColumn::make('status_code') ->badge() ->color(fn (?int $state) => match (true) { $state === null => 'danger', $state >= 500 => 'danger', $state >= 400 => 'warning', default => 'success', }), TextColumn::make('duration_ms') ->label('Duration (ms)') ->sortable(), TextColumn::make('error') ->limit(40) ->placeholder('—'), TextColumn::make('created_at') ->dateTime('d M Y H:i') ->sortable(), ]) ->defaultSort('created_at', 'desc') ->filters([ SelectFilter::make('service') ->options([ 'fuel_finder' => 'Fuel Finder', 'fred' => 'FRED', 'anthropic' => 'Anthropic', 'postcodes_io' => 'Postcodes.io', ]), Filter::make('errors_only') ->label('Errors only') ->query(fn (Builder $query) => $query->where( fn (Builder $q) => $q->where('status_code', '>=', 400) ->orWhereNull('status_code') ->orWhereNotNull('error') )), Filter::make('created_at') ->schema([ DatePicker::make('from')->label('From'), DatePicker::make('until')->label('Until'), ]) ->query(function (Builder $query, array $data) { $query ->when($data['from'], fn ($q, $d) => $q->whereDate('created_at', '>=', $d)) ->when($data['until'], fn ($q, $d) => $q->whereDate('created_at', '<=', $d)); }), ]) ->recordActions([ ViewAction::make(), ]); } public static function infolist(Schema $schema): Schema { return $schema->components([ Section::make('Request')->schema([ TextEntry::make('service')->badge(), TextEntry::make('method'), TextEntry::make('url')->columnSpanFull(), TextEntry::make('status_code') ->badge() ->color(fn (?int $state) => match (true) { $state === null => 'danger', $state >= 500 => 'danger', $state >= 400 => 'warning', default => 'success', }), TextEntry::make('duration_ms')->label('Duration (ms)'), TextEntry::make('created_at')->dateTime('d M Y H:i:s'), ])->columns(3), Section::make('Error')->schema([ TextEntry::make('error') ->columnSpanFull() ->placeholder('No error recorded'), ])->collapsed(fn (ApiLog $record) => $record->error === null), ]); } public static function getPages(): array { return [ 'index' => ListApiLogs::route('/'), 'view' => ViewApiLog::route('/{record}'), ]; } }