++ gruppi di servizio: sorvegliante con utenza limitata, pacchetto di territori, assegnazione ai membri
Il gruppo ha un sorvegliante (proclamatore con utenza: email e password temporanea, senza conferma dell'email) e dei membri; l'amministratore mette in blocco dei territori nel pacchetto del gruppo. Il pacchetto non e' un'assegnazione e non tocca le statistiche; quando il sorvegliante da' un territorio a un membro nasce un'assegnazione normale con gruppo_servizio_id. Al rientro il territorio torna in reparto. Sciogliere il gruppo libera pacchetto e membri e disattiva l'utenza. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
136
resources/views/livewire/gruppi/gruppo-show.blade.php
Normal file
136
resources/views/livewire/gruppi/gruppo-show.blade.php
Normal file
@@ -0,0 +1,136 @@
|
||||
<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($attivo && $gruppo->sorvegliante?->utente)
|
||||
· accede con <code>{{ $gruppo->sorvegliante->utente->email }}</code>
|
||||
@endif
|
||||
</p>
|
||||
@unless($attivo)
|
||||
<p class="mt-2 inline-flex rounded-full bg-gray-100 px-3 py-1 text-xs text-gray-700">
|
||||
Sciolto il {{ $gruppo->sciolto_at->format('d/m/Y') }} · {{ $assegnazioniDelGruppo }} assegnazioni nate dal gruppo restano nello storico
|
||||
</p>
|
||||
@endunless
|
||||
</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
|
||||
|
||||
@if($attivo)
|
||||
{{-- ─── 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 --}}
|
||||
<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 territori al pacchetto</h3>
|
||||
@if($candidatiTerritori->isEmpty())
|
||||
<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>
|
||||
<div class="mt-3">
|
||||
<x-btn variante="primary" wire:click="aggiungiTerritori" :disabled="count($nuoviTerritori) === 0">
|
||||
Aggiungi {{ count($nuoviTerritori) ?: '' }} al pacchetto
|
||||
</x-btn>
|
||||
</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: i territori non ancora dati tornano in reparto, i membri restano senza gruppo e l'utenza del sorvegliante viene disattivata. Le assegnazioni già fatte restano.">Togli il ruolo e sciogli il gruppo</x-btn>
|
||||
</div>
|
||||
</section>
|
||||
@endif
|
||||
</div>
|
||||
Reference in New Issue
Block a user