++ gruppi: le azioni del sorvegliante non finiscono piu' in 403; priorita' e filtri nel pacchetto; nome del sorvegliante
- LimitaSorvegliante: la rotta delle azioni di Livewire 3.7 si chiama "default.livewire.update"; con 'livewire.*' ogni clic era un 403. - Territorio::ordinaPerPriorita(): la regola di "Da assegnare" della Home in un metodo solo, usato dalla Home, dall'aggiunta al pacchetto e da "Il mio gruppo". - Aggiunta al pacchetto: ricerca, zona, tipologia, solo prioritari, "Seleziona tutti quelli mostrati", badge e giorni di fermo. - Il mio gruppo: da dare in ordine di priorita' poi i gia' dati; filtri stato, zona, tipologia, solo prioritari; sotto il titolo nome e cognome del sorvegliante. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -49,27 +49,65 @@
|
||||
@endforelse
|
||||
</ul>
|
||||
|
||||
{{-- Assegnazione in blocco: si spuntano i territori in reparto --}}
|
||||
<div class="border-t border-gray-100 bg-gray-50 p-4" x-data="elencoCercabile">
|
||||
{{-- Assegnazione in blocco: si spuntano i territori in reparto, in
|
||||
ordine di priorità (come "Da assegnare" nella Home), filtrabili. --}}
|
||||
<div class="border-t border-gray-100 bg-gray-50 p-4">
|
||||
<h3 class="text-sm font-semibold text-gray-700 mb-2">Aggiungi territori al pacchetto</h3>
|
||||
@if($candidatiTerritori->isEmpty())
|
||||
@if($totaleCandidati === 0)
|
||||
<p class="text-sm text-gray-500">Non ci sono territori in reparto da aggiungere.</p>
|
||||
@else
|
||||
<input x-model="q" type="search" inputmode="search" autocomplete="off" aria-label="Filtra i territori in reparto"
|
||||
placeholder="Filtra per numero o zona…"
|
||||
class="mb-2 block w-full rounded-lg border-gray-300 text-base sm:text-sm focus:ring-indigo-500 focus:border-indigo-500">
|
||||
<div class="max-h-72 overflow-y-auto rounded-lg border border-gray-200 bg-white divide-y divide-gray-100">
|
||||
@foreach($candidatiTerritori as $c)
|
||||
<label class="flex items-center gap-3 px-3 py-2.5 text-sm cursor-pointer hover:bg-indigo-50/40"
|
||||
data-cerca="{{ \Illuminate\Support\Str::lower(\Illuminate\Support\Str::ascii($c->numero . ' ' . $c->zona?->nome)) }}"
|
||||
x-show="corrisponde($el.dataset.cerca)" wire:key="candidato-t-{{ $c->id }}">
|
||||
<input type="checkbox" value="{{ $c->id }}" wire:model="nuoviTerritori" class="h-5 w-5 rounded border-gray-300 text-indigo-600">
|
||||
<span><strong>N° {{ $c->numero }}</strong> <span class="text-gray-500">{{ $c->zona?->nome }}</span></span>
|
||||
</label>
|
||||
@endforeach
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-2 mb-2">
|
||||
<input wire:model.live.debounce.300ms="cercaTerritorio" type="search" inputmode="search" autocomplete="off" aria-label="Cerca tra i territori in reparto"
|
||||
placeholder="Numero, zona o tipologia…"
|
||||
class="block w-full rounded-lg border-gray-300 text-base sm:text-sm focus:ring-indigo-500 focus:border-indigo-500">
|
||||
<select wire:model.live="filtroZona" aria-label="Zona"
|
||||
class="block w-full rounded-lg border-gray-300 text-base sm:text-sm focus:ring-indigo-500 focus:border-indigo-500">
|
||||
<option value="">Tutte le zone</option>
|
||||
@foreach($zoneCandidati as $id => $nome)
|
||||
<option value="{{ $id }}">{{ $nome }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<select wire:model.live="filtroTipologia" aria-label="Tipologia"
|
||||
class="block w-full rounded-lg border-gray-300 text-base sm:text-sm focus:ring-indigo-500 focus:border-indigo-500">
|
||||
<option value="">Tutte le tipologie</option>
|
||||
@foreach($tipologieCandidati as $id => $nome)
|
||||
<option value="{{ $id }}">{{ $nome }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<label class="flex items-center gap-2 text-sm text-gray-700 px-1">
|
||||
<input type="checkbox" wire:model.live="soloPrioritari" class="h-5 w-5 rounded border-gray-300 text-indigo-600">
|
||||
Solo prioritari
|
||||
</label>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<div class="mb-2 flex flex-wrap items-center gap-2 text-xs text-gray-500">
|
||||
<span>{{ $candidatiTerritori->count() }} di {{ $totaleCandidati }} in reparto, prima i prioritari e quelli fermi da più tempo</span>
|
||||
@if($candidatiTerritori->isNotEmpty())
|
||||
<x-btn variante="secondary" tono="tenue" dimensione="sm" wire:click="selezionaMostrati">Seleziona tutti quelli mostrati</x-btn>
|
||||
@endif
|
||||
<x-btn variante="ghost" dimensione="sm" wire:click="deselezionaTutti">Deseleziona</x-btn>
|
||||
</div>
|
||||
<div class="max-h-96 overflow-y-auto rounded-lg border border-gray-200 bg-white divide-y divide-gray-100">
|
||||
@forelse($candidatiTerritori as $c)
|
||||
<label class="flex items-center gap-3 px-3 py-2.5 text-sm cursor-pointer hover:bg-indigo-50/40" wire:key="candidato-t-{{ $c->id }}">
|
||||
<input type="checkbox" value="{{ $c->id }}" wire:model="nuoviTerritori" class="h-5 w-5 rounded border-gray-300 text-indigo-600">
|
||||
<span class="min-w-0">
|
||||
<strong>N° {{ $c->numero }}</strong>
|
||||
@if($c->in_priorita)
|
||||
<span class="ml-1 inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide" style="background:#fef3c7;color:#92400e">★ Prioritario</span>
|
||||
@endif
|
||||
<span class="block text-xs text-gray-500">
|
||||
{{ collect([$c->zona?->nome, $c->tipologia?->nome])->filter()->join(' — ') }}
|
||||
@if($c->giacenza_giorni > 0) · fermo da {{ $c->giacenza_giorni }} gg @endif
|
||||
</span>
|
||||
</span>
|
||||
</label>
|
||||
@empty
|
||||
<p class="px-3 py-6 text-center text-sm text-gray-500">Nessun territorio con questi filtri.</p>
|
||||
@endforelse
|
||||
</div>
|
||||
<div class="mt-3 flex flex-wrap items-center gap-3">
|
||||
<x-btn variante="primary" wire:click="aggiungiTerritori">Aggiungi i territori selezionati</x-btn>
|
||||
<span class="text-xs text-gray-500" x-data>Selezionati: <strong x-text="$wire.nuoviTerritori.length">{{ count($nuoviTerritori) }}</strong></span>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@@ -10,11 +10,14 @@
|
||||
@else
|
||||
<div class="mb-5">
|
||||
<h1 class="text-2xl font-bold text-gray-900">Gruppo {{ $gruppo->nome }}</h1>
|
||||
@if($gruppo->sorvegliante)
|
||||
<p class="text-sm text-gray-700 mt-0.5">Sorvegliante: <strong>{{ trim($gruppo->sorvegliante->nome . ' ' . $gruppo->sorvegliante->cognome) }}</strong></p>
|
||||
@endif
|
||||
{{-- In questa vista solo blocchi php…endphp: la forma in linea, se
|
||||
viene prima di un blocco, confonde il compilatore di Blade. --}}
|
||||
@php $daDare = $territori->filter(fn ($t) => ! $t->assegnazioneCorrente)->count(); @endphp
|
||||
@php $daDare = $pacchetto->filter(fn ($t) => ! $t->assegnazioneCorrente)->count(); @endphp
|
||||
<p class="text-sm text-gray-500 mt-1">
|
||||
{{ $territori->count() }} {{ $territori->count() === 1 ? 'territorio' : 'territori' }} nel pacchetto ·
|
||||
{{ $pacchetto->count() }} {{ $pacchetto->count() === 1 ? 'territorio' : 'territori' }} nel pacchetto ·
|
||||
{{ $daDare }} da dare · {{ $membri->count() }} {{ $membri->count() === 1 ? 'membro' : 'membri' }}
|
||||
</p>
|
||||
</div>
|
||||
@@ -29,12 +32,43 @@
|
||||
<symbol id="tm-i-avviso" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/></symbol>
|
||||
</svg>
|
||||
|
||||
<div class="px-4 py-3 border-b border-gray-100 flex flex-wrap items-center justify-between gap-2">
|
||||
<h2 id="titolo-pacchetto" class="text-sm font-semibold text-gray-800">Territori del pacchetto</h2>
|
||||
@if($territori->count() > 5)
|
||||
<input x-model="q" type="search" inputmode="search" autocomplete="off" aria-label="Cerca nel pacchetto"
|
||||
placeholder="Cerca numero, zona o nome…"
|
||||
class="w-full sm:w-64 rounded-lg border-gray-300 text-base sm:text-sm focus:ring-indigo-500 focus:border-indigo-500">
|
||||
<div class="px-4 py-3 border-b border-gray-100 space-y-2">
|
||||
<div class="flex flex-wrap items-center justify-between gap-2">
|
||||
<h2 id="titolo-pacchetto" class="text-sm font-semibold text-gray-800">Territori del pacchetto</h2>
|
||||
@if($pacchetto->count() > 5)
|
||||
<input x-model="q" type="search" inputmode="search" autocomplete="off" aria-label="Cerca nel pacchetto"
|
||||
placeholder="Cerca numero, zona o nome…"
|
||||
class="w-full sm:w-64 rounded-lg border-gray-300 text-base sm:text-sm focus:ring-indigo-500 focus:border-indigo-500">
|
||||
@endif
|
||||
</div>
|
||||
{{-- Filtri; l'ordine è di priorità: prima i prioritari e quelli fermi da più tempo --}}
|
||||
@if($pacchetto->isNotEmpty())
|
||||
<div class="grid grid-cols-2 sm:grid-cols-4 gap-2">
|
||||
<select wire:model.live="filtroStato" aria-label="Stato"
|
||||
class="block w-full rounded-lg border-gray-300 text-base sm:text-sm focus:ring-indigo-500 focus:border-indigo-500">
|
||||
<option value="">Tutti</option>
|
||||
<option value="da_dare">Da dare</option>
|
||||
<option value="dati">Già dati</option>
|
||||
</select>
|
||||
<select wire:model.live="filtroZona" aria-label="Zona"
|
||||
class="block w-full rounded-lg border-gray-300 text-base sm:text-sm focus:ring-indigo-500 focus:border-indigo-500">
|
||||
<option value="">Tutte le zone</option>
|
||||
@foreach($zone as $id => $nome)
|
||||
<option value="{{ $id }}">{{ $nome }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<select wire:model.live="filtroTipologia" aria-label="Tipologia"
|
||||
class="block w-full rounded-lg border-gray-300 text-base sm:text-sm focus:ring-indigo-500 focus:border-indigo-500">
|
||||
<option value="">Tutte le tipologie</option>
|
||||
@foreach($tipologie as $id => $nome)
|
||||
<option value="{{ $id }}">{{ $nome }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<label class="flex items-center gap-2 text-sm text-gray-700 px-1">
|
||||
<input type="checkbox" wire:model.live="soloPrioritari" class="h-5 w-5 rounded border-gray-300 text-indigo-600">
|
||||
Solo prioritari
|
||||
</label>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@@ -47,11 +81,12 @@
|
||||
@endphp
|
||||
<div wire:key="pacchetto-{{ $t->id }}" data-cerca="{{ $cerca }}" x-show="corrisponde($el.dataset.cerca)" class="tm-assegnato">
|
||||
<div class="tm-assegnato-testa">
|
||||
<span><span class="tm-assegnato-numero">N° {{ $t->numero }}</span> @if($t->zona?->nome)<span class="tm-assegnato-zona">{{ $t->zona->nome }}</span>@endif</span>
|
||||
<span><span class="tm-assegnato-numero">N° {{ $t->numero }}</span> @if($t->zona?->nome)<span class="tm-assegnato-zona">{{ $t->zona->nome }}</span>@endif
|
||||
@if($t->in_priorita)<span class="ml-1 inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide" style="background:#fef3c7;color:#92400e">★ Prioritario</span>@endif</span>
|
||||
@if($a)
|
||||
<span class="tm-assegnato-info"><b>{{ $a->proclamatore?->nome_completo }}</b> · dal {{ $a->assigned_at->format('d/m/Y') }} · <span class="tm-assegnato-giorni {{ $a->giorni > 120 ? 'tm-g-tardi' : ($a->giorni > 90 ? 'tm-g-presto' : '') }}">{{ $a->giorni }}g</span></span>
|
||||
@else
|
||||
<span class="tm-assegnato-info"><b>Da dare</b></span>
|
||||
<span class="tm-assegnato-info"><b>Da dare</b>@if($t->tipologia?->nome) · {{ $t->tipologia->nome }}@endif @if($t->giacenza_giorni > 0) · fermo da {{ $t->giacenza_giorni }} gg @endif</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@@ -101,7 +136,9 @@
|
||||
@endif
|
||||
</div>
|
||||
@empty
|
||||
<p class="px-4 py-8 text-center text-sm text-gray-500">Il pacchetto è vuoto: l'amministratore non ha ancora assegnato territori al gruppo.</p>
|
||||
<p class="px-4 py-8 text-center text-sm text-gray-500">
|
||||
{{ $pacchetto->isEmpty() ? "Il pacchetto è vuoto: l'amministratore non ha ancora assegnato territori al gruppo." : 'Nessun territorio con questi filtri.' }}
|
||||
</p>
|
||||
@endforelse
|
||||
<p x-show="nessuno" x-cloak class="px-4 py-8 text-center text-sm text-gray-400">Nessun risultato per «<span x-text="q"></span>».</p>
|
||||
</div>
|
||||
@@ -111,7 +148,7 @@
|
||||
<h2 id="titolo-membri" class="text-sm font-semibold text-gray-800 mb-2">Membri del gruppo</h2>
|
||||
<ul class="text-sm text-gray-700 space-y-1">
|
||||
@foreach($membri as $m)
|
||||
@php $quanti = $territori->filter(fn ($t) => $t->assegnazioneCorrente?->proclamatore_id === $m->id)->count(); @endphp
|
||||
@php $quanti = $pacchetto->filter(fn ($t) => $t->assegnazioneCorrente?->proclamatore_id === $m->id)->count(); @endphp
|
||||
<li class="flex justify-between gap-3">
|
||||
<span>{{ $m->nome_completo }} @if($m->id === $gruppo->sorvegliante_id)<span class="text-xs text-gray-500">(sorvegliante)</span>@endif</span>
|
||||
<span class="text-gray-500">{{ $quanti }} {{ $quanti === 1 ? 'territorio' : 'territori' }}</span>
|
||||
|
||||
@@ -110,14 +110,14 @@
|
||||
<div>
|
||||
<div class="flex items-center gap-2">
|
||||
<a data-ritorno href="{{ route('territori.show', $t) }}" class="text-sm font-semibold text-gray-900 hover:text-indigo-600 transition-colors">N° {{ $t->numero }}</a>
|
||||
@if($t->home_is_prioritario)
|
||||
@if($t->in_priorita)
|
||||
<span class="inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide badge-pulse" style="background:#fef3c7;color:#92400e">★ Prioritario</span>
|
||||
@endif
|
||||
</div>
|
||||
<p class="text-xs text-gray-500">
|
||||
{{ $t->zona?->nome }} — {{ $t->tipologia?->nome }}
|
||||
@if($t->home_giorni_giacenza > 0)
|
||||
— <span class="font-medium">{{ $t->home_giorni_giacenza }} gg</span> in reparto
|
||||
@if($t->giacenza_giorni > 0)
|
||||
— <span class="font-medium">{{ $t->giacenza_giorni }} gg</span> in reparto
|
||||
@endif
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -44,9 +44,9 @@
|
||||
<td style="font-weight:bold">{{ $t->numero }}</td>
|
||||
<td>{{ $t->zona?->nome ?? '-' }}</td>
|
||||
<td>{{ $t->tipologia?->nome ?? '-' }}</td>
|
||||
<td>{{ $t->home_giorni_giacenza }} gg</td>
|
||||
<td>{{ $t->giacenza_giorni }} gg</td>
|
||||
<td>
|
||||
@if($t->home_is_prioritario)
|
||||
@if($t->in_priorita)
|
||||
<span class="prioritario">★ Prioritario</span>
|
||||
@else
|
||||
-
|
||||
|
||||
Reference in New Issue
Block a user