From 7c8a0ba94bca6d0051a4778009c13eb8b6d528fe Mon Sep 17 00:00:00 2001 From: Matt Young Date: Fri, 30 Jan 2026 18:10:37 -0600 Subject: [PATCH] Dashboard widgets for draft invoices and recent payments. --- .../components/⚡draft-invoices.blade.php | 90 ++++++++++++++++++ .../components/⚡recent-payments.blade.php | 91 +++++++++++++++++++ resources/views/dashboard.blade.php | 9 +- 3 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 resources/views/components/⚡draft-invoices.blade.php create mode 100644 resources/views/components/⚡recent-payments.blade.php diff --git a/resources/views/components/⚡draft-invoices.blade.php b/resources/views/components/⚡draft-invoices.blade.php new file mode 100644 index 0000000..dbc9201 --- /dev/null +++ b/resources/views/components/⚡draft-invoices.blade.php @@ -0,0 +1,90 @@ +loadInvoices(); + } + + public function loadInvoices(): void + { + $this->invoices = Cache::remember('draft_invoices', now()->addMinutes(15), function () { + return Invoice::where('status', InvoiceStatus::DRAFT) + ->with('client') + ->orderBy('created_at', 'desc') + ->limit(10) + ->get() + ->map(fn($invoice) => [ + 'uuid' => $invoice->uuid, + 'invoice_number' => $invoice->invoice_number, + 'client_name' => $invoice->client?->abbreviation ?? $invoice->client?->name ?? 'Unknown', + 'total' => $invoice->total, + 'created_at' => $invoice->created_at->format('M j'), + ]) + ->toArray(); + }); + } + + #[On('invoice-created')] + public function clearCache(): void + { + Cache::forget('draft_invoices'); + $this->loadInvoices(); + } + + public function refresh(): void + { + Cache::forget('draft_invoices'); + $this->loadInvoices(); + } +}; +?> + +
+
+

Draft Invoices

+ +
+ + @if(empty($invoices)) +
+

No draft invoices

+
+ @else +
+ + + @foreach($invoices as $invoice) + + + + + + @endforeach + +
+
{{ $invoice['invoice_number'] }}
+
{{ $invoice['client_name'] }}
+
+
${{ number_format($invoice['total'], 0) }}
+
{{ $invoice['created_at'] }}
+
+ + Edit + +
+
+ @endif + +

Cached for 15 min

+
\ No newline at end of file diff --git a/resources/views/components/⚡recent-payments.blade.php b/resources/views/components/⚡recent-payments.blade.php new file mode 100644 index 0000000..4e42b2b --- /dev/null +++ b/resources/views/components/⚡recent-payments.blade.php @@ -0,0 +1,91 @@ +loadPayments(); + } + + public function loadPayments(): void + { + $this->payments = Cache::remember('recent_payments', now()->addMinutes(15), function () { + return Payment::with(['invoice.client', 'contact']) + ->orderBy('payment_date', 'desc') + ->orderBy('created_at', 'desc') + ->limit(10) + ->get() + ->map(fn($payment) => [ + 'id' => $payment->id, + 'amount' => $payment->amount, + 'payment_date' => $payment->payment_date->format('M j'), + 'client_name' => $payment->invoice?->client?->abbreviation ?? $payment->invoice?->client?->name ?? 'Unknown', + 'invoice_number' => $payment->invoice?->invoice_number, + 'method' => $payment->payment_method->value, + 'status' => $payment->status->value, + 'status_color' => $payment->status === PaymentStatus::COMPLETED ? 'green' : ($payment->status === PaymentStatus::PENDING ? 'yellow' : 'red'), + ]) + ->toArray(); + }); + } + + #[On('payment-created')] + public function clearCache(): void + { + Cache::forget('recent_payments'); + $this->loadPayments(); + } + + public function refresh(): void + { + Cache::forget('recent_payments'); + $this->loadPayments(); + } +}; +?> + +
+
+

Recent Payments

+ +
+ + @if(empty($payments)) +
+

No payments yet

+
+ @else +
+ + + @foreach($payments as $payment) + + + + + + @endforeach + +
+
{{ $payment['client_name'] }}
+
{{ $payment['invoice_number'] }}
+
+
${{ number_format($payment['amount'], 2) }}
+
{{ $payment['payment_date'] }}
+
+ {{ ucfirst($payment['method']) }} +
+
+ @endif + +

Cached for 15 min

+
\ No newline at end of file diff --git a/resources/views/dashboard.blade.php b/resources/views/dashboard.blade.php index 1325aad..4f9af08 100644 --- a/resources/views/dashboard.blade.php +++ b/resources/views/dashboard.blade.php @@ -11,8 +11,13 @@ -
- +
+
+ +
+
+ +