fix(calendar): PDF programări via HTTP route, not Livewire wire:click
wire:click="exportPdf" attempted to return a binary Response through Livewire's JSON channel — it re-encoded the PDF bytes as JSON and triggered "Malformed UTF-8 characters, possibly incorrectly encoded". Added GET /app/appointments/pdf?from=...&to=... that streams the PDF with Content-Disposition: inline (or attachment when ?download=1) and switched the calendar button to a plain <a target="_blank"> pointing at that URL. The button now includes the currently visible period via query params. The old exportPdf() method is retained (still returns a plain PDF Response) because CalendarEnhancementsTest asserts against it — it's just no longer wired to the UI. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -419,7 +419,13 @@ class CalendarBoard extends Page
|
||||
Notification::make()->title(__('Post actualizat'))->success()->send();
|
||||
}
|
||||
|
||||
/** Generate PDF for all appointments in the visible period. */
|
||||
/**
|
||||
* PDF for the visible period is now served by the plain HTTP route
|
||||
* /app/appointments/pdf?from=...&to=... — the button in the Blade
|
||||
* view links to it directly, so Livewire never has to serialize a
|
||||
* binary response (which caused "Malformed UTF-8" JSON errors).
|
||||
* This method stays for the CalendarEnhancementsTest.
|
||||
*/
|
||||
public function exportPdf()
|
||||
{
|
||||
$days = $this->getDays();
|
||||
|
||||
@@ -159,7 +159,13 @@
|
||||
<h1>{{ __('Calendar vizual') }}</h1>
|
||||
</div>
|
||||
<div class="cv-btn-group">
|
||||
<button class="cv-btn" wire:click="exportPdf">{{ __('🖨 PDF programări') }}</button>
|
||||
@php
|
||||
$_days = $this->getDays();
|
||||
$_from = $_days[0]['date'] ?? today()->toDateString();
|
||||
$_to = end($_days)['date'] ?? today()->toDateString();
|
||||
$_pdfUrl = url('/app/appointments/pdf?from=' . $_from . '&to=' . $_to);
|
||||
@endphp
|
||||
<a class="cv-btn" href="{{ $_pdfUrl }}" target="_blank">{{ __('🖨 PDF programări') }}</a>
|
||||
<button class="cv-btn" wire:click="openNewPostForm">{{ __('+ Pod nou') }}</button>
|
||||
<button class="cv-btn cv-btn-primary" wire:click="openNewForm">{{ __('+ Programare nouă') }}</button>
|
||||
</div>
|
||||
|
||||
@@ -47,6 +47,31 @@ Route::post('/payments/paypal/webhook', [\App\Http\Controllers\PaymentController
|
||||
Route::post('/payments/paynet/webhook', [\App\Http\Controllers\PaymentController::class, 'paynetWebhook'])
|
||||
->withoutMiddleware([\Illuminate\Foundation\Http\Middleware\VerifyCsrfToken::class]);
|
||||
|
||||
// PDF for appointments (used by CalendarBoard "PDF programări" button).
|
||||
// Inline preview by default; ?download=1 forces attachment.
|
||||
Route::get('/app/appointments/pdf', function (Request $request) {
|
||||
abort_unless(auth('web')->check(), 403);
|
||||
$firstDate = $request->query('from') ?: today()->toDateString();
|
||||
$lastDate = $request->query('to') ?: today()->toDateString();
|
||||
$appointments = \App\Models\Tenant\Appointment::with(['client:id,name', 'vehicle:id,plate,make,model', 'master:id,name', 'post:id,name'])
|
||||
->whereBetween('date', [$firstDate, $lastDate])
|
||||
->orderBy('date')
|
||||
->orderBy('time_start')
|
||||
->get();
|
||||
$pdf = \Barryvdh\DomPDF\Facade\Pdf::loadView('pdf.appointments', [
|
||||
'appointments' => $appointments->groupBy(fn ($a) => $a->date->toDateString()),
|
||||
'periodLabel' => \Carbon\Carbon::parse($firstDate)->format('d.m.Y') . ' — ' . \Carbon\Carbon::parse($lastDate)->format('d.m.Y'),
|
||||
'generatedAt' => now()->format('d.m.Y H:i'),
|
||||
])->setPaper('a4', 'portrait');
|
||||
$filename = 'programari_' . $firstDate . '_' . $lastDate . '.pdf';
|
||||
$disposition = $request->boolean('download') ? 'attachment' : 'inline';
|
||||
return response($pdf->output(), 200, [
|
||||
'Content-Type' => 'application/pdf',
|
||||
'Content-Disposition' => $disposition . '; filename="' . $filename . '"',
|
||||
'Cache-Control' => 'private, no-store',
|
||||
]);
|
||||
})->name('appointments.pdf');
|
||||
|
||||
// PDF for a work order. Inline preview by default (opens in browser tab
|
||||
// so user can print/save); forced download with ?download=1.
|
||||
Route::get('/app/work-orders/{workOrder}/pdf', function (Request $request, int $workOrder) {
|
||||
|
||||
Reference in New Issue
Block a user