From 561153c7540cade46d1f4fc8cb0128e96ee1a060 Mon Sep 17 00:00:00 2001 From: Francesco Picone Date: Sun, 26 Jul 2026 00:08:55 +0200 Subject: [PATCH] ++ fix --- HANDOFF.md | 46 +++++++++++++++---- .../Controllers/AssignmentPdfController.php | 6 ++- .../Controllers/ShortPdfLinkController.php | 7 +-- app/Livewire/Assegnazioni/Assegna.php | 23 +++++++++- app/Livewire/Profile.php | 6 ++- app/Livewire/Settings/SettingsEdit.php | 4 -- app/Livewire/Territori/TerritorioShow.php | 3 +- .../views/components/layouts/app.blade.php | 10 ++++ .../livewire/assegnazioni/assegna.blade.php | 21 +++++++-- .../livewire/campagne/campagna-show.blade.php | 12 ++--- .../proclamatori/proclamatore-show.blade.php | 12 ++--- .../livewire/settings/settings-edit.blade.php | 9 +--- .../livewire/settings/xml-exchange.blade.php | 16 +++---- .../territori/territorio-show.blade.php | 14 +++--- 14 files changed, 127 insertions(+), 62 deletions(-) diff --git a/HANDOFF.md b/HANDOFF.md index 67e37c9..93f4087 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -177,9 +177,35 @@ larghezza supera i 640px → torna la tabella normale (per questo landscape "non problemi"). Convenzioni: ogni `` dati ha `data-label="..."`; la cella azioni ha classe `cell-actions` (niente label, occupa la riga a piena larghezza); le celle `colspan` (stato vuoto, form di modifica utente inline) restano `block` a -piena larghezza. Applicata a: territori, proclamatori, campagne, registro, -utenti, audit-log e i due cestini. La pagina *Assegnazioni* era già ottimizzata e -non è stata toccata. +piena larghezza. Applicata a tutte le liste e sottopagine con tabelle: territori, +proclamatori, campagne, registro, utenti, audit-log, i due cestini, le tabelle +"storico assegnazioni" di territorio-show/proclamatore-show, "territori +conteggiati" di campagna-show e le due tabelle di esito import in xml-exchange +(una a classi Tailwind, una a stili inline — `border:none !important` nella regola +gestisce anche i bordi inline). La pagina *Assegnazioni* era già ottimizzata. + +### Scadenza link PDF unificata con la soglia rientro + +La "Validità link PDF (mesi)" è stata rimossa: il link condivisibile ora scade +esattamente quando l'assegnazione raggiunge la **soglia rientro** +(`giorni_per_smarrito`), cioè `assigned_at + giorni_per_smarrito` — la stessa +data di `Assegnazione::data_consegna_presunta` e del chip "Scadenza" nel viewer. +`AssignmentPdfController::linkScaduto` e `ShortPdfLinkController` calcolano ora +`addDays(giorni_per_smarrito)` invece di `addMonths(ttl)`; la scadenza vale solo +per i non autenticati e il link muore comunque al rientro (`is_aperta`). Rimossi +il campo Impostazioni e la proprietà `assignment_link_ttl_months` in +`SettingsEdit`. **La colonna `assignment_link_ttl_hours` resta nel DB** (niente +migration distruttiva): è ormai vestigiale per la logica ma l'export/import XML +continua a leggerla/scriverla senza effetti. + +### Ricerca rapida nella lista link (pagina Assegna) + +La sezione "Territori Assegnati" (i link PDF) ha un unico campo che filtra per +numero territorio, zona e proclamatore. Il filtro è **in memoria** (proprietà +`linkSearch`, collection `assegnazioniAperteVisibili`) perché nome/cognome del +proclamatore sono cifrati e non filtrabili via SQL — stesso approccio del +Registro. La sezione resta visibile anche a risultato vuoto (mostra "Nessun +risultato"), perché l'`@if` esterno guarda la lista non filtrata. ### Assegnare un territorio ne azzera il flag "prioritario" @@ -204,12 +230,14 @@ Tre ritocchi minori ma con qualche implicazione: ogni utente loggato (nel gruppo `auth`, nessun permesso): l'utente corrente può modificare il proprio nome/cognome ed email (`updateProfile`) e cambiare la password (`updatePassword`, con verifica della password attuale via regola - `current_password`; il cast `hashed` cifra al salvataggio). Nell'header il - blocco utente è un link a questa pagina, con nome in evidenza ed - `email · qualifica` sotto. Non esiste un campo "username" né "cognome" - separato: `name` è il nome completo (etichettato "Nome e cognome") e l'email fa - da identificativo. La qualifica (ruolo) non è modificabile dal profilo — resta - in gestione all'admin. + `current_password`; il cast `hashed` cifra al salvataggio). Dopo il salvataggio + dei dati `updateProfile` fa `redirect(navigate:true)` sulla stessa pagina, così + header (nel layout, fuori dal componente) e card mostrano subito i nuovi valori. + Il link al profilo è nell'header su desktop e, su mobile, in fondo alla sidebar + (`lg:hidden`, dopo un separatore) — sull'header è `hidden sm:flex`. Non esiste + un campo "username" né "cognome" separato: `name` è il nome completo + (etichettato "Nome e cognome") e l'email fa da identificativo. La qualifica + (ruolo) non è modificabile dal profilo — resta in gestione all'admin. - **Viewer PDF pubblico**: oltre a territorio/proclamatore/data mostra ora *giorni assegnato*, *consegna prevista* e *scadenza*. Sono attributi calcolati su `Assegnazione` (`data_consegna_presunta`, `giorni_alla_scadenza`) basati diff --git a/app/Http/Controllers/AssignmentPdfController.php b/app/Http/Controllers/AssignmentPdfController.php index fe104b7..f1443bd 100644 --- a/app/Http/Controllers/AssignmentPdfController.php +++ b/app/Http/Controllers/AssignmentPdfController.php @@ -65,9 +65,11 @@ class AssignmentPdfController extends Controller return null; } - $ttlMonths = max(1, (int) \App\Models\Setting::getValue('assignment_link_ttl_hours', 1)); + // Il link scade quando l'assegnazione raggiunge la soglia rientro + // (giorni_per_smarrito), cioè quando il territorio diventa "da rientrare". + $soglia = max(1, (int) \App\Models\Setting::getValue('giorni_per_smarrito', 120)); - if ($assignment->assigned_at->copy()->addMonths($ttlMonths)->isPast()) { + if ($assignment->assigned_at->copy()->addDays($soglia)->isPast()) { return view('assignments.link-scaduto', [ 'numero' => $assignment->territorio?->numero, ]); diff --git a/app/Http/Controllers/ShortPdfLinkController.php b/app/Http/Controllers/ShortPdfLinkController.php index 5bf395a..d5fbc4b 100644 --- a/app/Http/Controllers/ShortPdfLinkController.php +++ b/app/Http/Controllers/ShortPdfLinkController.php @@ -15,10 +15,11 @@ class ShortPdfLinkController extends Controller abort_unless($assignment->is_aperta, 403); abort_unless($assignment->territorio?->pdf_path, 404); - // Unauthenticated users (proclamatori) are subject to link TTL + // Unauthenticated users (proclamatori) are subject to the link expiry: + // il link scade al raggiungimento della soglia rientro (giorni_per_smarrito). if (! auth()->check()) { - $ttlMonths = max(1, (int) \App\Models\Setting::getValue('assignment_link_ttl_hours', 1)); - if ($assignment->assigned_at->copy()->addMonths($ttlMonths)->isPast()) { + $soglia = max(1, (int) \App\Models\Setting::getValue('giorni_per_smarrito', 120)); + if ($assignment->assigned_at->copy()->addDays($soglia)->isPast()) { return view('assignments.link-scaduto', [ 'numero' => $assignment->territorio?->numero, ]); diff --git a/app/Livewire/Assegnazioni/Assegna.php b/app/Livewire/Assegnazioni/Assegna.php index 6380824..00a7661 100644 --- a/app/Livewire/Assegnazioni/Assegna.php +++ b/app/Livewire/Assegnazioni/Assegna.php @@ -16,6 +16,7 @@ class Assegna extends Component public ?int $proclamatore_id = null; public string $assigned_at = ''; public string $territorioSearch = ''; + public string $linkSearch = ''; // Optional pre-selection from parent context public ?int $preselectedTerritorioId = null; @@ -129,13 +130,31 @@ class Assegna extends Component ->get() ->sortBy(fn($a) => (int) $a->territorio?->numero); - $linkTtlMonths = max(1, (int) \App\Models\Setting::getValue('assignment_link_ttl_hours', 1)); + // Ricerca rapida nella lista dei link: numero territorio, zona, + // proclamatore in un solo campo. In memoria perché nome/cognome del + // proclamatore sono cifrati e non filtrabili via SQL. + $assegnazioniAperteVisibili = $assegnazioniAperte; + if (trim($this->linkSearch) !== '') { + $term = mb_strtolower(trim($this->linkSearch)); + $assegnazioniAperteVisibili = $assegnazioniAperte->filter(function ($a) use ($term) { + $haystack = mb_strtolower( + ($a->territorio?->numero ?? '') . ' ' . + ($a->territorio?->zona?->nome ?? '') . ' ' . + ($a->proclamatore?->nome_completo ?? '') + ); + return str_contains($haystack, $term); + })->values(); + } + + // Il link scade alla soglia rientro (giorni_per_smarrito). + $sogliaRientro = max(1, (int) \App\Models\Setting::getValue('giorni_per_smarrito', 120)); return view('livewire.assegnazioni.assegna', [ 'territoriDisponibili' => $territoriDisponibili, 'proclamatoriAttivi' => $proclamatoriAttivi, 'assegnazioniAperte' => $assegnazioniAperte, - 'linkTtlMonths' => $linkTtlMonths, + 'assegnazioniAperteVisibili' => $assegnazioniAperteVisibili, + 'sogliaRientro' => $sogliaRientro, ]); } } diff --git a/app/Livewire/Profile.php b/app/Livewire/Profile.php index d21f60b..ef487b6 100644 --- a/app/Livewire/Profile.php +++ b/app/Livewire/Profile.php @@ -21,7 +21,7 @@ class Profile extends Component $this->email = $user->email; } - public function updateProfile(): void + public function updateProfile() { $user = auth()->user(); @@ -36,6 +36,10 @@ class Profile extends Component ]); session()->flash('profile_success', 'Profilo aggiornato con successo.'); + + // Ricarica la pagina così header e card mostrano subito i nuovi dati + // (l'header vive nel layout, fuori dal componente). + return $this->redirect(route('profile'), navigate: true); } public function updatePassword(): void diff --git a/app/Livewire/Settings/SettingsEdit.php b/app/Livewire/Settings/SettingsEdit.php index ac01b39..24d371d 100644 --- a/app/Livewire/Settings/SettingsEdit.php +++ b/app/Livewire/Settings/SettingsEdit.php @@ -12,7 +12,6 @@ class SettingsEdit extends Component public int $giorni_giacenza_prioritari = 180; public int $giorni_per_smarrito = 120; public int $home_limit_list = 10; - public int $assignment_link_ttl_months = 1; public bool $pdf_viewer_show_download = true; public int $audit_retention_days = 365; @@ -24,7 +23,6 @@ class SettingsEdit extends Component $this->giorni_giacenza_prioritari = $settings->giorni_giacenza_prioritari ?? 180; $this->giorni_per_smarrito = $settings->giorni_per_smarrito ?? 120; $this->home_limit_list = $settings->home_limit_list ?? 10; - $this->assignment_link_ttl_months = $settings->assignment_link_ttl_hours ?? 1; $this->pdf_viewer_show_download = $settings->pdf_viewer_show_download ?? true; $this->audit_retention_days = $settings->audit_retention_days ?? 365; } @@ -37,7 +35,6 @@ class SettingsEdit extends Component 'giorni_giacenza_prioritari' => 'required|integer|min:1|max:730', 'giorni_per_smarrito' => 'required|integer|min:30|max:365', 'home_limit_list' => 'required|integer|min:1|max:100', - 'assignment_link_ttl_months' => 'required|integer|min:1|max:24', 'pdf_viewer_show_download' => 'required|boolean', 'audit_retention_days' => 'required|integer|min:30|max:3650', ]; @@ -54,7 +51,6 @@ class SettingsEdit extends Component 'giorni_giacenza_prioritari' => $this->giorni_giacenza_prioritari, 'giorni_per_smarrito' => $this->giorni_per_smarrito, 'home_limit_list' => $this->home_limit_list, - 'assignment_link_ttl_hours' => $this->assignment_link_ttl_months, 'pdf_viewer_show_download' => $this->pdf_viewer_show_download, 'audit_retention_days' => $this->audit_retention_days, ]); diff --git a/app/Livewire/Territori/TerritorioShow.php b/app/Livewire/Territori/TerritorioShow.php index 9cecc9f..b0dc808 100644 --- a/app/Livewire/Territori/TerritorioShow.php +++ b/app/Livewire/Territori/TerritorioShow.php @@ -5,7 +5,6 @@ namespace App\Livewire\Territori; use Livewire\Component; use App\Models\Territorio; use App\Models\Assegnazione; -use App\Models\Setting; class TerritorioShow extends Component { @@ -26,7 +25,7 @@ class TerritorioShow extends Component return view('livewire.territori.territorio-show', [ 'activeAssignment' => $this->territorio->assegnazioneCorrente, - 'assignmentLinkTtlMonths' => (int) Setting::getValue('assignment_link_ttl_hours', 1), + 'assignmentScadenza' => $this->territorio->assegnazioneCorrente?->data_consegna_presunta, 'assegnazioniPerAnno' => $assegnazioni, ]); } diff --git a/resources/views/components/layouts/app.blade.php b/resources/views/components/layouts/app.blade.php index 8a45775..57ca7ac 100644 --- a/resources/views/components/layouts/app.blade.php +++ b/resources/views/components/layouts/app.blade.php @@ -160,6 +160,16 @@ @endcan + + {{-- Utente (solo mobile: su desktop è nell'header) --}} + + + + {{ auth()->user()->name }} + {{ ucfirst(auth()->user()->roles->first()?->name ?? 'utente') }} + + diff --git a/resources/views/livewire/assegnazioni/assegna.blade.php b/resources/views/livewire/assegnazioni/assegna.blade.php index 6c69e06..65dbd7c 100644 --- a/resources/views/livewire/assegnazioni/assegna.blade.php +++ b/resources/views/livewire/assegnazioni/assegna.blade.php @@ -99,14 +99,25 @@

