- 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>
224 lines
7.8 KiB
PHP
224 lines
7.8 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire\Gruppi;
|
|
|
|
use App\Livewire\Concerns\Avvisa;
|
|
use App\Livewire\Concerns\InviaLink;
|
|
use App\Models\Assegnazione;
|
|
use App\Models\GruppoServizio;
|
|
use App\Models\Proclamatore;
|
|
use App\Models\Territorio;
|
|
use App\Services\GruppiServizio;
|
|
use Carbon\Carbon;
|
|
use InvalidArgumentException;
|
|
use Livewire\Attributes\Locked;
|
|
use Livewire\Attributes\Url;
|
|
use Livewire\Component;
|
|
|
|
/**
|
|
* "Il mio gruppo": la sola pagina del sorvegliante di gruppo. Vede il
|
|
* pacchetto del suo gruppo e i membri; dà i territori ai membri (o a sé),
|
|
* manda il link, registra i rientri (pagina Rientra), apre la piantina e
|
|
* rimanda in reparto quelli non ancora dati. Le regole stanno in
|
|
* App\Services\GruppiServizio; qui ogni azione ricontrolla che il territorio
|
|
* o l'assegnazione siano del suo gruppo.
|
|
*/
|
|
class MioGruppo extends Component
|
|
{
|
|
use Avvisa;
|
|
use InviaLink;
|
|
|
|
/** Il territorio del pacchetto che si sta assegnando. */
|
|
#[Locked]
|
|
public ?int $territorioDaAssegnare = null;
|
|
|
|
public ?int $membroId = null;
|
|
|
|
public string $dataAssegnazione = '';
|
|
|
|
// Filtri del pacchetto, nell'indirizzo: tornando dal rientro si ritrovano.
|
|
#[Url(except: '')]
|
|
public string $filtroZona = '';
|
|
|
|
#[Url(except: '')]
|
|
public string $filtroTipologia = '';
|
|
|
|
/** '' tutti, 'da_dare', 'dati' */
|
|
#[Url(except: '')]
|
|
public string $filtroStato = '';
|
|
|
|
#[Url(except: false)]
|
|
public bool $soloPrioritari = false;
|
|
|
|
public function mount(): void
|
|
{
|
|
$this->dataAssegnazione = now()->format('Y-m-d');
|
|
}
|
|
|
|
private function gruppo(): ?GruppoServizio
|
|
{
|
|
return auth()->user()->gruppoSorvegliato();
|
|
}
|
|
|
|
private function gruppoOFallisci(): GruppoServizio
|
|
{
|
|
$gruppo = $this->gruppo();
|
|
abort_unless($gruppo, 403, 'Non sei il sorvegliante di un gruppo di servizio attivo.');
|
|
|
|
return $gruppo;
|
|
}
|
|
|
|
private function territorioDelPacchetto(int $id): Territorio
|
|
{
|
|
$gruppo = $this->gruppoOFallisci();
|
|
$territorio = Territorio::find($id);
|
|
abort_unless($territorio && $territorio->gruppo_servizio_id === $gruppo->id, 403);
|
|
|
|
return $territorio;
|
|
}
|
|
|
|
// ─── Assegnare un territorio del pacchetto ──────────────────
|
|
|
|
public function apriAssegnazione(int $territorioId): void
|
|
{
|
|
$this->territorioDelPacchetto($territorioId);
|
|
$this->territorioDaAssegnare = $territorioId;
|
|
$this->membroId = null;
|
|
$this->dataAssegnazione = now()->format('Y-m-d');
|
|
$this->resetValidation();
|
|
}
|
|
|
|
public function annullaAssegnazione(): void
|
|
{
|
|
$this->reset(['territorioDaAssegnare', 'membroId']);
|
|
$this->resetValidation();
|
|
}
|
|
|
|
public function assegna(): void
|
|
{
|
|
$this->validate([
|
|
'membroId' => 'required|integer',
|
|
'dataAssegnazione' => 'required|date|before_or_equal:today',
|
|
], [
|
|
'membroId.required' => 'Scegli a chi dare il territorio.',
|
|
'dataAssegnazione.before_or_equal' => 'La data non può essere nel futuro.',
|
|
]);
|
|
|
|
$gruppo = $this->gruppoOFallisci();
|
|
$territorio = $this->territorioDelPacchetto((int) $this->territorioDaAssegnare);
|
|
$membro = Proclamatore::find($this->membroId);
|
|
|
|
if (! $membro) {
|
|
$this->addError('membroId', 'Scegli un membro del gruppo.');
|
|
|
|
return;
|
|
}
|
|
|
|
try {
|
|
$assegnazione = app(GruppiServizio::class)->assegna($gruppo, $territorio, $membro, Carbon::parse($this->dataAssegnazione));
|
|
} catch (InvalidArgumentException $e) {
|
|
$this->addError('membroId', $e->getMessage());
|
|
|
|
return;
|
|
}
|
|
|
|
$this->reset(['territorioDaAssegnare', 'membroId']);
|
|
|
|
// Come dalla pagina Assegna: si apre l'invio del link.
|
|
$this->apriInvio($assegnazione->id);
|
|
}
|
|
|
|
// ─── Rimandare in reparto ───────────────────────────────────
|
|
|
|
public function rimanda(int $territorioId): void
|
|
{
|
|
$territorio = $this->territorioDelPacchetto($territorioId);
|
|
|
|
try {
|
|
app(GruppiServizio::class)->rimandaInReparto($this->gruppoOFallisci(), $territorio);
|
|
} catch (InvalidArgumentException $e) {
|
|
$this->avvisaErrore($e->getMessage());
|
|
|
|
return;
|
|
}
|
|
|
|
$this->avvisa("Territorio {$territorio->numero} rimandato in reparto.");
|
|
}
|
|
|
|
// ─── Link già inviato / condiviso dall'elenco ───────────────
|
|
|
|
private function assegnazioneDelGruppo(int $id): Assegnazione
|
|
{
|
|
$assegnazione = Assegnazione::aperte()->with('territorio')->find($id);
|
|
abort_unless($assegnazione && $this->puoInviare($assegnazione), 403);
|
|
|
|
return $assegnazione;
|
|
}
|
|
|
|
public function toggleLinkSent(int $assegnazioneId): void
|
|
{
|
|
$assegnazione = $this->assegnazioneDelGruppo($assegnazioneId);
|
|
$assegnazione->registraInvioLink(! $assegnazione->link_sent, $assegnazione->link_canale);
|
|
}
|
|
|
|
/** "Condividi" dall'elenco andato a buon fine (elencoCercabile.condividi). */
|
|
public function segnaCondiviso(int $assegnazioneId): void
|
|
{
|
|
$this->assegnazioneDelGruppo($assegnazioneId)->registraInvioLink(true, 'condividi');
|
|
}
|
|
|
|
// ─── Invio del link (trait InviaLink) ───────────────────────
|
|
|
|
protected function puoInviare(Assegnazione $assegnazione): bool
|
|
{
|
|
$gruppo = $this->gruppo();
|
|
|
|
return $gruppo !== null
|
|
&& ($assegnazione->gruppo_servizio_id === $gruppo->id
|
|
|| $assegnazione->territorio?->gruppo_servizio_id === $gruppo->id);
|
|
}
|
|
|
|
protected function paginaDopoInvio(): string
|
|
{
|
|
return route('mio-gruppo');
|
|
}
|
|
|
|
public function render()
|
|
{
|
|
$gruppo = $this->gruppo()?->load('sorvegliante');
|
|
|
|
// Prima quelli da dare, in ordine di priorità come "Da assegnare"
|
|
// nella Home (Territorio::ordinaPerPriorita); poi quelli già dati, dal
|
|
// più vecchio.
|
|
$pacchetto = $gruppo
|
|
? $gruppo->territori()->with(['zona', 'tipologia', 'ultimaAssegnazione', 'assegnazioneCorrente.proclamatore'])->get()
|
|
: collect();
|
|
[$dati, $daDare] = $pacchetto->partition(fn (Territorio $t) => $t->assegnazioneCorrente !== null);
|
|
$pacchetto = Territorio::ordinaPerPriorita($daDare)
|
|
->concat($dati->sortBy(fn (Territorio $t) => $t->assegnazioneCorrente->assigned_at)->values());
|
|
|
|
$territori = $pacchetto
|
|
->when($this->filtroZona !== '', fn ($c) => $c->where('zona_id', (int) $this->filtroZona))
|
|
->when($this->filtroTipologia !== '', fn ($c) => $c->where('tipologia_id', (int) $this->filtroTipologia))
|
|
->when($this->filtroStato === 'da_dare', fn ($c) => $c->whereNull('assegnazioneCorrente'))
|
|
->when($this->filtroStato === 'dati', fn ($c) => $c->whereNotNull('assegnazioneCorrente'))
|
|
->when($this->soloPrioritari, fn ($c) => $c->where('in_priorita', true))
|
|
->values();
|
|
|
|
$membri = $gruppo
|
|
? $gruppo->membri()->where('attivo', true)->get()->sortBy(fn ($p) => mb_strtolower($p->cognome . ' ' . $p->nome))->values()
|
|
: collect();
|
|
|
|
return view('livewire.gruppi.mio-gruppo', [
|
|
'gruppo' => $gruppo,
|
|
'pacchetto' => $pacchetto,
|
|
'territori' => $territori,
|
|
'zone' => $pacchetto->filter(fn ($t) => $t->zona)->mapWithKeys(fn ($t) => [$t->zona_id => $t->zona->nome])->sort(),
|
|
'tipologie' => $pacchetto->filter(fn ($t) => $t->tipologia)->mapWithKeys(fn ($t) => [$t->tipologia_id => $t->tipologia->nome])->sort(),
|
|
'membri' => $membri,
|
|
'opzioniMembri' => Proclamatore::opzioniScelta($membri, conGruppo: false),
|
|
'invio' => $this->invioCorrente(),
|
|
]);
|
|
}
|
|
}
|