Refactor AWB, Import Invoice, and Invoice Blade templates to improve rendering compatibility with Dompdf. Key changes: - Replace flexbox and box-sizing with table-based layouts to ensure consistent rendering in Dompdf. - Implement `@page` margins instead of container padding to prevent content overflow and clipping. - Update color palette to a modern navy and gray scheme. - Adjust font sizes and typography for better readability and professional appearance. - Fix width issues by using 100% width containers instead of fixed millimeter widths.
473 lines
19 KiB
PHP
473 lines
19 KiB
PHP
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<style>
|
||
/* ════════ Base Reset & Page ════════ */
|
||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
body {
|
||
font-family: DejaVu Sans, Arial, sans-serif;
|
||
font-size: 9px;
|
||
color: #111827;
|
||
line-height: 1.4;
|
||
}
|
||
/* ⚠️ Dompdf از box-sizing: border-box پشتیبانی نمیکند —
|
||
width باید 100% ناحیه قابل چاپ باشد و حاشیهها با @page داده شوند؛
|
||
width: 210mm + padding یعنی 230mm واقعی و بیرونزدگی از سمت راست. */
|
||
@page { margin: 8mm 10mm; }
|
||
.page {
|
||
width: 100%;
|
||
}
|
||
|
||
/* ════════ Brand Colors ════════ */
|
||
/* Navy: #1a1a2e | Orange accent: #f59e0b | Gray bg: #f3f4f6 */
|
||
|
||
/* ════════ Header ════════ */
|
||
.header-table {
|
||
width: 100%;
|
||
table-layout: fixed; /* ✅ ستونها به عرض مشخص محدود میشوند */
|
||
border-collapse: collapse;
|
||
border-bottom: 3px solid #1a1a2e;
|
||
margin-bottom: 6px;
|
||
}
|
||
.header-table td {
|
||
vertical-align: middle;
|
||
padding: 4px 6px 8px 6px;
|
||
word-wrap: break-word; /* ✅ متن طولانی میشکند */
|
||
}
|
||
.header-logo {
|
||
width: 90px; /* ✅ کوچکتر شد */
|
||
height: auto;
|
||
}
|
||
.header-brand {
|
||
font-size: 20px;
|
||
font-weight: bold;
|
||
color: #1a1a2e;
|
||
letter-spacing: 1px;
|
||
}
|
||
.header-tagline {
|
||
font-size: 8px;
|
||
color: #6b7280;
|
||
margin-top: 1px;
|
||
}
|
||
.header-title {
|
||
font-size: 14px;
|
||
font-weight: bold;
|
||
color: #1a1a2e;
|
||
text-align: center;
|
||
letter-spacing: 1px;
|
||
}
|
||
.header-awb {
|
||
font-size: 11px; /* ✅ کوچکتر */
|
||
font-weight: bold;
|
||
color: #1a1a2e;
|
||
text-align: right;
|
||
letter-spacing: 1px; /* ✅ کمتر */
|
||
}
|
||
.header-date {
|
||
font-size: 8px;
|
||
color: #6b7280;
|
||
text-align: right;
|
||
}
|
||
.header-barcode {
|
||
text-align: right;
|
||
}
|
||
.header-barcode img {
|
||
max-width: 50mm; /* ✅ حداکثر عرض برای جا ماندن در ستون */
|
||
height: 32px; /* ✅ کمی کوچکتر */
|
||
width: auto;
|
||
}
|
||
|
||
/* ════════ Route Bar ════════ */
|
||
.route-bar {
|
||
width: 100%;
|
||
background: #f3f4f6;
|
||
border: 1px solid #d1d5db;
|
||
padding: 4px 8px;
|
||
margin-bottom: 6px;
|
||
font-size: 10px;
|
||
font-weight: bold;
|
||
color: #1a1a2e;
|
||
}
|
||
.route-bar .route-arrow {
|
||
color: #f59e0b;
|
||
font-weight: bold;
|
||
font-size: 12px;
|
||
}
|
||
.route-bar .route-meta {
|
||
float: left;
|
||
font-size: 9px;
|
||
color: #4b5563;
|
||
font-weight: normal;
|
||
}
|
||
|
||
/* ════════ Main Grid (2×2) ════════ */
|
||
.grid-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
margin-bottom: 6px;
|
||
}
|
||
.grid-table > tbody > tr > td {
|
||
width: 50%;
|
||
vertical-align: top;
|
||
border: 1.5px solid #1a1a2e;
|
||
padding: 0;
|
||
}
|
||
.grid-table > tbody > tr > td.left {
|
||
border-right: 0.5px solid #1a1a2e;
|
||
}
|
||
|
||
/* ════════ Section Header (navy bar) ════════ */
|
||
.section-header {
|
||
background: #1a1a2e;
|
||
color: #ffffff;
|
||
padding: 4px 8px;
|
||
font-weight: bold;
|
||
font-size: 11px;
|
||
letter-spacing: 1.5px;
|
||
border-bottom: 1px solid #1a1a2e;
|
||
}
|
||
|
||
/* ════════ Section Body (label-value rows) ════════ */
|
||
.field-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
font-size: 9px;
|
||
}
|
||
.field-table td {
|
||
padding: 2px 8px;
|
||
vertical-align: top;
|
||
border-bottom: 0.5px solid #e5e7eb;
|
||
}
|
||
.field-table td.label {
|
||
width: 40%;
|
||
color: #6b7280;
|
||
font-weight: bold;
|
||
}
|
||
.field-table td.value {
|
||
color: #111827;
|
||
font-weight: normal;
|
||
}
|
||
.field-table tr:last-child td {
|
||
border-bottom: none;
|
||
}
|
||
|
||
/* ════════ Payment Total Row ════════ */
|
||
.total-row td {
|
||
background: #f59e0b !important;
|
||
color: #ffffff !important;
|
||
font-weight: bold !important;
|
||
font-size: 11px !important;
|
||
padding: 4px 8px !important;
|
||
}
|
||
|
||
/* ════════ Shipment Details Table ════════ */
|
||
.details-section {
|
||
border: 1.5px solid #1a1a2e;
|
||
margin-bottom: 6px;
|
||
}
|
||
.details-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
font-size: 8px;
|
||
}
|
||
.details-table th {
|
||
background: #1a1a2e;
|
||
color: #ffffff;
|
||
padding: 3px 4px;
|
||
text-align: left;
|
||
font-weight: bold;
|
||
border: 0.5px solid #1a1a2e;
|
||
}
|
||
.details-table td {
|
||
padding: 2px 4px;
|
||
border: 0.5px solid #d1d5db;
|
||
color: #111827;
|
||
}
|
||
.details-table tr:nth-child(even) td {
|
||
background: #f9fafb;
|
||
}
|
||
.details-total td {
|
||
background: #f3f4f6 !important;
|
||
font-weight: bold;
|
||
color: #1a1a2e;
|
||
}
|
||
|
||
/* ════════ Notes ════════ */
|
||
.notes {
|
||
border: 1px solid #d1d5db;
|
||
padding: 5px 8px;
|
||
margin-bottom: 6px;
|
||
font-size: 7.5px;
|
||
line-height: 1.5;
|
||
color: #4b5563;
|
||
background: #ffffff;
|
||
}
|
||
.notes-title {
|
||
font-weight: bold;
|
||
color: #1a1a2e;
|
||
font-size: 8px;
|
||
margin-bottom: 2px;
|
||
}
|
||
|
||
/* ════════ Signature ════════ */
|
||
.signature-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
margin-bottom: 6px;
|
||
}
|
||
.signature-table td {
|
||
width: 50%;
|
||
padding: 8px;
|
||
text-align: center;
|
||
font-size: 8px;
|
||
color: #6b7280;
|
||
}
|
||
.sig-line {
|
||
border-top: 1px solid #1a1a2e;
|
||
margin-top: 28px;
|
||
padding-top: 3px;
|
||
font-size: 8px;
|
||
color: #6b7280;
|
||
}
|
||
|
||
/* ════════ Footer ════════ */
|
||
.footer {
|
||
border-top: 2px solid #1a1a2e;
|
||
padding-top: 4px;
|
||
text-align: center;
|
||
font-size: 8px;
|
||
color: #6b7280;
|
||
}
|
||
.footer-brand {
|
||
color: #1a1a2e;
|
||
font-weight: bold;
|
||
font-size: 10px;
|
||
margin-bottom: 1px;
|
||
}
|
||
.footer-track {
|
||
font-size: 9px;
|
||
color: #f59e0b;
|
||
font-weight: bold;
|
||
margin: 1px 0;
|
||
}
|
||
.footer-meta {
|
||
font-size: 7px;
|
||
color: #9ca3af;
|
||
margin-top: 2px;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="page">
|
||
|
||
<!-- ════════ HEADER ════════ -->
|
||
<table class="header-table">
|
||
<tr>
|
||
<td style="width: 25%;">
|
||
<img src="{{ public_path('images/ifnex-logo.png') }}" class="header-logo" alt="IFNEX">
|
||
</td>
|
||
<td style="width: 38%;" align="center">
|
||
<div class="header-brand">IFNEX</div>
|
||
<div class="header-tagline">We Deliver Value</div>
|
||
<div class="header-title" style="margin-top:4px;">SHIPMENT WAYBILL</div>
|
||
</td>
|
||
<td style="width: 37%;" class="header-barcode">
|
||
@if($barcode_base64)
|
||
<img src="{{ $barcode_base64 }}" alt="barcode"><br>
|
||
@endif
|
||
<div class="header-awb">{{ $shipment->awb_no }}</div>
|
||
<div class="header-date">Date: {{ $shipment->created_at?->format('m/d/Y') }}</div>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
|
||
<!-- ════════ ROUTE BAR ════════ -->
|
||
<div class="route-bar">
|
||
<span class="route-meta">
|
||
Service: {{ $service_label }} | Type: {{ $type_label }}
|
||
</span>
|
||
From: {{ strtoupper($shipment->fromCountry?->name ?? '—') }} ({{ $shipment->fromCountry?->iso_code }})
|
||
<span class="route-arrow"> → </span>
|
||
To: {{ strtoupper($shipment->toCountry?->name ?? '—') }} ({{ $shipment->toCountry?->iso_code }})
|
||
</div>
|
||
|
||
<!-- ════════ GRID 2×2: Shipper / Receiver ════════ -->
|
||
<table class="grid-table">
|
||
<tr>
|
||
<!-- SHIPPER -->
|
||
<td class="left">
|
||
<div class="section-header">SHIPPER</div>
|
||
<table class="field-table">
|
||
@if($shipper['company'])
|
||
<tr><td class="label">Company</td><td class="value">{{ $shipper['company'] }}</td></tr>
|
||
@endif
|
||
<tr><td class="label">Contact Name</td><td class="value">{{ $shipper['name'] ?: '—' }}</td></tr>
|
||
<tr><td class="label">Phone</td><td class="value">{{ $shipper['phone'] ?: '—' }}</td></tr>
|
||
@if($shipper['email'])
|
||
<tr><td class="label">Email</td><td class="value">{{ $shipper['email'] }}</td></tr>
|
||
@endif
|
||
<tr><td class="label">Address</td><td class="value">{{ $shipper['address'] ?: '—' }}</td></tr>
|
||
@if($shipper['city'])
|
||
<tr><td class="label">City</td><td class="value">{{ $shipper['city'] }}</td></tr>
|
||
@endif
|
||
@if($shipper['zip'])
|
||
<tr><td class="label">Zip Code</td><td class="value">{{ $shipper['zip'] }}</td></tr>
|
||
@endif
|
||
@if($shipper['id_number'])
|
||
<tr><td class="label">ID Number</td><td class="value">{{ $shipper['id_number'] }}</td></tr>
|
||
@endif
|
||
</table>
|
||
</td>
|
||
<!-- RECEIVER -->
|
||
<td>
|
||
<div class="section-header">RECEIVER</div>
|
||
<table class="field-table">
|
||
@if($receiver['company'])
|
||
<tr><td class="label">Company</td><td class="value">{{ $receiver['company'] }}</td></tr>
|
||
@endif
|
||
<tr><td class="label">Contact Name</td><td class="value">{{ $receiver['name'] ?: '—' }}</td></tr>
|
||
<tr><td class="label">Phone</td><td class="value">{{ $receiver['phone'] ?: '—' }}</td></tr>
|
||
@if($receiver['email'])
|
||
<tr><td class="label">Email</td><td class="value">{{ $receiver['email'] }}</td></tr>
|
||
@endif
|
||
<tr><td class="label">Address</td><td class="value">{{ $receiver['address'] ?: '—' }}</td></tr>
|
||
@if($receiver['city'])
|
||
<tr><td class="label">City</td><td class="value">{{ $receiver['city'] }}</td></tr>
|
||
@endif
|
||
@if($receiver['zip'])
|
||
<tr><td class="label">Zip Code</td><td class="value">{{ $receiver['zip'] }}</td></tr>
|
||
@endif
|
||
@if($receiver['id_number'])
|
||
<tr><td class="label">ID Number</td><td class="value">{{ $receiver['id_number'] }}</td></tr>
|
||
@endif
|
||
</table>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
|
||
<!-- ════════ GRID 2×2: Shipment / Payment ════════ -->
|
||
<table class="grid-table">
|
||
<tr>
|
||
<!-- SHIPMENT -->
|
||
<td class="left">
|
||
<div class="section-header">SHIPMENT</div>
|
||
<table class="field-table">
|
||
<tr><td class="label">Gross Weight</td><td class="value">{{ $shipment->weight ?: '—' }} Kg</td></tr>
|
||
@if($shipment->dimensions)
|
||
<tr><td class="label">Dimensions</td><td class="value">{{ $shipment->dimensions }} cm</td></tr>
|
||
@endif
|
||
@if($shipment->volumetric_weight)
|
||
<tr><td class="label">Volumetric Weight</td><td class="value">{{ $shipment->volumetric_weight }} Kg</td></tr>
|
||
@endif
|
||
<tr><td class="label">Chargeable Weight</td><td class="value">{{ $shipment->chargeable_weight ?: max($shipment->weight ?? 0, $shipment->volumetric_weight ?? 0) }} Kg</td></tr>
|
||
@if($invoice_total_usd > 0)
|
||
<tr><td class="label">Declared Value</td><td class="value">{{ number_format($invoice_total_usd, 0) }} USD</td></tr>
|
||
@endif
|
||
@php
|
||
$contentDesc = $items->isNotEmpty()
|
||
? $items->pluck('description')->implode(', ')
|
||
: ($shipment->content_description ?: $shipment->reason_for_export ?: 'General Goods');
|
||
@endphp
|
||
<tr><td class="label">Content</td><td class="value">{{ $contentDesc }}</td></tr>
|
||
</table>
|
||
</td>
|
||
<!-- PAYMENT -->
|
||
<td>
|
||
<div class="section-header">PAYMENT</div>
|
||
<table class="field-table">
|
||
<tr><td class="label">Shipping Price</td><td class="value">{{ $shipment->shipping_price ? number_format($shipment->shipping_price, 0) : '—' }}</td></tr>
|
||
@if(($shipment->extra_service ?? 0) > 0)
|
||
<tr><td class="label">Extra Service</td><td class="value">{{ number_format($shipment->extra_service) }}</td></tr>
|
||
@endif
|
||
@if(($shipment->domestic_pickup ?? 0) > 0)
|
||
<tr><td class="label">Domestic Pickup</td><td class="value">{{ number_format($shipment->domestic_pickup) }}</td></tr>
|
||
@endif
|
||
@if(($shipment->packing_cost ?? 0) > 0)
|
||
<tr><td class="label">Packing Cost</td><td class="value">{{ number_format($shipment->packing_cost) }}</td></tr>
|
||
@endif
|
||
@if(($shipment->domestic_delivery ?? 0) > 0)
|
||
<tr><td class="label">Domestic Delivery</td><td class="value">{{ number_format($shipment->domestic_delivery) }}</td></tr>
|
||
@endif
|
||
@if(($shipment->warehousing_cost ?? 0) > 0)
|
||
<tr><td class="label">Warehousing</td><td class="value">{{ number_format($shipment->warehousing_cost) }}</td></tr>
|
||
@endif
|
||
@if(($shipment->discount ?? 0) > 0)
|
||
<tr><td class="label">Discount</td><td class="value" style="color:#dc2626;">-{{ number_format($shipment->discount) }}</td></tr>
|
||
@endif
|
||
<tr class="total-row"><td class="label">TOTAL FEE</td><td class="value">{{ number_format($shipment->total_fee ?? 0) }} IRR</td></tr>
|
||
@if($shipment->cod_amount)
|
||
<tr><td class="label">Cash on Delivery</td><td class="value">{{ number_format($shipment->cod_amount, 0) }} AED</td></tr>
|
||
@endif
|
||
</table>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
|
||
<!-- ════════ SHIPMENT DETAILS (Items table — only if items exist) ════════ -->
|
||
@if($items->isNotEmpty())
|
||
<div class="details-section">
|
||
<div class="section-header">SHIPMENT DETAILS</div>
|
||
<table class="details-table">
|
||
<thead>
|
||
<tr>
|
||
<th style="width: 5%;">No</th>
|
||
<th style="width: 40%;">Description</th>
|
||
<th style="width: 15%;">H.S. Code</th>
|
||
<th style="width: 10%;">Qty</th>
|
||
<th style="width: 15%;">Unit Price (USD)</th>
|
||
<th style="width: 15%;">Total (USD)</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
@foreach($items as $item)
|
||
<tr>
|
||
<td>{{ $item->row_number }}</td>
|
||
<td>{{ $item->description }}</td>
|
||
<td>{{ $item->hs_code ?: '—' }}</td>
|
||
<td>{{ $item->quantity }}</td>
|
||
<td>{{ number_format($item->unit_price, 2) }}</td>
|
||
<td>{{ number_format($item->total_usd, 2) }}</td>
|
||
</tr>
|
||
@endforeach
|
||
<tr class="details-total">
|
||
<td colspan="5" style="text-align: right;">Total Invoice Amount (USD):</td>
|
||
<td>{{ number_format($invoice_total_usd, 2) }}</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
@endif
|
||
|
||
<!-- ════════ NOTES ════════ -->
|
||
<div class="notes">
|
||
<div class="notes-title">⚠ Terms & Conditions</div>
|
||
Door-to-door service applies only to general cargo without special approvals. Consignee is responsible for import rules at destination. All shipments are subject to customs approval at origin and destination. The courier company cannot guarantee clearance.
|
||
</div>
|
||
|
||
<!-- ════════ SIGNATURE ════════ -->
|
||
<table class="signature-table">
|
||
<tr>
|
||
<td style="border-left: 1px solid #e5e7eb;">
|
||
Shipper Name & Signature
|
||
<div class="sig-line"></div>
|
||
</td>
|
||
<td>
|
||
Date
|
||
<div class="sig-line">...../...../..........</div>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
|
||
<!-- ════════ FOOTER ════════ -->
|
||
<div class="footer">
|
||
<div class="footer-brand">IFNEX LOGISTICS — We Deliver Value</div>
|
||
<div class="footer-track">Track Your Shipment: http://ifnex.net</div>
|
||
<div class="footer-meta">
|
||
AWB: {{ $shipment->awb_no }} | Generated: {{ now()->format('Y-m-d H:i') }} | © {{ date('Y') }} IFNEX Logistics
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</body>
|
||
</html> |