Territori Assegnati ({{ $assegnazioniAperte->count() }})

-

Link PDF · stato invio · link valido {{ $linkTtlMonths }} {{ $linkTtlMonths === 1 ? 'mese' : 'mesi' }}

+

Link PDF · stato invio · il link scade alla soglia rientro ({{ $sogliaRientro }} giorni)

+ + {{-- Ricerca rapida: territorio, numero, zona, proclamatore in un solo campo --}} +
+
+ + +
+
+
- @foreach($assegnazioniAperte as $a) + @forelse($assegnazioniAperteVisibili as $a) @php $pdfUrl = $a->shortPdfUrl(); - $linkScaduto = ! auth()->check() && $a->assigned_at->copy()->addMonths($linkTtlMonths)->isPast(); + $linkScaduto = ! auth()->check() && $a->data_consegna_presunta && $a->data_consegna_presunta->isPast(); @endphp
{{-- Testata riga --}} @@ -168,7 +179,9 @@

Nessun PDF disponibile

@endif
- @endforeach + @empty +
Nessun risultato per "{{ $linkSearch }}".
+ @endforelse
@endif diff --git a/resources/views/livewire/campagne/campagna-show.blade.php b/resources/views/livewire/campagne/campagna-show.blade.php index 219ba80..efa5f5e 100644 --- a/resources/views/livewire/campagne/campagna-show.blade.php +++ b/resources/views/livewire/campagne/campagna-show.blade.php @@ -50,7 +50,7 @@

