refactor: remove redundant dashboard widgets and clean up layout structure
This commit is contained in:
@@ -1,197 +1,372 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
@php
|
||||
$accent = $invoiceSettings->accent_color ?? '#FFB7C5';
|
||||
$hex = ltrim($accent, '#');
|
||||
$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)
|
||||
$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)
|
||||
$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; }
|
||||
* {
|
||||
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; }
|
||||
.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; }
|
||||
.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; }
|
||||
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; }
|
||||
.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; }
|
||||
.bank-box {
|
||||
background:
|
||||
{{ $tint }}
|
||||
;
|
||||
border-radius: 10px;
|
||||
padding: 14px 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.notes { font-size: 11px; color: #9CA3AF; font-style: italic; }
|
||||
.footer { margin-top: 40px; text-align: center; font-size: 11px; color: #D1D5DB; }
|
||||
.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">{{ $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>
|
||||
{{-- ── Header ─────────────────────────────────────────────────── --}}
|
||||
<table class="header-table" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td style="width:50%;">Description</td>
|
||||
<td class="td-center" style="width:10%;">Qty</td>
|
||||
<td class="td-right" style="width:20%;">Unit Price</td>
|
||||
<td class="td-right" style="width:20%;">Total</td>
|
||||
<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>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($invoice->items as $item)
|
||||
</table>
|
||||
|
||||
{{-- ── Billing Info ─────────────────────────────────────────────── --}}
|
||||
<table class="billing-table" cellpadding="0" cellspacing="0">
|
||||
<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>
|
||||
<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">{{ $invoice->client->full_address }}</div> @endif
|
||||
@else
|
||||
<div class="billing-detail">—</div>
|
||||
@endif
|
||||
</td>
|
||||
<td class="td-center">{{ $item->quantity }}</td>
|
||||
<td class="td-right">Rp {{ number_format($item->unit_price, 0, ',', '.') }}</td>
|
||||
<td class="td-right" style="font-weight:600;">Rp {{ number_format($item->total, 0, ',', '.') }}</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>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</table>
|
||||
|
||||
{{-- ── Totals ───────────────────────────────────────────────────── --}}
|
||||
<div class="totals-wrap clearfix">
|
||||
<div class="totals-inner">
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
{{-- ── Line Items ───────────────────────────────────────────────── --}}
|
||||
<table class="items" cellpadding="0" cellspacing="0">
|
||||
<thead>
|
||||
<tr>
|
||||
<td style="color:#6B7280;">Subtotal</td>
|
||||
<td class="amount">Rp {{ number_format($invoice->subtotal, 0, ',', '.') }}</td>
|
||||
<td style="width:50%;">Description</td>
|
||||
<td class="td-center" style="width:10%;">Qty</td>
|
||||
<td class="td-right" style="width:20%;">Unit Price</td>
|
||||
<td class="td-right" style="width:20%;">Total</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>
|
||||
</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-center">{{ $item->quantity }}</td>
|
||||
<td class="td-right">Rp {{ number_format($item->unit_price, 0, ',', '.') }}</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>
|
||||
</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
|
||||
{{-- ── 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">{{ $invoice->notes }}</div>
|
||||
@endif
|
||||
@if($invoice->notes)
|
||||
<div class="notes">{{ $invoice->notes }}</div>
|
||||
@endif
|
||||
|
||||
<div class="footer">Generated by KOL Manager · Thank you for the collaboration!</div>
|
||||
<div class="footer">Thank you for the collaboration!</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user