['except' => ''], 'filtroStato' => ['except' => ''], ]; public function updatingSearch() { $this->resetPage(); } public function updatingFiltroStato() { $this->resetPage(); } public function sortBy(string $field) { if ($this->sortField === $field) { $this->sortDirection = $this->sortDirection === 'asc' ? 'desc' : 'asc'; } else { $this->sortField = $field; $this->sortDirection = 'asc'; } } public function toggleActive(int $id) { // La lista è in sola lettura per i non-admin: creare/modificare/ // eliminare proclamatori è riservato all'amministratore. Il check sta // nel metodo perché la rotta index resta accessibile con // proclamatori.manage. $this->authorize('settings.manage'); $proclamatore = Proclamatore::findOrFail($id); $gruppo = $proclamatore->attivo ? $proclamatore->gruppoSorvegliato() : null; // Un sorvegliante reso non attivo scioglie il gruppo (Proclamatore::booted). $proclamatore->update(['attivo' => !$proclamatore->attivo]); if ($gruppo) { $this->avvisa("{$proclamatore->nome_completo} non è più attivo. " . self::gruppoSciolto($gruppo)); } } public function deleteProclamatore(int $id) { $this->authorize('settings.manage'); $proclamatore = Proclamatore::findOrFail($id); if ($proclamatore->assegnazioni()->aperte()->exists()) { $this->avvisaErrore("Il proclamatore {$proclamatore->nome_completo} ha assegnazioni aperte. Rientra prima i territori."); return; } // Nel cestino lascia il gruppo; se ne era il sorvegliante, il gruppo // si scioglie (Proclamatore::booted). $gruppo = $proclamatore->gruppoSorvegliato(); $proclamatore->delete(); $this->avvisa("Proclamatore {$proclamatore->nome_completo} spostato nel cestino." . ($gruppo ? ' ' . self::gruppoSciolto($gruppo) : '')); } public function anonimizza(int $id) { $this->authorize('settings.manage'); $proclamatore = Proclamatore::findOrFail($id); $gruppo = $proclamatore->gruppoSorvegliato(); $proclamatore->anonimizza(); $this->avvisa("Dati personali del proclamatore anonimizzati (GDPR)." . ($gruppo ? ' ' . self::gruppoSciolto($gruppo) : '')); } /** L'avviso quando un sorvegliante esce di scena: anche per ProclamatoreEdit. */ public static function gruppoSciolto(GruppoServizio $gruppo): string { return "Era il sorvegliante del gruppo {$gruppo->nome}: il gruppo è stato sciolto, i territori non ancora dati sono tornati in reparto e la sua utenza è disattivata."; } public function render() { // withCount rather than letting the view call // ->assegnazioni()->aperte()->count() per row, which issued one // COUNT(*) per displayed proclamatore on every render. $query = Proclamatore::query()->withCount([ 'assegnazioni as assegnazioni_aperte_count' => fn ($q) => $q->whereNull('returned_at'), ]); if ($this->search !== '') { // In-memory filter because nome/cognome are encrypted $all = $query->get(); $filtered = $all->filter(function ($p) { return str_contains( mb_strtolower($p->nome . ' ' . $p->cognome), mb_strtolower($this->search) ); }); if ($this->filtroStato === 'attivo') { $filtered = $filtered->where('attivo', true); } elseif ($this->filtroStato === 'inattivo') { $filtered = $filtered->where('attivo', false); } // Sort in-memory $filtered = $filtered->sortBy(function ($p) { return match ($this->sortField) { 'nome' => mb_strtolower($p->nome), 'cognome' => mb_strtolower($p->cognome), default => mb_strtolower($p->cognome), }; }, SORT_REGULAR, $this->sortDirection === 'desc'); // Manual pagination $page = $this->getPage(); $perPage = 20; $items = $filtered->slice(($page - 1) * $perPage, $perPage)->values(); $proclamatori = new \Illuminate\Pagination\LengthAwarePaginator( $items, $filtered->count(), $perPage, $page, ['path' => request()->url()] ); } else { if ($this->filtroStato === 'attivo') { $query->where('attivo', true); } elseif ($this->filtroStato === 'inattivo') { $query->where('attivo', false); } // cognome/nome encrypted, so sort in-memory $all = $query->get()->sortBy(function ($p) { return match ($this->sortField) { 'nome' => mb_strtolower($p->nome), 'cognome' => mb_strtolower($p->cognome), default => mb_strtolower($p->cognome), }; }, SORT_REGULAR, $this->sortDirection === 'desc'); $page = $this->getPage(); $perPage = 20; $items = $all->slice(($page - 1) * $perPage, $perPage)->values(); $proclamatori = new \Illuminate\Pagination\LengthAwarePaginator( $items, $all->count(), $perPage, $page, ['path' => request()->url()] ); } return view('livewire.proclamatori.proclamatore-index', [ 'proclamatori' => $proclamatori, // Per avvisare, prima di disattivare o cestinare, che il gruppo si scioglie. 'gruppiSorvegliati' => GruppoServizio::attivi()->pluck('nome', 'sorvegliante_id'), ]); } }