refactor: improve fetch request handling, update invoice PDF layout, and adjust docker-compose configuration

This commit is contained in:
I-Fun
2026-04-05 16:25:58 +07:00
parent ed9e7dc0fd
commit d6b10f725b
7 changed files with 78 additions and 33 deletions

View File

@@ -303,8 +303,8 @@
<thead>
<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-center" style="width:10%;">Qty</td>
<td class="td-right" style="width:20%;">Total</td>
</tr>
</thead>
@@ -318,8 +318,8 @@
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-center">{{ $item->quantity }}</td>
<td class="td-right" style="font-weight:600;">Rp {{ number_format($item->total, 0, ',', '.') }}</td>
</tr>
@endforeach
@@ -361,17 +361,18 @@
</div>
@endif
<div style="margin-top: 40px;">
@if($invoice->notes)
<div class="notes" style="width: 50%; float: left; margin-top: 10px;">{{ $invoice->notes }}</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;">
<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>
@@ -386,7 +387,7 @@
<div style="clear: both;"></div>
</div>
<div class="footer">Thank you for the collaboration!</div>
<!-- <div class="footer">Thank you for the collaboration!</div> -->
</body>

View File

@@ -72,14 +72,21 @@
fd.append('header_logo', input.files[0]);
fd.append('_token', document.querySelector('meta[name=csrf-token]').content);
try {
const res = await fetch('{{ route('invoice-settings.upload-logo', [], false) }}', { method: 'POST', body: fd });
const res = await fetch('{{ route('invoice-settings.upload-logo', [], false) }}', {
method: 'POST',
body: fd,
headers: {
'Accept': 'application/json'
}
});
const data = await res.json();
if (res.ok) {
this.logoUrl = data.url + '?t=' + Date.now();
} else {
this.errorMsg = data.message ?? 'Upload failed.';
}
} catch {
} catch (err) {
console.error(err);
this.errorMsg = 'Network error. Please try again.';
}
this.uploading = false;
@@ -91,7 +98,11 @@
const fd = new FormData();
fd.append('_token', document.querySelector('meta[name=csrf-token]').content);
fd.append('_method', 'DELETE');
await fetch('{{ route('invoice-settings.delete-logo', [], false) }}', { method: 'POST', body: fd });
await fetch('{{ route('invoice-settings.delete-logo', [], false) }}', {
method: 'POST',
body: fd,
headers: { 'Accept': 'application/json' }
});
this.logoUrl = '';
}
}">
@@ -234,14 +245,21 @@
fd.append('signature_image', input.files[0]);
fd.append('_token', document.querySelector('meta[name=csrf-token]').content);
try {
const res = await fetch('{{ route('invoice-settings.upload-signature', [], false) }}', { method: 'POST', body: fd });
const res = await fetch('{{ route('invoice-settings.upload-signature', [], false) }}', {
method: 'POST',
body: fd,
headers: {
'Accept': 'application/json'
}
});
const data = await res.json();
if (res.ok) {
this.signatureUrl = data.url + '?t=' + Date.now();
} else {
this.errorMsg = data.message ?? 'Upload failed.';
}
} catch {
} catch (err) {
console.error(err);
this.errorMsg = 'Network error. Please try again.';
}
this.uploading = false;
@@ -253,7 +271,11 @@
const fd = new FormData();
fd.append('_token', document.querySelector('meta[name=csrf-token]').content);
fd.append('_method', 'DELETE');
await fetch('{{ route('invoice-settings.delete-signature', [], false) }}', { method: 'POST', body: fd });
await fetch('{{ route('invoice-settings.delete-signature', [], false) }}', {
method: 'POST',
body: fd,
headers: { 'Accept': 'application/json' }
});
this.signatureUrl = '';
}
}">

View File

@@ -90,8 +90,8 @@
<thead>
<tr class="text-xs text-gray-500 uppercase" style="background:{{ $tint }}">
<th class="text-left py-3 px-4 rounded-l-2xl">Description</th>
<th class="text-center py-3 px-4">Qty</th>
<th class="text-right py-3 px-4">Unit Price</th>
<th class="text-center py-3 px-4">Qty</th>
<th class="text-right py-3 px-4 rounded-r-2xl">Total</th>
</tr>
</thead>
@@ -105,9 +105,9 @@
class="ml-1.5 text-xs bg-gray-100 text-gray-500 px-2 py-0.5 rounded-full font-medium">Non-Taxable</span>
@endif
</td>
<td class="py-3 px-4 text-sm text-center text-gray-600">{{ $item->quantity }}</td>
<td class="py-3 px-4 text-sm text-right text-gray-600">Rp
{{ number_format($item->unit_price, 0, ',', '.') }}</td>
<td class="py-3 px-4 text-sm text-center text-gray-600">{{ $item->quantity }}</td>
<td class="py-3 px-4 text-sm text-right font-semibold text-gray-800">Rp
{{ number_format($item->total, 0, ',', '.') }}</td>
</tr>
@@ -137,7 +137,7 @@
{{-- Bank Info --}}
@if($invoice->bank_name)
<div class="rounded-2xl p-4 text-sm" style="background:{{ $tint }}">
<div class="rounded-2xl p-4 text-sm mb-4" style="background:{{ $tint }}">
<div class="font-semibold text-gray-700 mb-2">💳 Payment Info</div>
<div class="text-gray-600">
{{ $invoice->bank_name }}
@@ -147,12 +147,11 @@
</div>
@endif
<div class="flex flex-col sm:flex-row justify-between items-start mt-10 gap-6">
<div class="flex-1 text-left">
@if($invoice->notes)
<div class="text-sm text-gray-500 italic">{{ $invoice->notes }}</div>
@endif
</div>
@if($invoice->notes)
<div class="text-sm text-gray-500 italic mb-8">{{ $invoice->notes }}</div>
@endif
<div class="flex justify-end mt-10">
@if($invoice->signature_image)
<div class="shrink-0 text-center w-full sm:w-auto">
<div class="text-sm text-gray-500 mb-3">