authorize('site.manage'); } public function updatedSearch(): void { $this->resetPage(); } public function updatedYear(): void { $this->resetPage(); } public function render() { $invoices = Invoice::query() ->with(['customer', 'series']) ->when($this->search !== '', function ($q) { $term = '%'.$this->search.'%'; $q->where(fn ($w) => $w->where('number', 'like', $term) ->orWhereHas('customer', fn ($c) => $c->where('name', 'like', $term))); }) ->when($this->year !== '', fn ($q) => $q->whereYear('issued_on', (int) $this->year)) ->orderByDesc('issued_on') ->orderByDesc('id') ->paginate(25); return view('livewire.admin.invoices', [ 'invoices' => $invoices, // Straight from the rows rather than a fixed range: a list of years // with nothing in them is a filter that mostly returns nothing. // // Derived in PHP rather than with YEAR() in raw SQL. That function // is MySQL's; SQLite has no such thing, and a query that only runs // on one engine turns the test database into a different product // from the real one. 'years' => Invoice::query() ->orderByDesc('issued_on') ->pluck('issued_on') // ->local() even for a year (R19): on New Year's night the UTC // year is still the previous one, so the filter would offer a // year the operator is no longer in. ->map(fn ($date) => $date?->local()->format('Y')) ->filter() ->unique() ->values(), ]); } }