- 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>
166 lines
12 KiB
PHP
166 lines
12 KiB
PHP
<div>
|
|
<div class="mb-6">
|
|
<a href="{{ $ritorno ?? route('gruppi.index') }}" class="inline-flex items-center gap-1 text-sm text-gray-500 hover:text-indigo-600 transition-colors mb-1">
|
|
<svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/></svg>
|
|
{{ $ritorno ? 'Torna indietro' : 'Gruppi di servizio' }}
|
|
</a>
|
|
<h1 class="text-2xl font-bold text-gray-900">Gruppo {{ $gruppo->nome }}</h1>
|
|
<p class="text-sm text-gray-500 mt-1">
|
|
Sorvegliante: <strong>{{ $gruppo->sorvegliante?->nome_completo ?? '—' }}</strong>
|
|
@if($gruppo->sorvegliante?->utente)
|
|
· accede con <code class="select-all">{{ $gruppo->sorvegliante->utente->email }}</code>
|
|
@endif
|
|
</p>
|
|
</div>
|
|
|
|
@if($passwordTemporanea)
|
|
<div class="mb-6 rounded-xl border-2 border-green-200 bg-green-50 p-4 text-sm text-green-900" role="status">
|
|
<p>Nuova password temporanea per {{ $gruppo->sorvegliante?->nome_completo }}, da cambiare al primo accesso. Si vede <strong>solo ora</strong>:</p>
|
|
<p class="mt-2"><code class="select-all text-base">{{ $passwordTemporanea }}</code></p>
|
|
</div>
|
|
@endif
|
|
|
|
{{-- ─── Pacchetto ─────────────────────────────────────────── --}}
|
|
<section class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden mb-6" aria-labelledby="titolo-pacchetto">
|
|
<h2 id="titolo-pacchetto" class="px-4 py-3 border-b border-gray-100 text-sm font-semibold text-gray-800">
|
|
Pacchetto ({{ $territori->count() }} territori)
|
|
</h2>
|
|
<ul class="divide-y divide-gray-100">
|
|
@forelse($territori as $t)
|
|
@php($a = $t->assegnazioneCorrente)
|
|
<li class="px-4 py-3 flex flex-wrap items-center justify-between gap-2" wire:key="pacchetto-{{ $t->id }}">
|
|
<span class="text-sm">
|
|
<a data-ritorno href="{{ route('territori.show', $t) }}" class="font-semibold text-indigo-600 hover:underline">N° {{ $t->numero }}</a>
|
|
<span class="text-gray-500">{{ $t->zona?->nome }}</span>
|
|
—
|
|
@if($a)
|
|
<span class="text-gray-700">a {{ $a->proclamatore?->nome_completo }} dal {{ $a->assigned_at->format('d/m/Y') }}</span>
|
|
@else
|
|
<span class="text-gray-700">da dare</span>
|
|
@endif
|
|
</span>
|
|
@unless($a)
|
|
<x-btn variante="secondary" tono="tenue" dimensione="sm" wire:click="rimanda({{ $t->id }})"
|
|
wire:confirm="Rimandare in reparto il territorio {{ $t->numero }}?">Rimanda in reparto</x-btn>
|
|
@endunless
|
|
</li>
|
|
@empty
|
|
<li class="px-4 py-6 text-center text-sm text-gray-500">Il pacchetto è vuoto.</li>
|
|
@endforelse
|
|
</ul>
|
|
|
|
{{-- 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($totaleCandidati === 0)
|
|
<p class="text-sm text-gray-500">Non ci sono territori in reparto da aggiungere.</p>
|
|
@else
|
|
<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="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>
|
|
</section>
|
|
|
|
{{-- ─── Membri ───────────────────────────────────────────── --}}
|
|
<section class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden mb-6" aria-labelledby="titolo-membri">
|
|
<h2 id="titolo-membri" class="px-4 py-3 border-b border-gray-100 text-sm font-semibold text-gray-800">Membri ({{ $membri->count() }})</h2>
|
|
<ul class="divide-y divide-gray-100">
|
|
@foreach($membri as $m)
|
|
<li class="px-4 py-2.5 flex items-center justify-between gap-2 text-sm" wire:key="membro-{{ $m->id }}">
|
|
<span>{{ $m->nome_completo }} @if($m->id === $gruppo->sorvegliante_id)<span class="text-xs text-gray-500">(sorvegliante)</span>@endif</span>
|
|
@if($m->id !== $gruppo->sorvegliante_id)
|
|
<x-btn variante="secondary" tono="tenue" dimensione="sm" wire:click="togliMembro({{ $m->id }})">Togli</x-btn>
|
|
@endif
|
|
</li>
|
|
@endforeach
|
|
</ul>
|
|
|
|
<div class="border-t border-gray-100 bg-gray-50 p-4" x-data="elencoCercabile">
|
|
<h3 class="text-sm font-semibold text-gray-700 mb-2">Aggiungi membri</h3>
|
|
@if($candidatiMembri->isEmpty())
|
|
<p class="text-sm text-gray-500">Tutti i proclamatori attivi fanno già parte di un gruppo.</p>
|
|
@else
|
|
<input x-model="q" type="search" inputmode="search" autocomplete="off" aria-label="Filtra i proclamatori"
|
|
placeholder="Filtra per nome…"
|
|
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($candidatiMembri 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->nome_completo)) }}"
|
|
x-show="corrisponde($el.dataset.cerca)" wire:key="candidato-p-{{ $c->id }}">
|
|
<input type="checkbox" value="{{ $c->id }}" wire:model="nuoviMembri" class="h-5 w-5 rounded border-gray-300 text-indigo-600">
|
|
<span>{{ $c->nome_completo }}</span>
|
|
</label>
|
|
@endforeach
|
|
</div>
|
|
<div class="mt-3">
|
|
<x-btn variante="primary" wire:click="aggiungiMembri">Aggiungi i membri selezionati</x-btn>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</section>
|
|
|
|
{{-- ─── Sorvegliante ─────────────────────────────────────── --}}
|
|
<section class="bg-white rounded-xl shadow-sm border border-gray-200 p-4" aria-labelledby="titolo-sorvegliante">
|
|
<h2 id="titolo-sorvegliante" class="text-sm font-semibold text-gray-800 mb-2">Sorvegliante</h2>
|
|
<div class="flex flex-wrap gap-2">
|
|
<x-btn variante="secondary" wire:click="nuovaPassword"
|
|
wire:confirm="Generare una nuova password temporanea per {{ $gruppo->sorvegliante?->nome_completo }}? Quella attuale smette di funzionare.">Nuova password temporanea</x-btn>
|
|
<x-btn variante="danger" wire:click="sciogli"
|
|
wire:confirm="Togliere il ruolo di sorvegliante a {{ $gruppo->sorvegliante?->nome_completo }}? Il gruppo si scioglie e viene eliminato: i territori non ancora dati tornano in reparto, i membri restano senza gruppo e l'utenza del sorvegliante viene eliminata. Le assegnazioni già fatte restano ai membri.">Togli il ruolo e sciogli il gruppo</x-btn>
|
|
</div>
|
|
</section>
|
|
</div>
|