whereNotIn('status', ['delivered', 'cancelled'])->count(); return $open > 0 ? (string) $open : null; } public static function form(Schema $schema): Schema { return $schema->components([ Schemas\Components\Section::make('Lucrare') ->columns(3) ->schema([ Forms\Components\TextInput::make('number')->label('Nr.')->disabled()->dehydrated(false)->placeholder('Generat automat'), Forms\Components\Select::make('type')->label('Tip')->options(BodyshopJob::TYPES)->default('body_repair')->required(), Forms\Components\Select::make('status')->label('Status')->options(BodyshopJob::STATUSES)->default('estimate')->required(), Forms\Components\Select::make('client_id') ->label('Client') ->options(fn () => Client::pluck('name', 'id')) ->searchable()->live(), Forms\Components\Select::make('vehicle_id') ->label('Auto') ->options(fn (Get $get) => $get('client_id') ? Vehicle::where('client_id', $get('client_id'))->get() ->mapWithKeys(fn ($v) => [$v->id => "{$v->make} {$v->model} {$v->plate}"])->toArray() : []) ->searchable(), Forms\Components\TextInput::make('estimate_amount')->label('Deviz')->numeric()->default(0), Forms\Components\TextInput::make('approved_amount')->label('Aprobat')->numeric()->default(0), ]), Schemas\Components\Section::make('Asigurare') ->collapsible() ->columns(3) ->schema([ Forms\Components\Toggle::make('is_insurance')->label('Caz de asigurare')->live()->columnSpanFull(), Forms\Components\TextInput::make('insurer')->label('Asigurător') ->visible(fn (Get $get) => $get('is_insurance')), Forms\Components\TextInput::make('policy_no')->label('Nr. poliță') ->visible(fn (Get $get) => $get('is_insurance')), Forms\Components\TextInput::make('claim_no')->label('Nr. dosar daună') ->visible(fn (Get $get) => $get('is_insurance')), Forms\Components\Select::make('insurance_status')->label('Status dosar') ->options(BodyshopJob::INSURANCE_STATUSES) ->visible(fn (Get $get) => $get('is_insurance')), ]), Schemas\Components\Section::make('Foto înainte / după') ->columns(2) ->schema([ \Filament\Forms\Components\SpatieMediaLibraryFileUpload::make('photos_before') ->label('Înainte')->collection('photos_before')->multiple()->image()->reorderable()->maxFiles(20), \Filament\Forms\Components\SpatieMediaLibraryFileUpload::make('photos_after') ->label('După')->collection('photos_after')->multiple()->image()->reorderable()->maxFiles(20), ]), Forms\Components\Textarea::make('notes')->label('Observații')->columnSpanFull()->rows(2), ]); } public static function table(Table $table): Table { return $table ->columns([ Tables\Columns\TextColumn::make('number')->label('Nr.')->searchable()->sortable(), Tables\Columns\TextColumn::make('client.name')->label('Client')->searchable()->placeholder('—'), Tables\Columns\TextColumn::make('vehicle.plate')->label('Auto')->placeholder('—'), Tables\Columns\TextColumn::make('type') ->formatStateUsing(fn ($s) => BodyshopJob::TYPES[$s] ?? $s) ->badge()->color('info'), Tables\Columns\IconColumn::make('is_insurance')->label('Asig.')->boolean()->toggleable(), Tables\Columns\TextColumn::make('damage_points_count')->counts('damagePoints')->label('Daune')->alignRight(), Tables\Columns\TextColumn::make('approved_amount')->label('Aprobat')->money('MDL')->alignRight(), Tables\Columns\TextColumn::make('status') ->formatStateUsing(fn ($s) => BodyshopJob::STATUSES[$s] ?? $s) ->badge() ->colors([ 'gray' => ['estimate'], 'info' => ['approved', 'in_progress'], 'success' => ['done', 'delivered'], 'danger' => ['cancelled'], ]), ]) ->filters([ Tables\Filters\SelectFilter::make('type')->options(BodyshopJob::TYPES), Tables\Filters\SelectFilter::make('status')->options(BodyshopJob::STATUSES), Tables\Filters\TernaryFilter::make('is_insurance')->label('Caz asigurare'), ]) ->actions([ Actions\EditAction::make(), Actions\DeleteAction::make(), ]) ->emptyStateHeading('Nicio lucrare de caroserie') ->emptyStateDescription('Înregistrează lucrări de tinichigerie, vopsitorie, PDR, detailing, ceramică, PPF sau polish. Hartă daune, dosar asigurare și arhivă foto înainte/după.') ->emptyStateIcon('heroicon-o-paint-brush') ->defaultSort('created_at', 'desc'); } public static function getRelations(): array { return [ RelationManagers\DamagePointsRelationManager::class, ]; } public static function getNavigationLabel(): string { return __('Tinichigerie / Detailing'); } public static function getNavigationGroup(): ?string { return __('Tinichigerie'); } public static function getModelLabel(): string { return __('lucrare caroserie'); } public static function getPluralModelLabel(): string { return __('lucrări caroserie'); } public static function getPages(): array { return [ 'index' => Pages\ListBodyshopJobs::route('/'), 'create' => Pages\CreateBodyshopJob::route('/create'), 'edit' => Pages\EditBodyshopJob::route('/{record}/edit'), ]; } }