++ fix
This commit is contained in:
46
HANDOFF.md
46
HANDOFF.md
@@ -177,9 +177,35 @@ larghezza supera i 640px → torna la tabella normale (per questo landscape "non
|
|||||||
problemi"). Convenzioni: ogni `<td>` dati ha `data-label="..."`; la cella azioni
|
problemi"). Convenzioni: ogni `<td>` dati ha `data-label="..."`; la cella azioni
|
||||||
ha classe `cell-actions` (niente label, occupa la riga a piena larghezza); le
|
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
|
celle `colspan` (stato vuoto, form di modifica utente inline) restano `block` a
|
||||||
piena larghezza. Applicata a: territori, proclamatori, campagne, registro,
|
piena larghezza. Applicata a tutte le liste e sottopagine con tabelle: territori,
|
||||||
utenti, audit-log e i due cestini. La pagina *Assegnazioni* era già ottimizzata e
|
proclamatori, campagne, registro, utenti, audit-log, i due cestini, le tabelle
|
||||||
non è stata toccata.
|
"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"
|
### 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ò
|
ogni utente loggato (nel gruppo `auth`, nessun permesso): l'utente corrente può
|
||||||
modificare il proprio nome/cognome ed email (`updateProfile`) e cambiare la
|
modificare il proprio nome/cognome ed email (`updateProfile`) e cambiare la
|
||||||
password (`updatePassword`, con verifica della password attuale via regola
|
password (`updatePassword`, con verifica della password attuale via regola
|
||||||
`current_password`; il cast `hashed` cifra al salvataggio). Nell'header il
|
`current_password`; il cast `hashed` cifra al salvataggio). Dopo il salvataggio
|
||||||
blocco utente è un link a questa pagina, con nome in evidenza ed
|
dei dati `updateProfile` fa `redirect(navigate:true)` sulla stessa pagina, così
|
||||||
`email · qualifica` sotto. Non esiste un campo "username" né "cognome"
|
header (nel layout, fuori dal componente) e card mostrano subito i nuovi valori.
|
||||||
separato: `name` è il nome completo (etichettato "Nome e cognome") e l'email fa
|
Il link al profilo è nell'header su desktop e, su mobile, in fondo alla sidebar
|
||||||
da identificativo. La qualifica (ruolo) non è modificabile dal profilo — resta
|
(`lg:hidden`, dopo un separatore) — sull'header è `hidden sm:flex`. Non esiste
|
||||||
in gestione all'admin.
|
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
|
- **Viewer PDF pubblico**: oltre a territorio/proclamatore/data mostra ora
|
||||||
*giorni assegnato*, *consegna prevista* e *scadenza*. Sono attributi calcolati
|
*giorni assegnato*, *consegna prevista* e *scadenza*. Sono attributi calcolati
|
||||||
su `Assegnazione` (`data_consegna_presunta`, `giorni_alla_scadenza`) basati
|
su `Assegnazione` (`data_consegna_presunta`, `giorni_alla_scadenza`) basati
|
||||||
|
|||||||
@@ -65,9 +65,11 @@ class AssignmentPdfController extends Controller
|
|||||||
return null;
|
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', [
|
return view('assignments.link-scaduto', [
|
||||||
'numero' => $assignment->territorio?->numero,
|
'numero' => $assignment->territorio?->numero,
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -15,10 +15,11 @@ class ShortPdfLinkController extends Controller
|
|||||||
abort_unless($assignment->is_aperta, 403);
|
abort_unless($assignment->is_aperta, 403);
|
||||||
abort_unless($assignment->territorio?->pdf_path, 404);
|
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()) {
|
if (! auth()->check()) {
|
||||||
$ttlMonths = max(1, (int) \App\Models\Setting::getValue('assignment_link_ttl_hours', 1));
|
$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', [
|
return view('assignments.link-scaduto', [
|
||||||
'numero' => $assignment->territorio?->numero,
|
'numero' => $assignment->territorio?->numero,
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ class Assegna extends Component
|
|||||||
public ?int $proclamatore_id = null;
|
public ?int $proclamatore_id = null;
|
||||||
public string $assigned_at = '';
|
public string $assigned_at = '';
|
||||||
public string $territorioSearch = '';
|
public string $territorioSearch = '';
|
||||||
|
public string $linkSearch = '';
|
||||||
|
|
||||||
// Optional pre-selection from parent context
|
// Optional pre-selection from parent context
|
||||||
public ?int $preselectedTerritorioId = null;
|
public ?int $preselectedTerritorioId = null;
|
||||||
@@ -129,13 +130,31 @@ class Assegna extends Component
|
|||||||
->get()
|
->get()
|
||||||
->sortBy(fn($a) => (int) $a->territorio?->numero);
|
->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', [
|
return view('livewire.assegnazioni.assegna', [
|
||||||
'territoriDisponibili' => $territoriDisponibili,
|
'territoriDisponibili' => $territoriDisponibili,
|
||||||
'proclamatoriAttivi' => $proclamatoriAttivi,
|
'proclamatoriAttivi' => $proclamatoriAttivi,
|
||||||
'assegnazioniAperte' => $assegnazioniAperte,
|
'assegnazioniAperte' => $assegnazioniAperte,
|
||||||
'linkTtlMonths' => $linkTtlMonths,
|
'assegnazioniAperteVisibili' => $assegnazioniAperteVisibili,
|
||||||
|
'sogliaRientro' => $sogliaRientro,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class Profile extends Component
|
|||||||
$this->email = $user->email;
|
$this->email = $user->email;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function updateProfile(): void
|
public function updateProfile()
|
||||||
{
|
{
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
|
|
||||||
@@ -36,6 +36,10 @@ class Profile extends Component
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
session()->flash('profile_success', 'Profilo aggiornato con successo.');
|
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
|
public function updatePassword(): void
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ class SettingsEdit extends Component
|
|||||||
public int $giorni_giacenza_prioritari = 180;
|
public int $giorni_giacenza_prioritari = 180;
|
||||||
public int $giorni_per_smarrito = 120;
|
public int $giorni_per_smarrito = 120;
|
||||||
public int $home_limit_list = 10;
|
public int $home_limit_list = 10;
|
||||||
public int $assignment_link_ttl_months = 1;
|
|
||||||
public bool $pdf_viewer_show_download = true;
|
public bool $pdf_viewer_show_download = true;
|
||||||
public int $audit_retention_days = 365;
|
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_giacenza_prioritari = $settings->giorni_giacenza_prioritari ?? 180;
|
||||||
$this->giorni_per_smarrito = $settings->giorni_per_smarrito ?? 120;
|
$this->giorni_per_smarrito = $settings->giorni_per_smarrito ?? 120;
|
||||||
$this->home_limit_list = $settings->home_limit_list ?? 10;
|
$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->pdf_viewer_show_download = $settings->pdf_viewer_show_download ?? true;
|
||||||
$this->audit_retention_days = $settings->audit_retention_days ?? 365;
|
$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_giacenza_prioritari' => 'required|integer|min:1|max:730',
|
||||||
'giorni_per_smarrito' => 'required|integer|min:30|max:365',
|
'giorni_per_smarrito' => 'required|integer|min:30|max:365',
|
||||||
'home_limit_list' => 'required|integer|min:1|max:100',
|
'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',
|
'pdf_viewer_show_download' => 'required|boolean',
|
||||||
'audit_retention_days' => 'required|integer|min:30|max:3650',
|
'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_giacenza_prioritari' => $this->giorni_giacenza_prioritari,
|
||||||
'giorni_per_smarrito' => $this->giorni_per_smarrito,
|
'giorni_per_smarrito' => $this->giorni_per_smarrito,
|
||||||
'home_limit_list' => $this->home_limit_list,
|
'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,
|
'pdf_viewer_show_download' => $this->pdf_viewer_show_download,
|
||||||
'audit_retention_days' => $this->audit_retention_days,
|
'audit_retention_days' => $this->audit_retention_days,
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ namespace App\Livewire\Territori;
|
|||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
use App\Models\Territorio;
|
use App\Models\Territorio;
|
||||||
use App\Models\Assegnazione;
|
use App\Models\Assegnazione;
|
||||||
use App\Models\Setting;
|
|
||||||
|
|
||||||
class TerritorioShow extends Component
|
class TerritorioShow extends Component
|
||||||
{
|
{
|
||||||
@@ -26,7 +25,7 @@ class TerritorioShow extends Component
|
|||||||
|
|
||||||
return view('livewire.territori.territorio-show', [
|
return view('livewire.territori.territorio-show', [
|
||||||
'activeAssignment' => $this->territorio->assegnazioneCorrente,
|
'activeAssignment' => $this->territorio->assegnazioneCorrente,
|
||||||
'assignmentLinkTtlMonths' => (int) Setting::getValue('assignment_link_ttl_hours', 1),
|
'assignmentScadenza' => $this->territorio->assegnazioneCorrente?->data_consegna_presunta,
|
||||||
'assegnazioniPerAnno' => $assegnazioni,
|
'assegnazioniPerAnno' => $assegnazioni,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -160,6 +160,16 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@endcan
|
@endcan
|
||||||
|
|
||||||
|
{{-- Utente (solo mobile: su desktop è nell'header) --}}
|
||||||
|
<a href="{{ route('profile') }}"
|
||||||
|
class="lg:hidden flex items-center gap-3 px-3 py-2.5 mt-4 pt-4 border-t border-gray-200 text-sm font-medium rounded-lg transition-all duration-150 {{ request()->routeIs('profile') ? 'sidebar-active' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900' }}">
|
||||||
|
<svg class="h-5 w-5 flex-none" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/></svg>
|
||||||
|
<span class="flex flex-col leading-tight min-w-0">
|
||||||
|
<span class="truncate">{{ auth()->user()->name }}</span>
|
||||||
|
<span class="text-xs text-gray-400">{{ ucfirst(auth()->user()->roles->first()?->name ?? 'utente') }}</span>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
</nav>
|
</nav>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
|
|||||||
@@ -99,14 +99,25 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h3 class="text-sm font-semibold" style="color:#3730a3">Territori Assegnati ({{ $assegnazioniAperte->count() }})</h3>
|
<h3 class="text-sm font-semibold" style="color:#3730a3">Territori Assegnati ({{ $assegnazioniAperte->count() }})</h3>
|
||||||
<p class="text-xs" style="color:#4f46e5">Link PDF · stato invio · link valido {{ $linkTtlMonths }} {{ $linkTtlMonths === 1 ? 'mese' : 'mesi' }}</p>
|
<p class="text-xs" style="color:#4f46e5">Link PDF · stato invio · il link scade alla soglia rientro ({{ $sogliaRientro }} giorni)</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- Ricerca rapida: territorio, numero, zona, proclamatore in un solo campo --}}
|
||||||
|
<div class="px-5 py-3 border-b border-gray-100" style="background:#fafafa">
|
||||||
|
<div class="relative">
|
||||||
|
<svg class="h-4 w-4 absolute left-3 top-1/2 -translate-y-1/2 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/></svg>
|
||||||
|
<input wire:model.live.debounce.300ms="linkSearch" type="text"
|
||||||
|
placeholder="Cerca per territorio, numero, zona o proclamatore..."
|
||||||
|
class="block w-full rounded-lg border-gray-300 text-sm pl-9 focus:ring-indigo-500 focus:border-indigo-500">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="divide-y divide-gray-100">
|
<div class="divide-y divide-gray-100">
|
||||||
@foreach($assegnazioniAperte as $a)
|
@forelse($assegnazioniAperteVisibili as $a)
|
||||||
@php
|
@php
|
||||||
$pdfUrl = $a->shortPdfUrl();
|
$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
|
@endphp
|
||||||
<div class="px-5 py-4 hover:bg-indigo-50/30 transition-colors">
|
<div class="px-5 py-4 hover:bg-indigo-50/30 transition-colors">
|
||||||
{{-- Testata riga --}}
|
{{-- Testata riga --}}
|
||||||
@@ -168,7 +179,9 @@
|
|||||||
<p class="mt-2 text-xs text-gray-300">Nessun PDF disponibile</p>
|
<p class="mt-2 text-xs text-gray-300">Nessun PDF disponibile</p>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
@empty
|
||||||
|
<div class="px-5 py-8 text-center text-sm text-gray-400">Nessun risultato per "{{ $linkSearch }}".</div>
|
||||||
|
@endforelse
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
<h3 class="text-sm font-semibold text-gray-700">Territori Conteggiati</h3>
|
<h3 class="text-sm font-semibold text-gray-700">Territori Conteggiati</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
<table class="min-w-full divide-y divide-gray-200 text-sm">
|
<table class="min-w-full divide-y divide-gray-200 text-sm table-cards">
|
||||||
<thead class="bg-gray-50">
|
<thead class="bg-gray-50">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500">Territorio</th>
|
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500">Territorio</th>
|
||||||
@@ -63,11 +63,11 @@
|
|||||||
<tbody class="divide-y divide-gray-100">
|
<tbody class="divide-y divide-gray-100">
|
||||||
@forelse($conteggiate as $a)
|
@forelse($conteggiate as $a)
|
||||||
<tr>
|
<tr>
|
||||||
<td class="px-4 py-2"><a href="{{ route('territori.show', $a->territorio_id) }}" class="text-indigo-600 hover:underline">N° {{ $a->territorio?->numero }}</a></td>
|
<td data-label="Territorio" class="px-4 py-2"><a href="{{ route('territori.show', $a->territorio_id) }}" class="text-indigo-600 hover:underline">N° {{ $a->territorio?->numero }}</a></td>
|
||||||
<td class="px-4 py-2">{{ $a->proclamatore?->nome_completo ?? 'N/A' }}</td>
|
<td data-label="Proclamatore" class="px-4 py-2">{{ $a->proclamatore?->nome_completo ?? 'N/A' }}</td>
|
||||||
<td class="px-4 py-2">{{ $a->assigned_at->format('d/m/Y') }}</td>
|
<td data-label="Assegnato" class="px-4 py-2">{{ $a->assigned_at->format('d/m/Y') }}</td>
|
||||||
<td class="px-4 py-2">{{ $a->returned_at?->format('d/m/Y') }}</td>
|
<td data-label="Rientrato" class="px-4 py-2">{{ $a->returned_at?->format('d/m/Y') }}</td>
|
||||||
<td class="px-4 py-2">{{ $a->giorni }}</td>
|
<td data-label="Giorni" class="px-4 py-2">{{ $a->giorni }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@empty
|
@empty
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
<div class="mb-6">
|
<div class="mb-6">
|
||||||
<h4 class="text-sm font-semibold text-indigo-600 mb-2">Anno Teocratico {{ $annoLabel }}</h4>
|
<h4 class="text-sm font-semibold text-indigo-600 mb-2">Anno Teocratico {{ $annoLabel }}</h4>
|
||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
<table class="min-w-full divide-y divide-gray-200 text-sm">
|
<table class="min-w-full divide-y divide-gray-200 text-sm table-cards">
|
||||||
<thead class="bg-gray-50">
|
<thead class="bg-gray-50">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="px-3 py-2 text-left text-xs font-medium text-gray-500">Territorio</th>
|
<th class="px-3 py-2 text-left text-xs font-medium text-gray-500">Territorio</th>
|
||||||
@@ -57,21 +57,21 @@
|
|||||||
<tbody class="divide-y divide-gray-100">
|
<tbody class="divide-y divide-gray-100">
|
||||||
@foreach($assegnazioni as $assegnazione)
|
@foreach($assegnazioni as $assegnazione)
|
||||||
<tr>
|
<tr>
|
||||||
<td class="px-3 py-2">
|
<td data-label="Territorio" class="px-3 py-2">
|
||||||
<a href="{{ route('territori.show', $assegnazione->territorio_id) }}" class="text-indigo-600 hover:underline">
|
<a href="{{ route('territori.show', $assegnazione->territorio_id) }}" class="text-indigo-600 hover:underline">
|
||||||
{{ $assegnazione->territorio?->numero ?? 'N/A' }}
|
{{ $assegnazione->territorio?->numero ?? 'N/A' }}
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-3 py-2">{{ $assegnazione->assigned_at->format('d/m/Y') }}</td>
|
<td data-label="Assegnato" class="px-3 py-2">{{ $assegnazione->assigned_at->format('d/m/Y') }}</td>
|
||||||
<td class="px-3 py-2">
|
<td data-label="Rientrato" class="px-3 py-2">
|
||||||
@if($assegnazione->returned_at)
|
@if($assegnazione->returned_at)
|
||||||
{{ $assegnazione->returned_at->format('d/m/Y') }}
|
{{ $assegnazione->returned_at->format('d/m/Y') }}
|
||||||
@else
|
@else
|
||||||
<span class="text-amber-600 font-medium">In corso</span>
|
<span class="text-amber-600 font-medium">In corso</span>
|
||||||
@endif
|
@endif
|
||||||
</td>
|
</td>
|
||||||
<td class="px-3 py-2">{{ $assegnazione->giorni }}</td>
|
<td data-label="Giorni" class="px-3 py-2">{{ $assegnazione->giorni }}</td>
|
||||||
<td class="px-3 py-2">
|
<td data-label="Campagna" class="px-3 py-2">
|
||||||
@if($assegnazione->counted_in_campaign)
|
@if($assegnazione->counted_in_campaign)
|
||||||
<span class="text-green-600">{{ $assegnazione->campagna?->descrizione }}</span>
|
<span class="text-green-600">{{ $assegnazione->campagna?->descrizione }}</span>
|
||||||
@else
|
@else
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label for="giorni_per_smarrito" class="block text-sm font-medium text-gray-700">Soglia Rientro (giorni)</label>
|
<label for="giorni_per_smarrito" class="block text-sm font-medium text-gray-700">Soglia Rientro (giorni)</label>
|
||||||
<p class="text-xs text-gray-500 mb-1">Dopo quanti giorni dall'assegnazione un territorio appare nella lista "da rientrare".</p>
|
<p class="text-xs text-gray-500 mb-1">Dopo quanti giorni dall'assegnazione un territorio appare nella lista "da rientrare". Determina anche la scadenza del link PDF condivisibile.</p>
|
||||||
<input wire:model="giorni_per_smarrito" type="number" min="30" max="365" id="giorni_per_smarrito" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 text-sm">
|
<input wire:model="giorni_per_smarrito" type="number" min="30" max="365" id="giorni_per_smarrito" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 text-sm">
|
||||||
@error('giorni_per_smarrito') <p class="text-red-500 text-xs mt-1">{{ $message }}</p> @enderror
|
@error('giorni_per_smarrito') <p class="text-red-500 text-xs mt-1">{{ $message }}</p> @enderror
|
||||||
</div>
|
</div>
|
||||||
@@ -56,13 +56,6 @@
|
|||||||
@error('home_limit_list') <p class="text-red-500 text-xs mt-1">{{ $message }}</p> @enderror
|
@error('home_limit_list') <p class="text-red-500 text-xs mt-1">{{ $message }}</p> @enderror
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
|
||||||
<label for="assignment_link_ttl_months" class="block text-sm font-medium text-gray-700">Validità link PDF assegnazione (mesi)</label>
|
|
||||||
<p class="text-xs text-gray-500 mb-1">Durata del link temporaneo condivisibile per il PDF dell'assegnazione attiva.</p>
|
|
||||||
<input wire:model="assignment_link_ttl_months" type="number" min="1" max="24" id="assignment_link_ttl_months" class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:ring-indigo-500 focus:border-indigo-500 text-sm">
|
|
||||||
@error('assignment_link_ttl_months') <p class="text-red-500 text-xs mt-1">{{ $message }}</p> @enderror
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label class="flex items-center gap-2 text-sm font-medium text-gray-700 cursor-pointer">
|
<label class="flex items-center gap-2 text-sm font-medium text-gray-700 cursor-pointer">
|
||||||
<input wire:model="pdf_viewer_show_download" type="checkbox" value="1" class="rounded border-gray-300 text-indigo-600 focus:ring-indigo-500">
|
<input wire:model="pdf_viewer_show_download" type="checkbox" value="1" class="rounded border-gray-300 text-indigo-600 focus:ring-indigo-500">
|
||||||
|
|||||||
@@ -217,7 +217,7 @@
|
|||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<div class="mb-2 text-sm font-medium text-gray-800">Riepilogo file non associati o problematici</div>
|
<div class="mb-2 text-sm font-medium text-gray-800">Riepilogo file non associati o problematici</div>
|
||||||
<div class="overflow-x-auto rounded-lg border border-gray-200 bg-white">
|
<div class="overflow-x-auto rounded-lg border border-gray-200 bg-white">
|
||||||
<table class="min-w-full divide-y divide-gray-200 text-sm">
|
<table class="min-w-full divide-y divide-gray-200 text-sm table-cards">
|
||||||
<thead class="bg-gray-50">
|
<thead class="bg-gray-50">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="px-3 py-2 text-left text-xs font-medium uppercase text-gray-500">File</th>
|
<th class="px-3 py-2 text-left text-xs font-medium uppercase text-gray-500">File</th>
|
||||||
@@ -228,9 +228,9 @@
|
|||||||
<tbody class="divide-y divide-gray-100">
|
<tbody class="divide-y divide-gray-100">
|
||||||
@foreach($pdfImportIssues as $issue)
|
@foreach($pdfImportIssues as $issue)
|
||||||
<tr>
|
<tr>
|
||||||
<td class="px-3 py-2 text-gray-900">{{ $issue['file'] ?? '-' }}</td>
|
<td data-label="File" class="px-3 py-2 text-gray-900">{{ $issue['file'] ?? '-' }}</td>
|
||||||
<td class="px-3 py-2 text-gray-600">{{ $issue['message'] ?? '-' }}</td>
|
<td data-label="Motivo" class="px-3 py-2 text-gray-600">{{ $issue['message'] ?? '-' }}</td>
|
||||||
<td class="px-3 py-2 text-gray-600">{{ !empty($issue['matched_numbers']) ? implode(', ', $issue['matched_numbers']) : '-' }}</td>
|
<td data-label="Territori rilevati" class="px-3 py-2 text-gray-600">{{ !empty($issue['matched_numbers']) ? implode(', ', $issue['matched_numbers']) : '-' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
</tbody>
|
</tbody>
|
||||||
@@ -317,7 +317,7 @@
|
|||||||
|
|
||||||
@if(!empty($importIssues))
|
@if(!empty($importIssues))
|
||||||
<div class="mt-2" style="max-height:260px;overflow:auto;border:1px solid #e5e7eb;border-radius:10px;">
|
<div class="mt-2" style="max-height:260px;overflow:auto;border:1px solid #e5e7eb;border-radius:10px;">
|
||||||
<table style="width:100%;border-collapse:collapse;font-size:13px;">
|
<table class="table-cards" style="width:100%;border-collapse:collapse;font-size:13px;">
|
||||||
<thead style="background:#f9fafb;position:sticky;top:0;">
|
<thead style="background:#f9fafb;position:sticky;top:0;">
|
||||||
<tr>
|
<tr>
|
||||||
<th style="text-align:left;padding:8px;border-bottom:1px solid #e5e7eb;">Entità</th>
|
<th style="text-align:left;padding:8px;border-bottom:1px solid #e5e7eb;">Entità</th>
|
||||||
@@ -328,9 +328,9 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
@foreach($importIssues as $issue)
|
@foreach($importIssues as $issue)
|
||||||
<tr>
|
<tr>
|
||||||
<td style="padding:8px;border-bottom:1px solid #f3f4f6;">{{ $issue['entity'] }}</td>
|
<td data-label="Entità" style="padding:8px;border-bottom:1px solid #f3f4f6;">{{ $issue['entity'] }}</td>
|
||||||
<td style="padding:8px;border-bottom:1px solid #f3f4f6;">{{ $issue['legacy_id'] }}</td>
|
<td data-label="Legacy ID" style="padding:8px;border-bottom:1px solid #f3f4f6;">{{ $issue['legacy_id'] }}</td>
|
||||||
<td style="padding:8px;border-bottom:1px solid #f3f4f6;">{{ $issue['reason'] }}</td>
|
<td data-label="Motivo" style="padding:8px;border-bottom:1px solid #f3f4f6;">{{ $issue['reason'] }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -106,7 +106,7 @@
|
|||||||
<div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
<div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
||||||
<div>
|
<div>
|
||||||
<div class="text-sm font-medium text-indigo-900">Link PDF temporaneo</div>
|
<div class="text-sm font-medium text-indigo-900">Link PDF temporaneo</div>
|
||||||
<div class="mt-1 text-xs text-indigo-700">Valido per {{ $assignmentLinkTtlMonths }} {{ $assignmentLinkTtlMonths === 1 ? 'mese' : 'mesi' }} o fino al rientro del territorio.</div>
|
<div class="mt-1 text-xs text-indigo-700">Valido fino al {{ optional($assignmentScadenza)->format('d/m/Y') ?? '—' }} (soglia rientro) o fino al rientro del territorio.</div>
|
||||||
</div>
|
</div>
|
||||||
<a href="{{ $temporaryPdfUrl }}" target="_blank" rel="noopener noreferrer" class="inline-flex items-center justify-center rounded-lg border border-indigo-200 bg-white px-3 py-2 text-sm font-medium text-indigo-700 hover:bg-indigo-100 transition">Apri viewer</a>
|
<a href="{{ $temporaryPdfUrl }}" target="_blank" rel="noopener noreferrer" class="inline-flex items-center justify-center rounded-lg border border-indigo-200 bg-white px-3 py-2 text-sm font-medium text-indigo-700 hover:bg-indigo-100 transition">Apri viewer</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -151,7 +151,7 @@
|
|||||||
<div class="mb-6">
|
<div class="mb-6">
|
||||||
<h4 class="text-sm font-semibold text-indigo-600 mb-2">Anno Teocratico {{ $annoLabel }}</h4>
|
<h4 class="text-sm font-semibold text-indigo-600 mb-2">Anno Teocratico {{ $annoLabel }}</h4>
|
||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
<table class="min-w-full divide-y divide-gray-200 text-sm">
|
<table class="min-w-full divide-y divide-gray-200 text-sm table-cards">
|
||||||
<thead class="bg-gray-50">
|
<thead class="bg-gray-50">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="px-3 py-2 text-left text-xs font-medium text-gray-500">Proclamatore</th>
|
<th class="px-3 py-2 text-left text-xs font-medium text-gray-500">Proclamatore</th>
|
||||||
@@ -164,17 +164,17 @@
|
|||||||
<tbody class="divide-y divide-gray-100">
|
<tbody class="divide-y divide-gray-100">
|
||||||
@foreach($assegnazioni as $assegnazione)
|
@foreach($assegnazioni as $assegnazione)
|
||||||
<tr>
|
<tr>
|
||||||
<td class="px-3 py-2">{{ $assegnazione->proclamatore?->nome_completo ?? 'N/A' }}</td>
|
<td data-label="Proclamatore" class="px-3 py-2">{{ $assegnazione->proclamatore?->nome_completo ?? 'N/A' }}</td>
|
||||||
<td class="px-3 py-2">{{ $assegnazione->assigned_at->format('d/m/Y') }}</td>
|
<td data-label="Assegnato" class="px-3 py-2">{{ $assegnazione->assigned_at->format('d/m/Y') }}</td>
|
||||||
<td class="px-3 py-2">
|
<td data-label="Rientrato" class="px-3 py-2">
|
||||||
@if($assegnazione->returned_at)
|
@if($assegnazione->returned_at)
|
||||||
{{ $assegnazione->returned_at->format('d/m/Y') }}
|
{{ $assegnazione->returned_at->format('d/m/Y') }}
|
||||||
@else
|
@else
|
||||||
<span class="text-amber-600 font-medium">In corso</span>
|
<span class="text-amber-600 font-medium">In corso</span>
|
||||||
@endif
|
@endif
|
||||||
</td>
|
</td>
|
||||||
<td class="px-3 py-2">{{ $assegnazione->giorni }}</td>
|
<td data-label="Giorni" class="px-3 py-2">{{ $assegnazione->giorni }}</td>
|
||||||
<td class="px-3 py-2">
|
<td data-label="Campagna" class="px-3 py-2">
|
||||||
@if($assegnazione->counted_in_campaign)
|
@if($assegnazione->counted_in_campaign)
|
||||||
<span class="text-green-600">Sì — {{ $assegnazione->campagna?->descrizione }}</span>
|
<span class="text-green-600">Sì — {{ $assegnazione->campagna?->descrizione }}</span>
|
||||||
@elseif($assegnazione->counted_in_campaign === false)
|
@elseif($assegnazione->counted_in_campaign === false)
|
||||||
|
|||||||
Reference in New Issue
Block a user