++ dopo un'operazione si torna alla pagina di partenza, con i suoi filtri

- Gli elenchi tengono ricerca, filtri e ordinamento nell'indirizzo
  (#[Url]); la pagina c'era già.
- I link verso schede e operazioni (data-ritorno) portano ?da= con la
  pagina di partenza, o il da già ricevuto: si risale all'origine
  (elenco -> scheda -> Rientra -> elenco filtrato).
- Ritorno::valida accetta solo percorsi interni: niente rimandi esterni.
- Trait RicordaRitorno: redirect dopo il salvataggio, Annulla e
  "Torna indietro" usano la pagina di partenza. Senza da, tutto come prima.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Francesco Picone
2026-10-19 15:04:42 +02:00
parent 0c530b65b3
commit bc465f53f5
32 changed files with 451 additions and 58 deletions

View File

@@ -2,6 +2,7 @@
namespace App\Livewire\Assegnazioni;
use App\Livewire\Concerns\RicordaRitorno;
use Livewire\Component;
use Livewire\Attributes\Computed;
use Livewire\Attributes\Locked;
@@ -16,6 +17,8 @@ use Illuminate\Support\Facades\Notification;
class Assegna extends Component
{
use RicordaRitorno;
// ─── Invio del link ─────────────────────────────────────────
//
// Dopo l'assegnazione non si torna subito alla pagina: si sceglie il
@@ -234,7 +237,7 @@ class Assegna extends Component
session()->flash('success', $inviato
? "Territorio {$numero} assegnato a {$nome}: link inviato."
: "Territorio {$numero} assegnato a {$nome}. Il link è ancora da inviare: lo trovi segnalato nell'elenco.");
return $this->redirect(route('assegnazioni.assegna'), navigate: true);
return $this->redirect($this->destinazione(route('assegnazioni.assegna')), navigate: true);
}
private function assegnazioneInInvio(): ?Assegnazione

View File

@@ -3,12 +3,15 @@
namespace App\Livewire\Assegnazioni;
use Livewire\Attributes\Locked;
use App\Livewire\Concerns\RicordaRitorno;
use Livewire\Component;
use App\Models\Assegnazione;
use App\Models\Campagna;
class Rientra extends Component
{
use RicordaRitorno;
public Assegnazione $assegnazione;
public string $returned_at = '';
public bool $showCampaignPrompt = false;
@@ -109,7 +112,7 @@ class Rientra extends Component
}
session()->flash('success', "Territorio {$territorio->numero} rientrato da {$proclamatore->nome_completo} dopo {$this->assegnazione->giorni} giorni.");
return $this->redirect(route('territori.show', $territorio), navigate: true);
return $this->redirect($this->destinazione(route('territori.show', $territorio)), navigate: true);
}
public function render()

View File

@@ -2,11 +2,14 @@
namespace App\Livewire\Campagne;
use App\Livewire\Concerns\RicordaRitorno;
use Livewire\Component;
use App\Models\Campagna;
class CampagnaCreate extends Component
{
use RicordaRitorno;
public string $descrizione = '';
public string $start_date = '';
public string $end_date = '';
@@ -34,7 +37,7 @@ class CampagnaCreate extends Component
]);
session()->flash('success', "Campagna '{$campagna->descrizione}' creata.");
return $this->redirect(route('campagne.index'), navigate: true);
return $this->redirect($this->destinazione(route('campagne.index')), navigate: true);
}
public function render()

View File

@@ -2,11 +2,14 @@
namespace App\Livewire\Campagne;
use App\Livewire\Concerns\RicordaRitorno;
use Livewire\Component;
use App\Models\Campagna;
class CampagnaEdit extends Component
{
use RicordaRitorno;
public Campagna $campagna;
public string $descrizione = '';
public string $start_date = '';
@@ -47,7 +50,7 @@ class CampagnaEdit extends Component
]);
session()->flash('success', "Campagna aggiornata.");
return $this->redirect(route('campagne.index'), navigate: true);
return $this->redirect($this->destinazione(route('campagne.index')), navigate: true);
}
public function render()