Territori Conteggiati

- +
@@ -63,11 +63,11 @@ @forelse($conteggiate as $a) - - - - - + + + + + @empty diff --git a/resources/views/livewire/proclamatori/proclamatore-show.blade.php b/resources/views/livewire/proclamatori/proclamatore-show.blade.php index eb2bc1e..218f3f0 100644 --- a/resources/views/livewire/proclamatori/proclamatore-show.blade.php +++ b/resources/views/livewire/proclamatori/proclamatore-show.blade.php @@ -44,7 +44,7 @@

Anno Teocratico {{ $annoLabel }}

-
Territorio
N° {{ $a->territorio?->numero }}{{ $a->proclamatore?->nome_completo ?? 'N/A' }}{{ $a->assigned_at->format('d/m/Y') }}{{ $a->returned_at?->format('d/m/Y') }}{{ $a->giorni }}N° {{ $a->territorio?->numero }}{{ $a->proclamatore?->nome_completo ?? 'N/A' }}{{ $a->assigned_at->format('d/m/Y') }}{{ $a->returned_at?->format('d/m/Y') }}{{ $a->giorni }}
+
@@ -57,21 +57,21 @@ @foreach($assegnazioni as $assegnazione) - - - + - - +
Territorio
+ {{ $assegnazione->territorio?->numero ?? 'N/A' }} {{ $assegnazione->assigned_at->format('d/m/Y') }} + {{ $assegnazione->assigned_at->format('d/m/Y') }} @if($assegnazione->returned_at) {{ $assegnazione->returned_at->format('d/m/Y') }} @else In corso @endif {{ $assegnazione->giorni }} + {{ $assegnazione->giorni }} @if($assegnazione->counted_in_campaign) {{ $assegnazione->campagna?->descrizione }} @else diff --git a/resources/views/livewire/settings/settings-edit.blade.php b/resources/views/livewire/settings/settings-edit.blade.php index 4eac4e4..cb92bbd 100644 --- a/resources/views/livewire/settings/settings-edit.blade.php +++ b/resources/views/livewire/settings/settings-edit.blade.php @@ -44,7 +44,7 @@
-

Dopo quanti giorni dall'assegnazione un territorio appare nella lista "da rientrare".

+

Dopo quanti giorni dall'assegnazione un territorio appare nella lista "da rientrare". Determina anche la scadenza del link PDF condivisibile.

@error('giorni_per_smarrito')

{{ $message }}

@enderror
@@ -56,13 +56,6 @@ @error('home_limit_list')

{{ $message }}

@enderror -
- -

Durata del link temporaneo condivisibile per il PDF dell'assegnazione attiva.

- - @error('assignment_link_ttl_months')

{{ $message }}

@enderror -
-