From 6f88c65d73cde27e0eb4fda27971f1c747f7eeaf Mon Sep 17 00:00:00 2001 From: Francesco Picone Date: Tue, 20 Oct 2026 15:43:15 +0200 Subject: [PATCH] ++ storico assegnazioni: una tabella sola con le colonne in linea, dal piu' recente Nelle schede di territorio e proclamatore ogni anno teocratico era una tabella a se', con le colonne dimensionate sul proprio contenuto. Ora una tabella con un'intestazione, colonne fisse, l'anno come riga di separazione (tm-riga-gruppo, titolo anche su telefono); ordine esplicito dal piu' recente. Nella scheda del proclamatore Campagna "Si'/No" e badge "via gruppo". Co-Authored-By: Claude Opus 5.5 --- HANDOFF.md | 13 +++ README.md | 4 +- .../Proclamatori/ProclamatoreShow.php | 5 +- app/Livewire/Territori/TerritorioShow.php | 5 +- resources/css/app.css | 12 +++ .../proclamatori/proclamatore-show.blade.php | 96 ++++++++++--------- .../territori/territorio-show.blade.php | 94 +++++++++--------- tests/Feature/StoricoAssegnazioniTest.php | 74 ++++++++++++++ 8 files changed, 210 insertions(+), 93 deletions(-) create mode 100644 tests/Feature/StoricoAssegnazioniTest.php diff --git a/HANDOFF.md b/HANDOFF.md index cbf58c6..23667c2 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -235,6 +235,19 @@ Decisioni successive dell'utente (20 ottobre 2026): (erano `home_giorni_giacenza` e `home_is_prioritario`, anche nel PDF). - "Il mio gruppo" mostra sotto il titolo nome e cognome del sorvegliante. +### Storico assegnazioni in linea (20 ottobre 2026) + +Richiesta dell'utente (screenshot della scheda territorio): le colonne dello +storico cambiavano posizione da un anno all'altro, perché ogni anno era una +tabella a sé dimensionata sul suo contenuto. Ora, nella scheda del territorio +e in quella del proclamatore, è **una tabella sola** con un'intestazione, +colonne a larghezza fissa (`table-fixed`, `w-[..%]`), e l'anno come riga di +separazione `tr.tm-riga-gruppo` (in `app.css`, su telefono resta un titolo e +non diventa una scheda). Ordine esplicito: anni dal più recente +(`sortKeysDesc`), dentro l'anno per data di assegnazione. Nella scheda del +proclamatore la colonna Campagna ora dice "Sì — …" / "No" come in quella del +territorio, e c'è il badge "via gruppo …". Test: `StoricoAssegnazioniTest`. + ### Rientro dall'elenco dei territori assegnati (20 ottobre 2026) Richiesta dell'utente ("un tasto che va alla registrazione", dallo screenshot diff --git a/README.md b/README.md index 62ced75..9905590 100644 --- a/README.md +++ b/README.md @@ -698,7 +698,9 @@ docker compose --profile dev up -d --build il form) - Filtri per zona, tipologia e stato, conservati nell'indirizzo della pagina - Badge di stato colorati e indicatore di priorità (manuale o automatica) -- Dettaglio con visualizzatore PDF e storico assegnazioni per anno teocratico +- Dettaglio con visualizzatore PDF e storico assegnazioni per anno teocratico: + una tabella sola con le colonne in linea, l'anno come riga di separazione, + dal più recente (lo stesso nella scheda del proclamatore) - Link PDF pubblico condivisibile, a scadenza configurabile - Soft delete con cestino (ripristino o eliminazione definitiva) - Import massivo di PDF da cartella o archivio ZIP, elaborato in background diff --git a/app/Livewire/Proclamatori/ProclamatoreShow.php b/app/Livewire/Proclamatori/ProclamatoreShow.php index b5550b0..57c5d98 100644 --- a/app/Livewire/Proclamatori/ProclamatoreShow.php +++ b/app/Livewire/Proclamatori/ProclamatoreShow.php @@ -24,8 +24,11 @@ class ProclamatoreShow extends Component $assegnazioni = Assegnazione::where('proclamatore_id', $this->proclamatore->id) ->with(['territorio', 'annoTeocratico', 'campagna']) ->orderByDesc('assigned_at') + ->orderByDesc('id') ->get() - ->groupBy(fn($a) => $a->annoTeocratico->label); + ->groupBy(fn($a) => $a->annoTeocratico->label) + // Dal più recente: gli anni ("2026-2027") si ordinano come testo. + ->sortKeysDesc(); $stats = [ 'totale_assegnazioni' => Assegnazione::where('proclamatore_id', $this->proclamatore->id)->count(), diff --git a/app/Livewire/Territori/TerritorioShow.php b/app/Livewire/Territori/TerritorioShow.php index d34b8ac..53192da 100644 --- a/app/Livewire/Territori/TerritorioShow.php +++ b/app/Livewire/Territori/TerritorioShow.php @@ -23,8 +23,11 @@ class TerritorioShow extends Component $assegnazioni = Assegnazione::where('territorio_id', $this->territorio->id) ->with(['proclamatore', 'annoTeocratico', 'campagna', 'creatoDa', 'rientratoDa']) ->orderByDesc('assigned_at') + ->orderByDesc('id') ->get() - ->groupBy(fn($a) => $a->annoTeocratico->label); + ->groupBy(fn($a) => $a->annoTeocratico->label) + // Dal più recente: gli anni ("2026-2027") si ordinano come testo. + ->sortKeysDesc(); return view('livewire.territori.territorio-show', [ 'activeAssignment' => $this->territorio->assegnazioneCorrente, diff --git a/resources/css/app.css b/resources/css/app.css index a33494e..1a7ccb6 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -1652,6 +1652,18 @@ html { scroll-behavior: smooth; } padding-top: 10px; border-top: 1px solid var(--tm-bordo) !important; } + /* Riga di separazione di un gruppo (l'anno teocratico negli storici): + resta un titolo, non diventa una scheda. */ + table.table-cards tr.tm-riga-gruppo { + border: none; + background: transparent; + padding: 0; + margin: 16px 0 6px; + } + table.table-cards tr.tm-riga-gruppo th { + display: block; + padding: 0 2px; + } /* Cells spanning all columns (empty state, inline edit form) stay full width and block, so their inner layout isn't squeezed by the flex row. */ table.table-cards td[colspan] { diff --git a/resources/views/livewire/proclamatori/proclamatore-show.blade.php b/resources/views/livewire/proclamatori/proclamatore-show.blade.php index ed05027..6505c10 100644 --- a/resources/views/livewire/proclamatori/proclamatore-show.blade.php +++ b/resources/views/livewire/proclamatori/proclamatore-show.blade.php @@ -101,52 +101,56 @@

