diff --git a/app/Filament/Tenant/Resources/WorkOrderResource.php b/app/Filament/Tenant/Resources/WorkOrderResource.php index 3b4e433..36faa46 100644 --- a/app/Filament/Tenant/Resources/WorkOrderResource.php +++ b/app/Filament/Tenant/Resources/WorkOrderResource.php @@ -56,101 +56,68 @@ class WorkOrderResource extends Resource public static function form(Schema $schema): Schema { return $schema->components([ - Schemas\Components\Section::make('Antet') - ->columns(3) + // Antet compact — o singură secțiune densă cu doar esențialul, mereu deschisă. + Schemas\Components\Section::make('Antet fișă') + ->description('Informația de bază — click pe titlul secțiunilor de mai jos pentru detalii.') + ->compact() + ->columns(4) ->schema([ - Forms\Components\TextInput::make('number') - ->label('Nr.') - ->disabled() - ->dehydrated(false) - ->placeholder('Generat automat'), - Forms\Components\DatePicker::make('opened_at') - ->label('Deschis') - ->default(today()) - ->required(), - Forms\Components\Select::make('status') - ->options(WorkOrder::STATUSES) - ->default('new') - ->required(), - Forms\Components\Select::make('urgency') - ->label('Urgență') - ->options(\App\Models\Tenant\PricingCoefficient::URGENCY) - ->default('normal') - ->required(), - Forms\Components\Select::make('client_id') - ->label('Client') + Forms\Components\TextInput::make('number')->label('Nr.')->disabled()->dehydrated(false)->placeholder('auto'), + Forms\Components\DatePicker::make('opened_at')->label('Deschis')->default(today())->required(), + Forms\Components\Select::make('status')->options(WorkOrder::STATUSES)->default('new')->required(), + Forms\Components\Select::make('urgency')->label('Urgență') + ->options(\App\Models\Tenant\PricingCoefficient::URGENCY)->default('normal')->required(), + 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') + ->searchable()->live()->required()->columnSpan(2), + 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() + ? Vehicle::where('client_id', $get('client_id'))->get() + ->mapWithKeys(fn ($v) => [$v->id => "{$v->make} {$v->model} {$v->plate}"])->toArray() : []) - ->searchable(), - Forms\Components\Select::make('master_id') - ->label('Maistru') + ->searchable()->columnSpan(2), + Forms\Components\Select::make('master_id')->label('Maistru') ->options(fn () => User::where('status', 'active')->pluck('name', 'id')) - ->searchable(), - Forms\Components\TextInput::make('mileage_in')->label('Km la intrare')->numeric(), - Forms\Components\TextInput::make('mileage_out')->label('Km la ieșire')->numeric(), + ->searchable()->columnSpan(2), + Forms\Components\TextInput::make('mileage_in')->label('Km intrare')->numeric(), + Forms\Components\TextInput::make('mileage_out')->label('Km ieșire')->numeric(), ]), + + // Toate secțiunile de detaliu — collapsible și collapsed by default Schemas\Components\Section::make('Diagnostic') - ->collapsible() + ->collapsible()->collapsed()->compact() ->schema([ Forms\Components\Textarea::make('complaint')->label('Plângere client')->rows(2)->columnSpanFull(), Forms\Components\Textarea::make('diagnosis')->label('Diagnostic')->rows(3)->columnSpanFull(), Forms\Components\Textarea::make('recommendations')->label('Recomandări')->rows(2)->columnSpanFull(), ]), Schemas\Components\Section::make('Foto') - ->collapsible() + ->collapsible()->collapsed()->compact() ->schema([ \Filament\Forms\Components\SpatieMediaLibraryFileUpload::make('photos') - ->label('Fotografii') - ->collection('photos') - ->multiple() - ->reorderable() - ->image() - ->imageEditor() - ->maxFiles(20) + ->label('Fotografii')->collection('photos') + ->multiple()->reorderable()->image()->imageEditor()->maxFiles(20) ->columnSpanFull(), ]), Schemas\Components\Section::make('Tracking & ETA') - ->columns(3) - ->collapsible() + ->columns(3)->collapsible()->collapsed()->compact() ->schema([ - Forms\Components\DateTimePicker::make('eta_at') - ->label('Gata estimat (ETA)') - ->seconds(false), - Forms\Components\TextInput::make('tracking_token') - ->label('Token public') - ->disabled() - ->dehydrated(false) - ->columnSpan(2) + Forms\Components\DateTimePicker::make('eta_at')->label('Gata estimat (ETA)')->seconds(false), + Forms\Components\TextInput::make('tracking_token')->label('Token public') + ->disabled()->dehydrated(false)->columnSpan(2) ->helperText(fn (?WorkOrder $record) => $record?->tracking_token ? 'Link client: ' . $record->trackingUrl() : 'Se generează la salvare'), ]), Schemas\Components\Section::make('Plată & total') - ->columns(3) + ->columns(3)->collapsible()->collapsed()->compact() ->schema([ - Forms\Components\Select::make('pay_status') - ->options(WorkOrder::PAY_STATUSES) - ->default('unpaid') - ->required(), + Forms\Components\Select::make('pay_status')->options(WorkOrder::PAY_STATUSES)->default('unpaid')->required(), Forms\Components\TextInput::make('discount_pct')->label('Discount %')->numeric()->default(0), - Forms\Components\TextInput::make('override_margin_pct') - ->label('Marjă internă (%) — override') - ->numeric() - ->step(0.01) - ->minValue(0) - ->maxValue(90) - ->placeholder('Ex: 25 pentru VIP / contract') - ->helperText('Doar pentru cazuri speciale. Lasă gol pentru a folosi marja mecanicului.') + Forms\Components\TextInput::make('override_margin_pct')->label('Marjă internă (%) — override') + ->numeric()->step(0.01)->minValue(0)->maxValue(90) + ->placeholder('Ex: 25') + ->helperText('Doar pentru cazuri speciale. Lasă gol → folosește marja mecanicului.') ->visible(fn () => auth()->user()?->canDo(\App\Auth\Permissions::FINANCE_VIEW_INTERNAL_MARGIN) ?? false), Forms\Components\TextInput::make('total')->label('Total')->numeric()->disabled()->dehydrated(false), Forms\Components\Toggle::make('approved')->label('Aprobat de client'), diff --git a/app/Filament/Tenant/Resources/WorkOrderResource/Pages/EditWorkOrder.php b/app/Filament/Tenant/Resources/WorkOrderResource/Pages/EditWorkOrder.php index c3ccbbc..ba614f3 100644 --- a/app/Filament/Tenant/Resources/WorkOrderResource/Pages/EditWorkOrder.php +++ b/app/Filament/Tenant/Resources/WorkOrderResource/Pages/EditWorkOrder.php @@ -12,6 +12,23 @@ class EditWorkOrder extends EditRecord { protected static string $resource = WorkOrderResource::class; + /** Manopere / Piese / Subcontract / Plăți se afișează SUS ca taburi, apoi antetul. */ + public function hasCombinedRelationManagerTabsWithContent(): bool + { + return true; + } + + public function getContentTabLabel(): ?string + { + return 'ⓘ Info & antet'; + } + + public function getContentTabPosition(): ?\Filament\Resources\Pages\Enums\ContentTabPosition + { + // Puts the form (content) AFTER all relation manager tabs + return \Filament\Resources\Pages\Enums\ContentTabPosition::After; + } + protected function getHeaderActions(): array { return [ diff --git a/app/Providers/Filament/TenantPanelProvider.php b/app/Providers/Filament/TenantPanelProvider.php index 7f6b36a..71de2a9 100644 --- a/app/Providers/Filament/TenantPanelProvider.php +++ b/app/Providers/Filament/TenantPanelProvider.php @@ -33,6 +33,7 @@ class TenantPanelProvider extends PanelProvider ->id('tenant') ->path('app') ->login() + ->sidebarCollapsibleOnDesktop() // permite îngustarea coloanei stânga cu un click ->brandName(fn () => app(\App\Tenancy\TenantManager::class)->current()?->display_name ?? app(\App\Tenancy\TenantManager::class)->current()?->name ?? 'AutoCRM')