394 lines
14 KiB
PHP
394 lines
14 KiB
PHP
<!DOCTYPE html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
@php
|
|
$accent = $invoiceSettings->accent_color ?? '#FFB7C5';
|
|
$hex = ltrim($accent, '#');
|
|
$r = hexdec(substr($hex, 0, 2));
|
|
$g = hexdec(substr($hex, 2, 2));
|
|
$b = hexdec(substr($hex, 4, 2));
|
|
// 92% white + 8% accent → very light tint
|
|
$tint = sprintf(
|
|
'#%02X%02X%02X',
|
|
(int) (255 * 0.92 + $r * 0.08),
|
|
(int) (255 * 0.92 + $g * 0.08),
|
|
(int) (255 * 0.92 + $b * 0.08)
|
|
);
|
|
// 80% white + 20% accent → medium-light tint (for borders)
|
|
$tintMid = sprintf(
|
|
'#%02X%02X%02X',
|
|
(int) (255 * 0.80 + $r * 0.20),
|
|
(int) (255 * 0.80 + $g * 0.20),
|
|
(int) (255 * 0.80 + $b * 0.20)
|
|
);
|
|
@endphp
|
|
<style>
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
body {
|
|
font-family: 'Helvetica', Arial, sans-serif;
|
|
color: #374151;
|
|
font-size: 13px;
|
|
padding: 40px;
|
|
}
|
|
|
|
/* ── Header ───────────────────────────────── */
|
|
.header-table {
|
|
width: 100%;
|
|
margin-bottom: 36px;
|
|
}
|
|
|
|
.logo-name {
|
|
font-size: 22px;
|
|
font-weight: 900;
|
|
color:
|
|
{{ $accent }}
|
|
;
|
|
}
|
|
|
|
.logo-sub {
|
|
font-size: 11px;
|
|
color: #9CA3AF;
|
|
margin-top: 3px;
|
|
}
|
|
|
|
.inv-number {
|
|
font-size: 22px;
|
|
font-weight: 700;
|
|
color: #1F2937;
|
|
}
|
|
|
|
|
|
/* ── Billing grid ─────────────────────────── */
|
|
.billing-table {
|
|
width: 100%;
|
|
margin-bottom: 28px;
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 10px;
|
|
font-weight: 700;
|
|
color: #9CA3AF;
|
|
text-transform: uppercase;
|
|
letter-spacing: 1px;
|
|
margin-bottom: 6px;
|
|
}
|
|
|
|
.billing-name {
|
|
font-weight: 700;
|
|
font-size: 15px;
|
|
color: #111827;
|
|
}
|
|
|
|
.billing-detail {
|
|
font-size: 12px;
|
|
color: #6B7280;
|
|
margin-top: 2px;
|
|
}
|
|
|
|
.detail-table {
|
|
font-size: 12px;
|
|
width: auto;
|
|
float: right;
|
|
}
|
|
|
|
.detail-table td {
|
|
padding: 3px 0;
|
|
}
|
|
|
|
.detail-table .lbl {
|
|
color: #9CA3AF;
|
|
padding-right: 16px;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.detail-table .val {
|
|
font-weight: 600;
|
|
text-align: right;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
/* ── Line items ───────────────────────────── */
|
|
table.items {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
table.items thead td {
|
|
background:
|
|
{{ $tint }}
|
|
;
|
|
padding: 10px 12px;
|
|
font-size: 10px;
|
|
font-weight: 700;
|
|
color: #9CA3AF;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
table.items tbody td {
|
|
padding: 10px 12px;
|
|
border-bottom: 1px solid
|
|
{{ $tintMid }}
|
|
;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.td-right {
|
|
text-align: right;
|
|
}
|
|
|
|
.td-center {
|
|
text-align: center;
|
|
}
|
|
|
|
/* ── Totals ───────────────────────────────── */
|
|
.totals-wrap {
|
|
width: 100%;
|
|
margin-bottom: 24px;
|
|
}
|
|
|
|
.totals-inner {
|
|
width: 260px;
|
|
float: right;
|
|
}
|
|
|
|
.totals-inner table {
|
|
width: 100%;
|
|
font-size: 12px;
|
|
border-collapse: collapse;
|
|
}
|
|
|
|
.totals-inner table td {
|
|
padding: 4px 0;
|
|
}
|
|
|
|
.totals-inner table td.amount {
|
|
text-align: right;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.totals-total td {
|
|
border-top: 2px solid
|
|
{{ $accent }}
|
|
;
|
|
padding-top: 8px !important;
|
|
margin-top: 6px;
|
|
font-size: 15px;
|
|
font-weight: 800;
|
|
color:
|
|
{{ $accent }}
|
|
;
|
|
}
|
|
|
|
.clearfix::after {
|
|
content: "";
|
|
display: table;
|
|
clear: both;
|
|
}
|
|
|
|
/* ── Payment info ─────────────────────────── */
|
|
.bank-box {
|
|
background:
|
|
{{ $tint }}
|
|
;
|
|
border-radius: 10px;
|
|
padding: 14px 16px;
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.bank-title {
|
|
font-weight: 700;
|
|
font-size: 12px;
|
|
color: #374151;
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
.bank-detail {
|
|
font-size: 12px;
|
|
color: #6B7280;
|
|
}
|
|
|
|
.notes {
|
|
font-size: 11px;
|
|
color: #9CA3AF;
|
|
font-style: italic;
|
|
}
|
|
|
|
.footer {
|
|
margin-top: 40px;
|
|
text-align: center;
|
|
font-size: 11px;
|
|
color: #D1D5DB;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
|
|
{{-- ── Header ─────────────────────────────────────────────────── --}}
|
|
<table class="header-table" cellpadding="0" cellspacing="0">
|
|
<tr>
|
|
<td style="vertical-align:middle;">
|
|
<table cellpadding="0" cellspacing="0">
|
|
<tr>
|
|
@if($invoiceSettings->header_logo && file_exists(storage_path('app/public/' . $invoiceSettings->header_logo)))
|
|
<td style="vertical-align:middle; padding-right:12px; width:64px;">
|
|
<img src="{{ storage_path('app/public/' . $invoiceSettings->header_logo) }}"
|
|
style="width:52px; height:52px; object-fit:cover; border-radius:12px; display:block;"
|
|
alt="Logo">
|
|
</td>
|
|
@endif
|
|
<td style="vertical-align:middle;">
|
|
<div class="logo-name">{{ $invoiceSettings->header_name ?: 'Cathy' }}</div>
|
|
<div class="logo-sub">{{ $invoiceSettings->header_title ?: 'Personal Talent Assistant' }}
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
<td style="text-align:right; vertical-align:top;">
|
|
<div class="inv-number">{{ $invoice->invoice_number }}</div>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
{{-- ── Billing Info ─────────────────────────────────────────────── --}}
|
|
<table class="billing-table" cellpadding="0" cellspacing="0">
|
|
<tr>
|
|
<td style="width:50%; vertical-align:top; padding-right:24px;">
|
|
<div class="section-title">Bill To</div>
|
|
@if($invoice->client)
|
|
<div class="billing-name">{{ $invoice->client->name }}</div>
|
|
@if($invoice->client->company)
|
|
<div class="billing-detail">{{ $invoice->client->company }}</div> @endif
|
|
@if($invoice->client->email)
|
|
<div class="billing-detail">{{ $invoice->client->email }}</div> @endif
|
|
@if($invoice->client->full_address)
|
|
<div class="billing-detail">{!! nl2br(e($invoice->client->full_address)) !!}</div> @endif
|
|
@else
|
|
<div class="billing-detail">—</div>
|
|
@endif
|
|
</td>
|
|
<td style="width:50%; vertical-align:top; text-align:right;">
|
|
<div class="section-title">Invoice Details</div>
|
|
<table class="detail-table" cellpadding="0" cellspacing="0">
|
|
<tr>
|
|
<td class="lbl">Issue Date</td>
|
|
<td class="val">{{ $invoice->issue_date->format('d M Y') }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="lbl">Due Date</td>
|
|
<td class="val">{{ $invoice->due_date->format('d M Y') }}</td>
|
|
</tr>
|
|
@if($invoice->paid_date)
|
|
<tr>
|
|
<td class="lbl">Paid Date</td>
|
|
<td class="val">{{ $invoice->paid_date->format('d M Y') }}</td>
|
|
</tr>
|
|
@endif
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
{{-- ── Line Items ───────────────────────────────────────────────── --}}
|
|
<table class="items" cellpadding="0" cellspacing="0">
|
|
<thead>
|
|
<tr>
|
|
<td style="width:50%;">Description</td>
|
|
<td class="td-right" style="width:20%;">Unit Price</td>
|
|
<td class="td-center" style="width:10%;">Qty</td>
|
|
<td class="td-right" style="width:20%;">Total</td>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach($invoice->items as $item)
|
|
<tr>
|
|
<td>
|
|
{{ $item->description }}
|
|
@if(!$item->is_taxable)
|
|
<span
|
|
style="margin-left:6px; font-size:10px; background:#F3F4F6; color:#6B7280; padding:2px 8px; border-radius:10px; font-weight:600;">Non-Taxable</span>
|
|
@endif
|
|
</td>
|
|
<td class="td-right">Rp {{ number_format($item->unit_price, 0, ',', '.') }}</td>
|
|
<td class="td-center">{{ $item->quantity }}</td>
|
|
<td class="td-right" style="font-weight:600;">Rp {{ number_format($item->total, 0, ',', '.') }}</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
|
|
{{-- ── Totals ───────────────────────────────────────────────────── --}}
|
|
<div class="totals-wrap clearfix">
|
|
<div class="totals-inner">
|
|
<table cellpadding="0" cellspacing="0">
|
|
<tr>
|
|
<td style="color:#6B7280;">Subtotal</td>
|
|
<td class="amount">Rp {{ number_format($invoice->subtotal, 0, ',', '.') }}</td>
|
|
</tr>
|
|
@if($invoice->tax_rate > 0)
|
|
<tr>
|
|
<td style="color:#D97706;">Tax ({{ $invoice->tax_rate }}% — paid by client)</td>
|
|
<td class="amount" style="color:#D97706;">Rp {{ number_format($invoice->tax_amount, 0, ',', '.') }}
|
|
</td>
|
|
</tr>
|
|
@endif
|
|
<tr class="totals-total">
|
|
<td>Grand Total</td>
|
|
<td class="amount">{{ $invoice->formatted_total }}</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- ── Payment Info ──────────────────────────────────────────────── --}}
|
|
@if($invoice->bank_name)
|
|
<div class="bank-box">
|
|
<div class="bank-title">Payment Information</div>
|
|
<div class="bank-detail">
|
|
{{ $invoice->bank_name }}
|
|
@if($invoice->branch_name) · {{ $invoice->branch_name }} @endif
|
|
· {{ $invoice->bank_account }} · a/n {{ $invoice->bank_holder }}
|
|
</div>
|
|
</div>
|
|
@endif
|
|
|
|
@if($invoice->notes)
|
|
<div class="notes" style="margin-bottom: 24px;">{{ $invoice->notes }}</div>
|
|
@endif
|
|
|
|
<div style="margin-top: 40px;">
|
|
@if($invoice->signature_image && file_exists(storage_path('app/public/' . $invoice->signature_image)))
|
|
<div style="width: 200px; float: right; text-align: center;">
|
|
<div style="font-size: 11px; color: #374151; margin-bottom: 12px;">
|
|
Jakarta, {{ $invoice->issue_date->format('d F Y') }}
|
|
</div>
|
|
<img src="{{ storage_path('app/public/' . $invoice->signature_image) }}"
|
|
style="max-height: 80px; max-width: 180px; object-fit: contain; margin-bottom: 8px;">
|
|
<div style="font-size: 12px; font-weight: 800; color: #111827; text-transform: uppercase;">
|
|
{{ $invoice->signer_name ?: ($invoiceSettings->signer_name ?: ($invoiceSettings->header_name ?: 'Signature')) }}
|
|
</div>
|
|
@if($invoice->signer_title || $invoiceSettings->signer_title || $invoiceSettings->header_title)
|
|
<div style="font-size: 10px; color: #6B7280; text-transform: uppercase; margin-top: 3px;">
|
|
{{ $invoice->signer_title ?: ($invoiceSettings->signer_title ?: $invoiceSettings->header_title) }}
|
|
</div>
|
|
@endif
|
|
</div>
|
|
@endif
|
|
|
|
<div style="clear: both;"></div>
|
|
</div>
|
|
|
|
<!-- <div class="footer">Thank you for the collaboration!</div> -->
|
|
|
|
</body>
|
|
|
|
</html> |