View File

@@ -2,6 +2,7 @@
namespace App\Livewire\Campagne;
use App\Livewire\Concerns\RicordaRitorno;
use Livewire\Component;
use App\Models\Campagna;
use App\Models\Assegnazione;
@@ -9,6 +10,8 @@ use App\Models\Territorio;
class CampagnaShow extends Component
{
use RicordaRitorno;
public Campagna $campagna;
public function mount(Campagna $campagna)

View File

@@ -0,0 +1,33 @@
<?php
namespace App\Livewire\Concerns;
use App\Support\Ritorno;
use Livewire\Attributes\Locked;
/**
* Per le pagine che si aprono da un'altra (schede e operazioni): ricorda da
* dove si è partiti (?da=…, vedi App\Support\Ritorno) e ci torna dopo la
* conferma. Annulla e "Torna…" nella vista usano $ritorno allo stesso modo.
*
* Aperta senza `da` (menu laterale, link salvato) la pagina si comporta come
* prima: ogni componente passa la sua destinazione predefinita.
*/
trait RicordaRitorno
{
/** URL della pagina di partenza; null se aperta direttamente. */
#[Locked]
public ?string $ritorno = null;
/** Hook di Livewire: gira al mount di ogni componente che usa il trait. */
public function mountRicordaRitorno(): void
{
$this->ritorno = Ritorno::daRichiesta();
}
/** Dove andare dopo la conferma: la pagina di partenza, o quella predefinita. */
protected function destinazione(string $predefinita): string
{
return $this->ritorno ?? $predefinita;
}
}

View File

@@ -2,11 +2,14 @@
namespace App\Livewire\Proclamatori;
use App\Livewire\Concerns\RicordaRitorno;
use Livewire\Component;
use App\Models\Proclamatore;
class ProclamatoreCreate extends Component
{
use RicordaRitorno;
public string $nome = '';
public string $cognome = '';
public bool $attivo = true;
@@ -52,7 +55,7 @@ class ProclamatoreCreate extends Component
->log('created');
session()->flash('success', "Proclamatore {$proclamatore->nome_completo} creato.");
return $this->redirect(route('proclamatori.index'), navigate: true);
return $this->redirect($this->destinazione(route('proclamatori.index')), navigate: true);
}
public function render()

View File

@@ -2,11 +2,14 @@
namespace App\Livewire\Proclamatori;
use App\Livewire\Concerns\RicordaRitorno;
use Livewire\Component;
use App\Models\Proclamatore;
class ProclamatoreEdit extends Component
{
use RicordaRitorno;
public Proclamatore $proclamatore;
public string $nome = '';
public string $cognome = '';
@@ -59,7 +62,7 @@ class ProclamatoreEdit extends Component
]);
session()->flash('success', "Proclamatore {$this->proclamatore->nome_completo} aggiornato.");
return $this->redirect(route('proclamatori.index'), navigate: true);
return $this->redirect($this->destinazione(route('proclamatori.index')), navigate: true);
}
public function render()

View File

