@php // $preview = true renders the same template for the on-screen preview // (served as HTML rather than dompdf). The only differences: the logo is // loaded by URL instead of base64 (dompdf needs the bytes inlined; a browser // does not), so the shared markup/CSS below stays the single source of truth. $preview = $preview ?? false; $primary = $setting?->primary_color ?: '#3B82F6'; $headerColor = $setting?->table_header_color ?: $primary; $symbol = $currencySymbol ?: ''; $code = $quote->currency_code ?: ''; $money = function ($value) use ($symbol, $code) { $formatted = number_format((float) $value, 2); return ($symbol !== '' ? $symbol . ' ' : ($code !== '' ? $code . ' ' : '')) . $formatted; }; // Status badge colour, matching the v1 palette. $statusColors = [ 'DRAFT' => '#6b7280', 'SENT' => '#3b82f6', 'ACCEPTED' => '#10b981', 'REJECTED' => '#ef4444', 'EXPIRED' => '#f59e0b', ]; $statusColor = $statusColors[$quote->status] ?? '#6b7280'; $logoData = null; if ($setting?->logo_path) { try { if ($preview) { $logoData = \Illuminate\Support\Facades\Storage::disk('public')->url($setting->logo_path); } else { $logoFull = \Illuminate\Support\Facades\Storage::disk('public')->path($setting->logo_path); if (is_file($logoFull)) { $logoData = 'data:' . (mime_content_type($logoFull) ?: 'image/png') . ';base64,' . base64_encode(file_get_contents($logoFull)); } } } catch (\Throwable $e) { $logoData = null; } } // Banking resolved for THIS quote's currency, see the note on the invoice // template: the same block has to hold across every render path. // // A quote follows the invoice rule, because customers treat a quote as a // pro-forma and pay straight off it. If the account number is on a quote // priced for cash, the transfer that follows costs us the fee we never // charged — so the details appear only once the quote itself names the bank // as the payment method, and its total carries the charge. $banking = \App\Support\DocumentBanking::for( $quote->team_id, $quote->currency_code, $setting, $quote->paymentMethod ); $hasBankingPage = $banking['showsBanking']; @endphp
|
@if ($logoData)
@endif {{ $setting?->company_name ?: $quote->team?->name }}@if ($setting?->address){{ __('Address') }}: {!! nl2br(e($setting->address)) !!} @endif @if ($setting?->email){{ __('Email') }}: {{ $setting->email }} @endif @if ($setting?->website){{ __('Web') }}: {{ $setting->website }} @endif @if ($setting?->phone){{ __('Phone') }}: {{ $setting->phone }} @endif @if ($setting?->tin_number){{ __('TIN') }}: {{ $setting->tin_number }} @endif |
|
{{ $quote->customer?->name ?: '—' }}
@if ($quote->customer?->address){{ __('Address') }}: {!! nl2br(e($quote->customer->address)) !!}
@endif @if ($quote->customer?->email){{ __('Email') }}: {{ $quote->customer->email }}
@endif @if ($quote->customer?->phone){{ __('Phone') }}: {{ $quote->customer->phone }}
@endif @if ($quote->customer?->tin_number){{ __('TIN') }}: {{ $quote->customer->tin_number }}
@endif| # | {{ __('Item Description') }} | {{ __('Qty') }} | {{ __('Rate') }} | {{ __('Discount') }} | {{ __('Total') }} |
|---|---|---|---|---|---|
| {{ $i + 1 }} |
{{ $line->name }}
@if ($line->description){!! nl2br(e($line->description)) !!} @endif
|
{{ number_format((float) $line->qty, 2) }} | {{ $money($line->unit_price) }} | {{ $money($line->discount) }} | {{ $money($line->line_total) }} |
| {{ __('No items.') }} | |||||
|
{{ $quote->notes }}