From 3c7e5fffbf453ce0656b1047a90c4be919fe33cf Mon Sep 17 00:00:00 2001 From: Vasyka Date: Fri, 4 Sep 2026 19:56:40 +0000 Subject: [PATCH] improve WO form: inline client/vehicle create, mechanic filter, category translation, PDF emoji fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - client_id field: switched to relationship() with createOptionForm so new clients can be created inline (name, phone, email); search also matches by phone - vehicle_id field: added createOptionForm (make, model, plate, year, VIN); newly created vehicle is automatically linked to the currently selected client - master_id field: now shows only active users with role mechanic/master - WorksRelationManager: labor catalog select marked optional; added createOptionForm so new catalog entries can be added without leaving the WO form - SubcontractJobsRelationManager: category table column now translates value via __() and shows explicit label(__('Categorie')) - PDF work-order: replaced 📞 / ✉ / ⚠ emojis with plain-text equivalents so DomPDF/DejaVu Sans renders them correctly instead of showing "????" Co-Authored-By: Claude Sonnet 4.6 --- .../Tenant/Resources/WorkOrderResource.php | 31 ++++++++++++++++--- .../SubcontractJobsRelationManager.php | 4 ++- .../RelationManagers/WorksRelationManager.php | 14 ++++++++- resources/views/pdf/work-order.blade.php | 6 ++-- 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/app/Filament/Tenant/Resources/WorkOrderResource.php b/app/Filament/Tenant/Resources/WorkOrderResource.php index a57c29b..4a7ddda 100644 --- a/app/Filament/Tenant/Resources/WorkOrderResource.php +++ b/app/Filament/Tenant/Resources/WorkOrderResource.php @@ -84,16 +84,39 @@ class WorkOrderResource extends Resource Forms\Components\Select::make('urgency')->label(__('Urgență')) ->options(\App\Support\I18n::opts(\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()->columnSpan(2), + ->relationship('client', 'name') + ->getSearchResultsUsing(fn (string $query) => + Client::where(fn ($q) => $q + ->where('name', 'like', "%{$query}%") + ->orWhere('phone', 'like', "%{$query}%")) + ->limit(30)->pluck('name', 'id')) + ->searchable()->live()->required()->columnSpan(2) + ->createOptionForm([ + Forms\Components\TextInput::make('name')->label(__('Nume'))->required(), + Forms\Components\TextInput::make('phone')->label(__('Telefon')), + Forms\Components\TextInput::make('email')->label(__('Email'))->email(), + ]), 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()->columnSpan(2), + ->searchable()->columnSpan(2) + ->createOptionForm([ + Forms\Components\TextInput::make('make')->label(__('Marcă'))->required(), + Forms\Components\TextInput::make('model')->label(__('Model'))->required(), + Forms\Components\TextInput::make('plate')->label(__('Nr. înmatriculare'))->required(), + Forms\Components\TextInput::make('year')->label(__('An'))->numeric(), + Forms\Components\TextInput::make('vin')->label(__('VIN')), + ]) + ->createOptionUsing(function (array $data, \Livewire\Component $livewire) { + $data['client_id'] = data_get((array) $livewire->data, 'client_id'); + return Vehicle::create($data)->id; + }), Forms\Components\Select::make('master_id')->label(__('Maistru')) - ->options(fn () => User::where('status', 'active')->pluck('name', 'id')) + ->options(fn () => User::where('status', 'active') + ->whereIn('role', ['mechanic', 'master']) + ->pluck('name', 'id')) ->searchable()->columnSpan(2), Forms\Components\TextInput::make('mileage_in')->label(__('Km intrare'))->numeric(), Forms\Components\TextInput::make('mileage_out')->label(__('Km ieșire'))->numeric(), diff --git a/app/Filament/Tenant/Resources/WorkOrderResource/RelationManagers/SubcontractJobsRelationManager.php b/app/Filament/Tenant/Resources/WorkOrderResource/RelationManagers/SubcontractJobsRelationManager.php index e3dc0ca..60013ea 100644 --- a/app/Filament/Tenant/Resources/WorkOrderResource/RelationManagers/SubcontractJobsRelationManager.php +++ b/app/Filament/Tenant/Resources/WorkOrderResource/RelationManagers/SubcontractJobsRelationManager.php @@ -51,7 +51,9 @@ class SubcontractJobsRelationManager extends RelationManager ->columns([ Tables\Columns\TextColumn::make('number')->label(__('Nr.')), Tables\Columns\TextColumn::make('subcontractor.name')->label(__('Terț'))->placeholder('—'), - Tables\Columns\TextColumn::make('category')->badge()->placeholder('—'), + Tables\Columns\TextColumn::make('category')->label(__('Categorie')) + ->formatStateUsing(fn ($s) => $s ? __($s) : '—') + ->badge()->placeholder('—'), Tables\Columns\TextColumn::make('cost')->money('MDL')->alignRight(), Tables\Columns\TextColumn::make('client_price')->label(__('Preț client'))->money('MDL')->alignRight(), Tables\Columns\TextColumn::make('margin') diff --git a/app/Filament/Tenant/Resources/WorkOrderResource/RelationManagers/WorksRelationManager.php b/app/Filament/Tenant/Resources/WorkOrderResource/RelationManagers/WorksRelationManager.php index 24c198c..d3b22d3 100644 --- a/app/Filament/Tenant/Resources/WorkOrderResource/RelationManagers/WorksRelationManager.php +++ b/app/Filament/Tenant/Resources/WorkOrderResource/RelationManagers/WorksRelationManager.php @@ -28,7 +28,7 @@ class WorksRelationManager extends RelationManager { return $schema->components([ Forms\Components\Select::make('labor_id') - ->label(__('Catalog manoperă')) + ->label(__('Catalog manoperă') . ' (' . __('opțional') . ')') ->options(fn () => Labor::where('is_active', true) ->get() ->mapWithKeys(fn ($l) => [$l->id => '[' . __($l->category) . '] ' . $l->label() . ' (' . $l->hours . __('h') . ')']) @@ -42,6 +42,18 @@ class WorksRelationManager extends RelationManager $set('price_per_hour', $labor->hours > 0 ? round($labor->price / max((float) $labor->hours, 1), 2) : 0); } }) + ->createOptionForm([ + Forms\Components\Select::make('category')->label(__('Categorie')) + ->options(\App\Support\I18n::opts(array_combine(Labor::CATEGORIES, Labor::CATEGORIES))) + ->required(), + Forms\Components\TextInput::make('name_ro')->label(__('Denumire'))->required(), + Forms\Components\TextInput::make('hours')->label(__('Ore normate'))->numeric()->default(1)->required(), + Forms\Components\TextInput::make('price')->label(__('Preț total (MDL)'))->numeric()->default(0)->required(), + ]) + ->createOptionUsing(function (array $data) { + $data['is_active'] = true; + return Labor::create($data)->id; + }) ->columnSpanFull(), Forms\Components\TextInput::make('name')->label(__('Nume'))->required()->columnSpanFull(), Forms\Components\TextInput::make('hours')->label(__('Ore'))->numeric()->default(1)->required(), diff --git a/resources/views/pdf/work-order.blade.php b/resources/views/pdf/work-order.blade.php index 59ac36f..59c6da2 100644 --- a/resources/views/pdf/work-order.blade.php +++ b/resources/views/pdf/work-order.blade.php @@ -126,10 +126,10 @@
{{ $company->city }}
@endif @if ($company->phone) -
📞 {{ $company->phone }}
+
Tel.: {{ $company->phone }}
@endif @if ($company->email) -
✉ {{ $company->email }}
+
Email: {{ $company->email }}
@endif
@@ -268,7 +268,7 @@ @if ($wo->recommendations)
-

{{ __('⚠ Recomandări') }}

+

{{ __('Recomandări') }}

{{ $wo->recommendations }}
@endif