count(); return $stored > 0 ? (string) $stored : null; } public static function getNavigationBadgeColor(): ?string { return 'info'; } public static function form(Schema $schema): Schema { return $schema->components([ Schemas\Components\Section::make(__('Proprietar')) ->columns(2) ->schema([ Forms\Components\Select::make('client_id') ->label(__('Client')) ->options(fn () => Client::pluck('name', 'id')) ->searchable() ->live() ->required(), 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('label')->label(__('Etichetă'))->placeholder(__('ex: Iarnă Michelin')), Forms\Components\Select::make('season')->label(__('Sezon'))->options(\App\Support\I18n::opts(TireSet::SEASONS))->default('winter')->required(), ]), Schemas\Components\Section::make(__('Specificații')) ->columns(3) ->schema([ Forms\Components\TextInput::make('width')->label(__('Lățime'))->numeric()->placeholder('205'), Forms\Components\TextInput::make('profile')->label(__('Profil'))->numeric()->placeholder('55'), Forms\Components\TextInput::make('diameter')->label(__('Diametru R'))->numeric()->placeholder('16'), Forms\Components\TextInput::make('brand')->maxLength(64), Forms\Components\TextInput::make('model')->maxLength(64), Forms\Components\TextInput::make('dot_year')->label(__('DOT'))->maxLength(8)->placeholder('3621'), Forms\Components\Toggle::make('has_rims')->label(__('Cu jante')), Forms\Components\Select::make('rim_type')->label(__('Tip jante'))->options(['steel' => __('Tablă'), 'alloy' => 'Aliaj']), Forms\Components\Select::make('condition')->label(__('Stare'))->options(\App\Support\I18n::opts(TireSet::CONDITIONS)), ]), Schemas\Components\Section::make(__('Uzură (mm) per poziție')) ->columns(4) ->schema([ Forms\Components\TextInput::make('tread.fl')->label(__('Față-Stânga'))->numeric(), Forms\Components\TextInput::make('tread.fr')->label(__('Față-Dreapta'))->numeric(), Forms\Components\TextInput::make('tread.rl')->label(__('Spate-Stânga'))->numeric(), Forms\Components\TextInput::make('tread.rr')->label(__('Spate-Dreapta'))->numeric(), ]), Schemas\Components\Section::make(__('TPMS & foto')) ->columns(2) ->schema([ Forms\Components\Toggle::make('tpms')->label(__('Senzori TPMS')), Forms\Components\TextInput::make('notes')->label(__('Observații')), \Filament\Forms\Components\SpatieMediaLibraryFileUpload::make('photos') ->label(__('Fotografii')) ->collection('photos') ->multiple() ->image() ->maxFiles(8) ->columnSpanFull(), ]), ]); } public static function table(Table $table): Table { return $table ->columns([ Tables\Columns\TextColumn::make('client.name')->label(__('Client'))->searchable()->sortable(), Tables\Columns\TextColumn::make('label')->label(__('Etichetă'))->placeholder('—'), Tables\Columns\TextColumn::make('size') ->label(__('Dimensiune')) ->state(fn (TireSet $r) => $r->sizeLabel()), Tables\Columns\TextColumn::make('season') ->label(__('Sezon')) ->formatStateUsing(fn ($s) => TireSet::SEASONS[$s] ?? $s) ->badge() ->colors(['warning' => ['summer'], 'info' => ['winter'], 'gray' => ['allseason']]), Tables\Columns\TextColumn::make('tread_min')->label(__('Uzură min')) ->formatStateUsing(fn ($s) => $s ? $s . ' mm' : '—') ->color(fn ($s) => $s !== null && (float) $s < 3 ? 'danger' : null) ->alignRight(), Tables\Columns\IconColumn::make('tpms')->label(__('TPMS'))->boolean()->toggleable(), Tables\Columns\TextColumn::make('storage_status') ->label(__('Depozit')) ->state(fn (TireSet $r) => $r->isStored() ? ($r->currentStorage()?->location ?? 'da') : '—') ->badge() ->color(fn ($state) => $state === '—' ? 'gray' : 'success'), ]) ->filters([ Tables\Filters\SelectFilter::make('season')->options(\App\Support\I18n::opts(TireSet::SEASONS)), Tables\Filters\Filter::make('stored') ->label(__('În depozit')) ->query(fn ($q) => $q->whereHas('storage', fn ($s) => $s->where('status', 'stored'))), ]) ->actions([ Actions\Action::make('check_in') ->label(__('Check-in depozit')) ->icon('heroicon-m-arrow-down-on-square') ->color('success') ->visible(fn (TireSet $r) => ! $r->isStored()) ->schema([ Forms\Components\TextInput::make('location')->label(__('Locație (raft)'))->required()->placeholder(__('A1-03')), Forms\Components\TextInput::make('season_label')->label(__('Perioadă'))->placeholder(__('Iarnă 2025-2026')), Forms\Components\TextInput::make('fee')->label(__('Taxă depozitare'))->numeric()->default(0), ]) ->action(function (TireSet $r, array $data) { \App\Models\Tenant\TireStorage::create([ 'tire_set_id' => $r->id, 'location' => $data['location'], 'season_label' => $data['season_label'] ?? null, 'fee' => (float) ($data['fee'] ?? 0), 'status' => 'stored', 'checked_in_at' => now(), ]); \Filament\Notifications\Notification::make()->title(__('Set primit în depozit'))->success()->send(); }), Actions\Action::make('check_out') ->label(__('Eliberează')) ->icon('heroicon-m-arrow-up-on-square') ->color('warning') ->visible(fn (TireSet $r) => $r->isStored()) ->requiresConfirmation() ->modalDescription(__('Marchează setul ca ridicat de client.')) ->action(function (TireSet $r) { $storage = $r->currentStorage(); if ($storage) { $storage->update(['status' => 'retrieved', 'checked_out_at' => now()]); } \Filament\Notifications\Notification::make()->title(__('Set eliberat din depozit'))->success()->send(); }), Actions\EditAction::make(), Actions\DeleteAction::make(), ]) ->emptyStateHeading(__('Niciun set de anvelope')) ->emptyStateDescription(__('Înregistrează seturile de anvelope ale clienților și gestionează depozitarea sezonieră (tire hotel). Urmărește uzura, TPMS și locația în depozit.')) ->emptyStateIcon('heroicon-o-lifebuoy') ->defaultSort('created_at', 'desc'); } public static function getRelations(): array { return [ RelationManagers\StorageRelationManager::class, ]; } public static function getModelLabel(): string { return __('set anvelope'); } public static function getPluralModelLabel(): string { return __('seturi anvelope'); } public static function getPages(): array { return [ 'index' => Pages\ListTireSets::route('/'), 'create' => Pages\CreateTireSet::route('/create'), 'edit' => Pages\EditTireSet::route('/{record}/edit'), ]; } }