Files
autocrm/app/Filament/Tenant/Resources/WorkOrderResource/Pages/EditWorkOrder.php
T
Vasyka 5a5f43f2de feat(pdf): inline preview by default with ?download=1 override + vehicle photo fallback
- WorkOrder and InjectorProtocol PDF routes now respond with
  Content-Disposition: inline (opens in browser tab so the user can
  read/print/save from the built-in PDF viewer). ?download=1 forces
  the classic attachment download.
- CalendarBoard exportPdf() switched to the same inline default.
- WO edit action + WO table row action + injector protocol actions
  now use ->url(...)->openUrlInNewTab() instead of streaming the PDF
  inline into the current tab.
- Dashboard Docs tab has both a preview link and a "Descarcă" link.
- Vehicle card photo falls back to WO's first uploaded photo when
  Vehicle model has no MediaLibrary integration of its own.

Test CalendarEnhancementsTest updated to assert the new inline
response headers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-08-05 20:56:24 +00:00

96 lines
4.1 KiB
PHP

<?php
namespace App\Filament\Tenant\Resources\WorkOrderResource\Pages;
use App\Filament\Tenant\Resources\WorkOrderResource;
use App\Models\Tenant\WorkOrder;
use Filament\Actions;
use Filament\Resources\Pages\EditRecord;
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 [
Actions\Action::make('dashboard')
->label(__('Vizualizare dashboard'))
->icon('heroicon-m-squares-2x2')
->color('info')
->url(fn () => \App\Filament\Tenant\Pages\WorkOrderDashboard::getUrl(
parameters: ['wo' => $this->record->id],
panel: 'tenant',
)),
Actions\Action::make('apply_template')
->label(__('Aplică șablon'))
->icon('heroicon-m-clipboard-document-list')
->color('gray')
->schema([
\Filament\Forms\Components\Select::make('template_id')
->label(__('Șablon serviciu'))
->options(fn () => \App\Models\Tenant\ServiceTemplate::where('is_active', true)->pluck('name', 'id'))
->searchable()
->required(),
])
->action(function (array $data) {
$template = \App\Models\Tenant\ServiceTemplate::with('items')->find($data['template_id']);
if (! $template) return;
$r = app(\App\Services\ServiceComposer::class)->applyTemplate($this->record, $template);
$this->fillForm();
\Filament\Notifications\Notification::make()
->title(__('Șablon aplicat') . ": {$r['labor']} " . __('manopere') . ", {$r['parts']} " . __('piese'))
->success()->send();
}),
Actions\Action::make('ai_diagnose')
->label(__('AI: sugerează diagnostic'))
->icon('heroicon-m-sparkles')
->color('primary')
->visible(fn () => ! empty($this->record->complaint))
->modalHeading(__('Diagnostic AI bazat pe plângerea clientului'))
->modalSubmitAction(false)
->modalCancelActionLabel(__('Închide'))
->modalContent(function () {
[$reply, $meta] = app(\App\Services\Ai\AiAssistantService::class)
->suggestDiagnosis($this->record);
return view('filament.tenant.ai-reply', ['reply' => $reply, 'meta' => $meta]);
}),
Actions\Action::make('tracking')
->label(__('Link client (QR)'))
->icon('heroicon-m-qr-code')
->color('primary')
->modalHeading(fn () => __('Tracking client') . ' — WO #' . $this->record->number)
->modalSubmitAction(false)
->modalCancelActionLabel(__('Închide'))
->modalWidth('lg')
->modalContent(fn () => view('filament.tenant.tracking-qr', [
'wo' => $this->record,
])),
Actions\Action::make('pdf')
->label(__('Vizualizare PDF'))
->icon('heroicon-m-document-magnifying-glass')
->color('gray')
->url(fn () => url('/app/work-orders/' . $this->record->id . '/pdf'))
->openUrlInNewTab(),
Actions\DeleteAction::make(),
];
}
}