count() ?: null; } public static function getNavigationBadgeColor(): ?string { return 'danger'; } public static function getGloballySearchableAttributes(): array { return ['subject']; } public static function getGlobalSearchResultTitle(Model $record): string|Htmlable { return $record->subject; } public static function form(Form $form): Form { return $form ->schema([ Forms\Components\TextInput::make('subject') ->label('Subject') ->columnSpan(function ($record) { return $record ? 2 : 1; }) ->required(), Forms\Components\Select::make('status') ->label('Status') ->options([ 'open' => 'Open', 'closed' => 'Closed', 'replied' => 'Replied', ]) ->columnSpan(function ($record) { return $record ? 2 : 1; }) ->default('open') ->required(), Forms\Components\Select::make('priority') ->label('Priority') ->options([ 'low' => 'Low', 'medium' => 'Medium', 'high' => 'High', ]) ->columnSpan(function ($record) { return $record ? 2 : 1; }) ->default('medium') ->required(), Forms\Components\Select::make('department') ->label('Department') ->options(array_combine(config('settings.ticket_departments'), config('settings.ticket_departments'))) ->columnSpan(function ($record) { return $record ? 2 : 1; }), UserComponent::make('user_id')->columnSpan(function ($record) { return $record ? 2 : 1; }), Forms\Components\Select::make('assigned_to') ->label('Assigned To') ->searchable() ->preload() ->relationship('user', 'id', fn (Builder $query) => $query->where('role_id', '!=', null)) ->getOptionLabelFromRecordUsing(fn ($record) => $record->name) ->columnSpan(function ($record) { return $record ? 2 : 1; }), Forms\Components\Select::make('service_id') ->label('Service') ->relationship('service', 'id', function (Builder $query, Get $get) { $query->where('user_id', $get('user_id')); }) ->getOptionLabelFromRecordUsing(fn ($record) => "{$record->product->name} - " . ucfirst($record->status)) ->columnSpan(function ($record) { return $record ? 2 : 1; }) ->disabled(fn (Get $get) => !$get('user_id')), Forms\Components\MarkdownEditor::make('message') ->columnSpan(2) ->label('Initial Message') ->hiddenOn('edit') ->columnSpan(function ($record) { return $record ? 2 : 1; }) ->required(), ]); } public static function table(Table $table): Table { return $table ->columns([ Tables\Columns\TextColumn::make('subject') ->limit(40) ->searchable() ->sortable(), Tables\Columns\TextColumn::make('status') ->sortable() ->badge() ->color(fn (Ticket $record) => match ($record->status) { 'open' => 'success', 'closed' => 'danger', 'replied' => 'warning', }) ->formatStateUsing(fn (string $state) => ucfirst($state)), Tables\Columns\TextColumn::make('priority') ->sortable() ->badge() ->color(fn (Ticket $record) => match ($record->priority) { 'low' => 'success', 'medium' => 'gray', 'high' => 'danger', }) ->formatStateUsing(fn (string $state) => ucfirst($state)), Tables\Columns\TextColumn::make('department') ->formatStateUsing(fn ($state) => array_combine(config('settings.ticket_departments'), config('settings.ticket_departments'))[$state]) ->sortable(), Tables\Columns\TextColumn::make('user.name') ->searchable(['first_name', 'last_name']) ->sortable(['first_name', 'last_name']), Tables\Columns\TextColumn::make('user.email') ->label('Email') ->searchable(), ]) ->filters([ // ]) ->actions([ Tables\Actions\EditAction::make(), ]) ->bulkActions([ Tables\Actions\BulkActionGroup::make([ Tables\Actions\DeleteBulkAction::make(), ]), ]) ->defaultSort('id', 'desc'); } public static function getWidgets(): array { return [ TicketsOverView::class, ]; } public static function getPages(): array { return [ 'index' => Pages\ListTickets::route('/'), 'create' => Pages\CreateTicket::route('/create'), 'edit' => Pages\EditTicket::route('/{record}/edit'), ]; } }