fix: Use View::file() to render sticker template directly, add missing test route, and allow GET for regenerate
- Changed from View::make() to View::file() with full path resolution
- Added file existence check with detailed error logging
- Allow GET/POST for regenerate sticker endpoint for easier testing
- Add design name and customer surname to A6 PDF stickers
- Add regenerate sticker endpoint POST /test/sticker/{orderNumber}/regenerate
- Add test sticker preview page at /test/sticker/{orderNumber}
This commit is contained in:
@@ -8,6 +8,7 @@ use chillerlan\QRCode\QRCode;
|
|||||||
use chillerlan\QRCode\QROptions;
|
use chillerlan\QRCode\QROptions;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Illuminate\Support\Facades\View;
|
||||||
|
|
||||||
class QrStickerService
|
class QrStickerService
|
||||||
{
|
{
|
||||||
@@ -99,17 +100,50 @@ class QrStickerService
|
|||||||
? 'STOCK ORDER'
|
? 'STOCK ORDER'
|
||||||
: 'CUSTOM ORDER';
|
: 'CUSTOM ORDER';
|
||||||
|
|
||||||
|
// Extract design name from first order item
|
||||||
|
$designName = '';
|
||||||
|
if ($order->items && $order->items->count() > 0) {
|
||||||
|
$firstItem = $order->items->first();
|
||||||
|
$designName = $firstItem->product?->name ?? $firstItem->name ?? 'Custom Design';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract customer surname (last word of name)
|
||||||
|
$customerName = $order->user?->name ?? '';
|
||||||
|
$nameParts = explode(' ', trim($customerName));
|
||||||
|
$customerSurname = end($nameParts);
|
||||||
|
|
||||||
// Prepare data for the view
|
// Prepare data for the view
|
||||||
$data = [
|
$data = [
|
||||||
'order' => $order,
|
'order' => $order,
|
||||||
'qrSvg' => $qrSvg,
|
'qrSvg' => $qrSvg,
|
||||||
'orderType' => $orderType,
|
'orderType' => $orderType,
|
||||||
|
'designName' => $designName,
|
||||||
|
'customerSurname' => $customerSurname,
|
||||||
'qrUrl' => $qrUrl,
|
'qrUrl' => $qrUrl,
|
||||||
'generatedAt' => now()->format('Y-m-d H:i'),
|
'generatedAt' => now()->format('Y-m-d H:i'),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Generate PDF using the sticker template
|
// Render the view to HTML first
|
||||||
$pdf = Pdf::loadView('stickers.qr-sticker', $data);
|
try {
|
||||||
|
$viewPath = resource_path('views/stickers/qr-sticker.blade.php');
|
||||||
|
if (!file_exists($viewPath)) {
|
||||||
|
throw new \Exception("View file not found at: {$viewPath}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile and render the view
|
||||||
|
$html = View::file($viewPath, $data)->render();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('Failed to render sticker view', [
|
||||||
|
'order_uuid' => $order->uuid,
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
'view_path' => $viewPath ?? 'unknown',
|
||||||
|
]);
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate PDF from HTML using DomPDF
|
||||||
|
try {
|
||||||
|
$pdf = Pdf::loadHTML($html);
|
||||||
|
|
||||||
// Configure for A6 landscape
|
// Configure for A6 landscape
|
||||||
// A6 is 105mm × 148mm (landscape: 148mm × 105mm)
|
// A6 is 105mm × 148mm (landscape: 148mm × 105mm)
|
||||||
@@ -122,5 +156,12 @@ class QrStickerService
|
|||||||
Storage::disk('public')->put($path, $pdfContent);
|
Storage::disk('public')->put($path, $pdfContent);
|
||||||
|
|
||||||
return $path;
|
return $path;
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('DomPDF generation failed', [
|
||||||
|
'order_uuid' => $order->uuid,
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
]);
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -170,11 +170,16 @@
|
|||||||
<!-- Customer Info -->
|
<!-- Customer Info -->
|
||||||
<div class="customer-info">
|
<div class="customer-info">
|
||||||
<div class="label">Customer</div>
|
<div class="label">Customer</div>
|
||||||
<div class="name">{{ $order->user->name ?? 'N/A' }}</div>
|
<div class="name">{{ $customerSurname }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Order Details -->
|
<!-- Order Details -->
|
||||||
<div class="details">
|
<div class="details">
|
||||||
|
<div class="detail-row">
|
||||||
|
<span class="detail-label">Design:</span>
|
||||||
|
<span class="detail-value" style="font-size: 6.5pt;">{{ substr($designName, 0, 12) }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="detail-row">
|
<div class="detail-row">
|
||||||
<span class="detail-label">Date:</span>
|
<span class="detail-label">Date:</span>
|
||||||
<span class="detail-value">{{ $order->created_at->format('M d') }}</span>
|
<span class="detail-value">{{ $order->created_at->format('M d') }}</span>
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container mx-auto px-4 py-8">
|
||||||
|
<h1 class="text-3xl font-bold mb-6">QR Sticker Preview</h1>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||||
|
<!-- Order Info -->
|
||||||
|
<div class="md:col-span-1 bg-white rounded-lg shadow-md p-6">
|
||||||
|
<h2 class="text-xl font-semibold mb-4">Order Details</h2>
|
||||||
|
|
||||||
|
<div class="space-y-3 text-sm">
|
||||||
|
<div>
|
||||||
|
<p class="text-gray-600">Order Number</p>
|
||||||
|
<p class="font-semibold">{{ $order->order_number }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<p class="text-gray-600">UUID</p>
|
||||||
|
<p class="font-mono text-xs">{{ $order->uuid }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<p class="text-gray-600">Status</p>
|
||||||
|
<p class="font-semibold capitalize">{{ str_replace('_', ' ', $order->status) }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<p class="text-gray-600">Customer</p>
|
||||||
|
<p class="font-semibold">{{ $order->user?->name ?? 'N/A' }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<p class="text-gray-600">Created</p>
|
||||||
|
<p class="font-semibold">{{ $order->created_at->format('M d, Y H:i') }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if($order->items->count() > 0)
|
||||||
|
<div>
|
||||||
|
<p class="text-gray-600">Design</p>
|
||||||
|
<p class="font-semibold text-sm">{{ $order->items->first()?->product?->name ?? 'Custom' }}</p>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<div class="pt-4 border-t">
|
||||||
|
<p class="text-gray-600 text-xs">Sticker Path</p>
|
||||||
|
<p class="font-mono text-xs break-all">{{ $stickerPath }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Download Link -->
|
||||||
|
<a href="{{ route('ops.order.sticker.download', $order) }}" class="mt-6 inline-block w-full text-center bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700">
|
||||||
|
📥 Download PDF
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- PDF Preview -->
|
||||||
|
<div class="md:col-span-2 bg-white rounded-lg shadow-md p-6">
|
||||||
|
<h2 class="text-xl font-semibold mb-4">PDF Preview (A6 Sticker)</h2>
|
||||||
|
|
||||||
|
<div class="bg-gray-100 rounded border-2 border-gray-300 p-4" style="min-height: 400px;">
|
||||||
|
<iframe
|
||||||
|
src="{{ $pdfUrl }}"
|
||||||
|
class="w-full h-full border-0"
|
||||||
|
style="min-height: 500px;"
|
||||||
|
title="Sticker PDF">
|
||||||
|
</iframe>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="text-xs text-gray-500 mt-4">
|
||||||
|
If the PDF doesn't display above, it may be loading. Try refreshing or downloading the PDF directly.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Back Link -->
|
||||||
|
<div class="mt-8">
|
||||||
|
<a href="/" class="text-blue-600 hover:text-blue-800">← Back to Home</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
@@ -84,6 +84,68 @@ Route::middleware('auth')->group(function () {
|
|||||||
// QR landing page (public but token-gated)
|
// QR landing page (public but token-gated)
|
||||||
Route::get('/ops/orders/{token}', [OpsController::class, 'showOrder'])->name('ops.order.show');
|
Route::get('/ops/orders/{token}', [OpsController::class, 'showOrder'])->name('ops.order.show');
|
||||||
|
|
||||||
|
// Test routes (remove in production)
|
||||||
|
Route::get('/test/sticker/{orderNumber}', function ($orderNumber) {
|
||||||
|
$order = \App\Models\Order::where('order_number', $orderNumber)->first();
|
||||||
|
|
||||||
|
if (!$order) {
|
||||||
|
return response()->json(['error' => 'Order not found'], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$stickerPath = "qr-stickers/{$order->uuid}.pdf";
|
||||||
|
|
||||||
|
if (!\Illuminate\Support\Facades\Storage::disk('public')->exists($stickerPath)) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'Sticker PDF not generated yet',
|
||||||
|
'order_uuid' => $order->uuid,
|
||||||
|
'regenerate_url' => route('test.sticker.regenerate', ['orderNumber' => $orderNumber])
|
||||||
|
], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$pdfUrl = \Illuminate\Support\Facades\Storage::disk('public')->url($stickerPath);
|
||||||
|
|
||||||
|
return view('test.sticker-display', [
|
||||||
|
'order' => $order,
|
||||||
|
'pdfUrl' => $pdfUrl,
|
||||||
|
'stickerPath' => $stickerPath,
|
||||||
|
]);
|
||||||
|
})->name('test.sticker');
|
||||||
|
|
||||||
|
// Regenerate sticker PDF for testing
|
||||||
|
Route::match(['get', 'post'], '/test/sticker/{orderNumber}/regenerate', function ($orderNumber) {
|
||||||
|
$order = \App\Models\Order::where('order_number', $orderNumber)->first();
|
||||||
|
|
||||||
|
if (!$order) {
|
||||||
|
return response()->json(['error' => 'Order not found'], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Ensure order has QR token
|
||||||
|
if (!$order->qr_token) {
|
||||||
|
$order->qr_token = \Illuminate\Support\Str::random(32);
|
||||||
|
$order->qr_generated_at = now();
|
||||||
|
$order->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate sticker
|
||||||
|
$service = new \App\Services\QrStickerService();
|
||||||
|
$paths = $service->generateSticker($order);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'message' => 'Sticker PDF generated successfully',
|
||||||
|
'svg_path' => $paths['svg_path'],
|
||||||
|
'pdf_path' => $paths['pdf_path'],
|
||||||
|
'view_url' => route('test.sticker', ['orderNumber' => $orderNumber])
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => 'Failed to generate sticker',
|
||||||
|
'message' => $e->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
})->name('test.sticker.regenerate');
|
||||||
|
|
||||||
// use Illuminate\Support\Facades\Route;
|
// use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
Route::get('/font-test', function () {
|
Route::get('/font-test', function () {
|
||||||
|
|||||||
Reference in New Issue
Block a user