Storico Assegnazioni

- @forelse($assegnazioniPerAnno as $annoLabel => $assegnazioni) -
-

Anno Teocratico {{ $annoLabel }}

-
- - - - - - - - - - - - @foreach($assegnazioni as $assegnazione) - - - - - - - - @endforeach - -
TerritorioAssegnatoRientratoGiorniCampagna
- - {{ $assegnazione->territorio?->numero ?? 'N/A' }} - - {{ $assegnazione->assigned_at->format('d/m/Y') }} - @if($assegnazione->returned_at) - {{ $assegnazione->returned_at->format('d/m/Y') }} - @else - In corso - @endif - {{ $assegnazione->giorni }} - @if($assegnazione->counted_in_campaign) - {{ $assegnazione->campagna?->descrizione }} - @else - - - @endif -
-
-
- @empty + {{-- Come nella scheda del territorio: una tabella sola, colonne fisse, + l'anno come riga di separazione (tm-riga-gruppo), dal più recente. --}} + @if($assegnazioniPerAnno->isEmpty())

Nessuna assegnazione registrata.

- @endforelse + @else +
+ + + + + + + + + + + @foreach($assegnazioniPerAnno as $annoLabel => $assegnazioni) + + + + + @foreach($assegnazioni as $assegnazione) + + + + + + + + @endforeach + + @endforeach +
TerritorioAssegnatoRientratoGiorniCampagna
Anno Teocratico {{ $annoLabel }}
+ N° {{ $assegnazione->territorio?->numero ?? 'N/A' }}@if($assegnazione->gruppo_nome)via gruppo {{ $assegnazione->gruppo_nome }}@endif + {{ $assegnazione->assigned_at->format('d/m/Y') }} + @if($assegnazione->returned_at) + {{ $assegnazione->returned_at->format('d/m/Y') }} + @else + In corso + @endif + {{ $assegnazione->giorni }} + @if($assegnazione->counted_in_campaign) + Sì — {{ $assegnazione->campagna?->descrizione }} + @elseif($assegnazione->counted_in_campaign === false) + No + @else + - + @endif +
+
+ @endif
diff --git a/resources/views/livewire/territori/territorio-show.blade.php b/resources/views/livewire/territori/territorio-show.blade.php index 5af6811..a7a02b2 100644 --- a/resources/views/livewire/territori/territorio-show.blade.php +++ b/resources/views/livewire/territori/territorio-show.blade.php @@ -161,50 +161,56 @@

Storico Assegnazioni

- @forelse($assegnazioniPerAnno as $annoLabel => $assegnazioni) -
-

Anno Teocratico {{ $annoLabel }}

-
- - - - - - - - - - - - @foreach($assegnazioni as $assegnazione) - - - - - - - - @endforeach - -
ProclamatoreAssegnatoRientratoGiorniCampagna
{{ $assegnazione->proclamatore?->nome_completo ?? 'N/A' }}@if($assegnazione->gruppo_nome)via gruppo {{ $assegnazione->gruppo_nome }}@endif{{ $assegnazione->assigned_at->format('d/m/Y') }} - @if($assegnazione->returned_at) - {{ $assegnazione->returned_at->format('d/m/Y') }} - @else - In corso - @endif - {{ $assegnazione->giorni }} - @if($assegnazione->counted_in_campaign) - Sì — {{ $assegnazione->campagna?->descrizione }} - @elseif($assegnazione->counted_in_campaign === false) - No - @else - - - @endif -
-
-
- @empty + {{-- Una tabella sola, colonne a larghezza fissa: con una tabella per + anno ciascuna si dimensionava sul suo contenuto e le colonne non + erano in linea. L'anno è una riga di separazione (tm-riga-gruppo). + Ordine: dal più recente, per anno e per data di assegnazione. --}} + @if($assegnazioniPerAnno->isEmpty())

Nessuna assegnazione registrata.

- @endforelse + @else +
+ + + + + + + + + + + @foreach($assegnazioniPerAnno as $annoLabel => $assegnazioni) + + + + + @foreach($assegnazioni as $assegnazione) + + + + + + + + @endforeach + + @endforeach +
ProclamatoreAssegnatoRientratoGiorniCampagna
Anno Teocratico {{ $annoLabel }}
{{ $assegnazione->proclamatore?->nome_completo ?? 'N/A' }}@if($assegnazione->gruppo_nome)via gruppo {{ $assegnazione->gruppo_nome }}@endif{{ $assegnazione->assigned_at->format('d/m/Y') }} + @if($assegnazione->returned_at) + {{ $assegnazione->returned_at->format('d/m/Y') }} + @else + In corso + @endif + {{ $assegnazione->giorni }} + @if($assegnazione->counted_in_campaign) + Sì — {{ $assegnazione->campagna?->descrizione }} + @elseif($assegnazione->counted_in_campaign === false) + No + @else + - + @endif +
+
+ @endif diff --git a/tests/Feature/StoricoAssegnazioniTest.php b/tests/Feature/StoricoAssegnazioniTest.php new file mode 100644 index 0000000..42145a4 --- /dev/null +++ b/tests/Feature/StoricoAssegnazioniTest.php @@ -0,0 +1,74 @@ +withoutVite(); + $this->seed(RolesAndPermissionsSeeder::class); + Setting::firstOrCreate([], ['congregazione_nome' => 'Congregazione di prova']); + + $this->admin = User::create(['name' => 'Admin', 'email' => 'admin@example.test', 'password' => 'password-di-prova']); + $this->admin->assignRole('amministratore'); + + $this->territorio = Territorio::create(['numero' => '7', 'attivo' => true]); + $this->proclamatore = Proclamatore::create(['nome' => 'Mario', 'cognome' => 'Rossi', 'attivo' => true]); + + $vecchio = AnnoTeocratico::create(['label' => '2024-2025', 'start_date' => '2024-09-01', 'end_date' => '2025-08-31']); + $recente = AnnoTeocratico::create(['label' => '2025-2026', 'start_date' => '2025-09-01', 'end_date' => '2026-08-31']); + + // Create in disordine: l'ordine lo deve dare la pagina. + foreach ([[$vecchio, '2024-10-01', '2024-11-01'], [$recente, '2025-10-01', '2025-11-15'], [$vecchio, '2025-03-01', '2025-04-01']] as [$anno, $dal, $al]) { + Assegnazione::create([ + 'territorio_id' => $this->territorio->id, 'proclamatore_id' => $this->proclamatore->id, + 'anno_teocratico_id' => $anno->id, 'assigned_at' => $dal, 'returned_at' => $al, 'created_by' => $this->admin->id, + ]); + } + } + + public function test_nella_scheda_del_territorio_una_tabella_sola_dal_piu_recente(): void + { + $html = $this->actingAs($this->admin)->get(route('territori.show', $this->territorio))->assertOk() + ->assertSeeInOrder(['Anno Teocratico 2025-2026', '01/10/2025', 'Anno Teocratico 2024-2025', '01/03/2025', '01/10/2024']) + ->getContent(); + + $this->assertSame(1, substr_count($html, '>Proclamatore'), "Un'intestazione sola: colonne in linea"); + $this->assertSame(2, substr_count($html, 'tm-riga-gruppo')); + } + + public function test_nella_scheda_del_proclamatore_una_tabella_sola_dal_piu_recente(): void + { + $html = $this->actingAs($this->admin)->get(route('proclamatori.show', $this->proclamatore))->assertOk() + ->assertSeeInOrder(['Anno Teocratico 2025-2026', '01/10/2025', 'Anno Teocratico 2024-2025', '01/03/2025', '01/10/2024']) + ->getContent(); + + $this->assertSame(1, substr_count($html, '>Territorio'), "Un'intestazione sola: colonne in linea"); + $this->assertSame(2, substr_count($html, 'tm-riga-gruppo')); + } +}