@@ -3,6 +3,7 @@
namespace App\Livewire\Proclamatori;
use App\Livewire\Concerns\Avvisa;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;
use App\Models\Proclamatore;
@@ -12,9 +13,14 @@ class ProclamatoreIndex extends Component
use Avvisa;
use WithPagination;
// Ricerca, filtro e ordinamento nell'indirizzo: si ritrovano tornando.
#[Url(except: '')]
public string $search = '';
#[Url(except: '')]
public string $filtroStato = '';
#[Url(except: 'cognome')]
public string $sortField = 'cognome';
#[Url(except: 'asc')]
public string $sortDirection = 'asc';
protected $queryString = [

View File

@@ -2,12 +2,15 @@
namespace App\Livewire\Proclamatori;
use App\Livewire\Concerns\RicordaRitorno;
use Livewire\Component;
use App\Models\Proclamatore;
use App\Models\Assegnazione;
class ProclamatoreShow extends Component
{
use RicordaRitorno;
public Proclamatore $proclamatore;
public function mount(Proclamatore $proclamatore)

View File

@@ -2,6 +2,7 @@
namespace App\Livewire;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;
use App\Models\Assegnazione;
@@ -19,12 +20,20 @@ class Registro extends Component
{
use WithPagination;
// Ricerca, filtri e ordinamento nell'indirizzo: si ritrovano tornando.
#[Url(except: '')]
public string $search = '';
#[Url(except: '')]
public string $filtroAnno = '';
#[Url(except: '')]
public string $filtroZona = '';
#[Url(except: '')]
public string $filtroTipologia = '';
#[Url(except: '')]
public string $filtroStato = ''; // aperte, chiuse
#[Url(except: 'territorio_numero')]
public string $sortField = 'territorio_numero';
#[Url(except: 'asc')]
public string $sortDirection = 'asc';
// ─── Modal create/edit ──────────────────────────────────────

View File

@@ -2,6 +2,7 @@
namespace App\Livewire\Territori;
use App\Livewire\Concerns\RicordaRitorno;
use Livewire\Component;
use Livewire\WithFileUploads;
use App\Models\Territorio;
@@ -11,6 +12,8 @@ use App\Services\TerritorioThumbnailService;
class TerritorioCreate extends Component
{
use RicordaRitorno;
use WithFileUploads;
public string $numero = '';
@@ -64,7 +67,7 @@ class TerritorioCreate extends Component
->log('created');
session()->flash('success', "Territorio {$territorio->numero} creato.");
return redirect()->route('territori.index');
return redirect()->to($this->destinazione(route('territori.index')));
}
public function render()

View File

@@ -2,6 +2,7 @@
namespace App\Livewire\Territori;
use App\Livewire\Concerns\RicordaRitorno;
use Livewire\Component;
use Livewire\WithFileUploads;
use App\Models\Territorio;
@@ -12,6 +13,8 @@ use Illuminate\Support\Facades\Storage;
class TerritorioEdit extends Component
{
use RicordaRitorno;
use WithFileUploads;
public Territorio $territorio;
@@ -82,7 +85,7 @@ class TerritorioEdit extends Component
$this->territorio->update($data);
session()->flash('success', "Territorio {$this->territorio->numero} aggiornato.");
return redirect()->route('territori.show', $this->territorio);
return redirect()->to($this->destinazione(route('territori.show', $this->territorio)));
}
public function removePdf()

View File

@@ -4,6 +4,7 @@ namespace App\Livewire\Territori;
use App\Livewire\Concerns\Avvisa;
use Illuminate\Pagination\LengthAwarePaginator;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;
use App\Models\Territorio;
@@ -15,14 +16,25 @@ class TerritorioIndex extends Component
use Avvisa;
use WithPagination;
// Ricerca, filtri e ordinamento stanno nell'indirizzo (#[Url]): tornando
// da una scheda o da un'operazione l'elenco si ritrova com'era.
#[Url(except: '')]
public string $search = '';
#[Url(except: '')]
public string $filterZona = '';
#[Url(except: '')]
public string $filterTipologia = '';
#[Url(except: '')]
public string $filterStato = '';
#[Url(except: '')]
public string $filterPriorita = '';
#[Url(except: '')]
public string $filterPdf = '';
#[Url(except: '')]
public string $filterContenuti = '';
#[Url(except: 'numero')]
public string $sortField = 'numero';
#[Url(except: 'asc')]
public string $sortDirection = 'asc';
protected $queryString = [

View File

@@ -2,12 +2,15 @@
namespace App\Livewire\Territori;
use App\Livewire\Concerns\RicordaRitorno;
use Livewire\Component;
use App\Models\Territorio;
use App\Models\Assegnazione;
class TerritorioShow extends Component
{
use RicordaRitorno;
public Territorio $territorio;
public function mount(Territorio $territorio)