Aug 27, 2025
0
Level 1
Schema has no [record()] or [state()] set. on ViewAction
I'm getting this on an actionview
<?php
namespace App\Filament\Resources\Bookings\Pages;
use App\Enums\Booking\State as BookingState;
use App\Enums\Payment\Method as PaymentMethod;
use App\Filament\Resources\Bookings\BookingResource;
use App\Filament\Widgets\DateSelectorWidget;
use App\Filament\Widgets\StaffFilterWidget;
use App\Filament\Widgets\TodayBookingsWidget;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\ForceDeleteBulkAction;
use Filament\Actions\RestoreBulkAction;
use Filament\Resources\Pages\ListRecords;
use Filament\Tables\Columns\TextColumn;
use App\Models\Booking;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Carbon;
use Filament\Schemas\Components\Tabs;
use Filament\Schemas\Components\Tabs\Tab;
use Filament\Actions\ViewAction;
use Filament\Forms\Components\TextInput;
use Filament\Actions\ActionGroup;
use Filament\Actions\ButtonAction;
use Filament\Infolists\Components\TextEntry;
use Filament\Infolists\Infolist;
use Filament\Actions\Action;
use Filament\Notifications\Notification;
use Filament\Forms\Components\Select;
use Filament\Facades\Filament;
use Livewire\Component;
use Livewire\Attributes\On;
class ListBookings extends ListRecords
{
#[On('ListBookings:refresh')]
public function refresh(): void {}
protected static string $resource = BookingResource::class;
public ?string $selectedDate = null;
public ?string $selectedStaff = null;
protected $listeners = [
'date-changed-to-parent' => 'onDateChanged',
'staff-changed-to-parent' => 'onStaffChanged',
'refresh' => '$refresh',
];
public function mount(): void
{
parent::mount();
if (! $this->selectedDate) {
$this->selectedDate = now()->toDateString();
}
}
protected function getHeaderActions(): array
{
return [];
}
public function getTabs(): array
{
return [
'pending' => Tab::make(__('Pending'))
->badge(fn(): string => (string) $this->getFilteredQuery()->whereIn('status', BookingState::pending(asValues: true))->count())
->badgeColor('warning')
->modifyQueryUsing(fn(Builder $query): Builder => $query->whereIn('status', BookingState::pending(asValues: true))),
'all' => Tab::make(__('All'))
->badgeColor('gray')
->modifyQueryUsing(fn(Builder $query): Builder => $query),
];
}
protected function getFilteredQuery(): Builder
{
$query = Booking::query();
if ($this->selectedDate) {
$query->whereDate('start_date', $this->selectedDate);
}
if ($this->selectedStaff) {
$query->where('staff_id', $this->selectedStaff);
}
return $query;
}
public function getHeaderWidgets(): array
{
return [
TodayBookingsWidget::class,
DateSelectorWidget::class,
StaffFilterWidget::class,
];
}
public function table(Table $table): Table
{
return $table
->columns([
TextColumn::make('start_date')
->label(__('Time'))
->formatStateUsing(function ($record) {
$startTime = Carbon::parse($record->start_date)->format('H:i');
$endTime = Carbon::parse($record->end_date)->format('H:i');
return "{$startTime} - {$endTime}";
})
->sortable()
->wrap()
->width('120px'),
TextColumn::make('client.first_name')
->label(__('Client'))
->formatStateUsing(fn($record) => $record->client->first_name . ' ' . $record->client->last_name)
->sortable()
->searchable()
->wrap()
->width('200px'),
TextColumn::make('service.name')
->label(__('Service'))
->sortable()
->wrap()
->width('180px'),
TextColumn::make('staff.first_name')
->label(__('Staff'))
->sortable()
->wrap()
->width('150px'),
TextColumn::make('payment_method')
->label(__('Payment Method'))
->badge()
->formatStateUsing(fn($state, $record) => PaymentMethod::from($record->payment_method)->getLabel())
->color(fn($state, $record) => PaymentMethod::from($record->payment_method)->getColor())
->icon(fn($state, $record) => PaymentMethod::from($record->payment_method)->getIcon())
->searchable()
->wrap()
->width('140px'),
])
->modifyQueryUsing(function (Builder $query): Builder {
if ($this->selectedDate) {
$query->whereDate('start_date', $this->selectedDate);
}
if ($this->selectedStaff) {
$query->where('staff_id', $this->selectedStaff);
}
return $query;
})
->recordActions([
ActionGroup::make([
ViewAction::make()
->schema([
TextEntry::make('start_date')
->label(__('Time'))
->formatStateUsing(function ($record) {
$startTime = Carbon::parse($record->start_date)->format('H:i');
$endTime = Carbon::parse($record->end_date)->format('H:i');
return "{$startTime} - {$endTime}";
}),
TextEntry::make('client.first_name')
->label(__('Client'))
->formatStateUsing(fn($record) => $record->client->first_name . ' ' . $record->client->last_name),
TextEntry::make('client.phone')
->label(__('Contact'))
->badge()
->icon('heroicon-o-phone')
->url(fn($record) => 'https://wa.me/' . preg_replace('/\D/', '', $record->client->phone)),
TextEntry::make('client.email')
->label(__('Email'))
->badge()
->icon('heroicon-o-envelope')
->url(fn($record) => 'mailto:' . $record->client->email),
TextEntry::make('service.name')
->label(__('Service')),
TextEntry::make('staff.first_name')
->label(__('Staff'))
->formatStateUsing(fn($record) => $record->staff->first_name . ' ' . $record->staff->last_name),
TextEntry::make('payment_method')
->label(__('Payment Method'))
->badge()
->formatStateUsing(fn($state, $record) => PaymentMethod::from($record->payment_method)->getLabel())
->color(fn($state, $record) => PaymentMethod::from($record->payment_method)->getColor()),
TextEntry::make('status')
->label(__('Booking Status'))
->badge()
->formatStateUsing(fn($state, $record) => $record->status->getLabel())
->color(fn($state, $record) => $record->status->getColor()),
TextEntry::make('total')
->label(__('Total'))
->money('UYU')
])
->extraModalFooterActions([
$this->getCompleteAction(),
$this->getCancelAction()
])
->slideOver(),
])
])
->toolbarActions([
BulkActionGroup::make([
DeleteBulkAction::make(),
ForceDeleteBulkAction::make(),
RestoreBulkAction::make(),
]),
]);
}
public function onDateChanged(string $date): void
{
$this->selectedDate = $date;
$this->resetTable();
}
public function onStaffChanged(?string $staffId): void
{
$this->selectedStaff = $staffId;
$this->resetTable();
}
private function getCompleteAction(): Action
{
/** @var \App\Models\User $user */
$user = Filament::auth()->user();
return Action::make('completeBooking')
->label(__('Complete'))
->requiresConfirmation()
->icon('heroicon-o-check-circle')
->color('success')
->outlined()
->action(function (Booking $record, Component $livewire): void {
$record->update(['status' => BookingState::Completed]);
$livewire->dispatch('ListBookings:refresh');
});
}
public function getCancelAction(): Action
{
return Action::make('cancelBooking')
->label(__('Cancel'))
->requiresConfirmation()
->icon('heroicon-o-x-circle')
->color('danger')
->outlined()
->action(function (Booking $record, Component $livewire): void {
$record->update(['status' => BookingState::Cancelled]);
$livewire->dispatch('ListBookings:refresh');
});
}
}
Please or to participate in this conversation.