Al posto delle tendine (Assegna, Registro, editor delle piantine) un
campo in cui si scrive e compaiono le proposte più vicine: uguale, inizia
con, contiene, errore di battitura ("forse cercavi"); parole in qualsiasi
ordine, senza badare a maiuscole e accenti. Campo vuoto: la tendina
completa. Fatto anche per il telefono (16px, voci da 44px, scelta al tocco).
- Logica pura in resources/js/scelta.js con test node (tests/js).
- Opzioni dal server: Territorio/Proclamatore::opzioneScelta(); i
territori già assegnati si trovano ("già assegnato a …") ma non si
scelgono. Nomi cifrati ordinati e cercati decifrati, mai in SQL.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
613 lines
21 KiB
PHP
613 lines
21 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire\Piantine;
|
|
|
|
use App\Livewire\Concerns\Avvisa;
|
|
use App\Models\Territorio;
|
|
use App\Models\TerritorioMappa;
|
|
use App\Models\Tipologia;
|
|
use App\Models\Zona;
|
|
use App\Services\Piantine\PiantineArea;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Illuminate\Validation\Rule;
|
|
use Livewire\Attributes\Layout;
|
|
use Livewire\Attributes\Locked;
|
|
use Livewire\Attributes\On;
|
|
use Livewire\Component;
|
|
|
|
/**
|
|
* Editor delle piantine a schermo intero (solo amministratore).
|
|
*
|
|
* Tutto quello che si fa qui è bozza e si salva da solo: il confine a ogni
|
|
* disegno o spostamento di vertice, il nome e il collegamento appena cambiano.
|
|
* La bozza non tocca il PDF del territorio, che cambia solo con "Pubblica"
|
|
* (anteprima e conferma, nel componente Pubblicazione). I dati del territorio
|
|
* — numero, zona, tipologia, confini — sono invece dati del gestionale e si
|
|
* salvano subito, come dalla scheda territorio.
|
|
*
|
|
* Disegnare crea sempre una piantina nuova: per cambiare il confine di quella
|
|
* aperta ci sono "Modifica vertici" e "Ridisegna", espliciti. Prima un
|
|
* disegno fatto con una piantina aperta ne sostituiva il confine in silenzio.
|
|
*
|
|
* Con la mappa si parla per eventi, e solo con il necessario: i dati di tutte
|
|
* le piantine li chiede la mappa una volta (datiMappa), poi riceve solo la
|
|
* piantina cambiata. Prima ogni richiesta rispediva tutte le geometrie e
|
|
* l'area KML, fino a una decina di MB per aprire un pannello.
|
|
*/
|
|
#[Layout('components.layouts.editor')]
|
|
class PiantineEditor extends Component
|
|
{
|
|
use Avvisa;
|
|
|
|
/** Piantina aperta, o null quando non ce n'è nessuna selezionata. */
|
|
#[Locked]
|
|
public ?int $mappaId = null;
|
|
|
|
public string $nome = '';
|
|
|
|
/** Ora dell'ultimo salvataggio automatico, per l'indicazione in testata. */
|
|
public string $salvatoAlle = '';
|
|
|
|
// ─── Territorio ─────────────────────────────────────────────────────────
|
|
|
|
/** '' = nessun territorio, 'nuovo' = da creare, altrimenti l'id. */
|
|
public string $territorioScelto = '';
|
|
|
|
public string $numero = '';
|
|
|
|
public string $zonaId = '';
|
|
|
|
public string $tipologiaId = '';
|
|
|
|
public string $confini = '';
|
|
|
|
public string $nuovaZona = '';
|
|
|
|
public string $nuovaTipologia = '';
|
|
|
|
/**
|
|
* Arrivati da "Nuovo territorio" (?nuovo=1): la mappa parte già in
|
|
* disegno, e la prima piantina disegnata si apre con "nuovo territorio"
|
|
* scelto, pronta da compilare e creare.
|
|
*/
|
|
#[Locked]
|
|
public bool $creaTerritorio = false;
|
|
|
|
public function mount(?int $mappa = null): void
|
|
{
|
|
if ($mappa !== null && TerritorioMappa::whereKey($mappa)->exists()) {
|
|
$this->carica(TerritorioMappa::with('territorio')->find($mappa));
|
|
} elseif (request()->boolean('nuovo')) {
|
|
$this->creaTerritorio = true;
|
|
}
|
|
}
|
|
|
|
// ─── Selezione ──────────────────────────────────────────────────────────
|
|
|
|
#[On('piantina-selezionata-mappa')]
|
|
public function apri($mappaId): void
|
|
{
|
|
$mappa = TerritorioMappa::with('territorio')->find(is_numeric($mappaId) ? (int) $mappaId : null);
|
|
|
|
if (! $mappa) {
|
|
$this->avvisaErrore('Questa piantina non esiste più: forse è stata eliminata da un\'altra scheda.');
|
|
$this->dispatch('piantina-rimossa', mappaId: (int) $mappaId);
|
|
|
|
return;
|
|
}
|
|
|
|
$this->carica($mappa);
|
|
$this->dispatch('piantina-selezionata', mappaId: $mappa->id, inquadra: true);
|
|
}
|
|
|
|
/** "Nuova piantina": si deseleziona e la mappa entra in modalità disegno. */
|
|
public function nuova(): void
|
|
{
|
|
$this->svuota();
|
|
$this->dispatch('piantina-selezionata', mappaId: null, inquadra: false);
|
|
$this->dispatch('editor-disegna');
|
|
}
|
|
|
|
private function carica(TerritorioMappa $mappa): void
|
|
{
|
|
$this->resetValidation();
|
|
$this->mappaId = $mappa->id;
|
|
$this->nome = (string) $mappa->nome;
|
|
$this->salvatoAlle = '';
|
|
$this->nuovaZona = '';
|
|
$this->nuovaTipologia = '';
|
|
$this->caricaTerritorio($mappa->territorio);
|
|
}
|
|
|
|
private function svuota(): void
|
|
{
|
|
$this->resetValidation();
|
|
$this->reset([
|
|
'mappaId', 'nome', 'salvatoAlle',
|
|
'territorioScelto', 'numero', 'zonaId', 'tipologiaId', 'confini',
|
|
'nuovaZona', 'nuovaTipologia',
|
|
]);
|
|
}
|
|
|
|
private function caricaTerritorio(?Territorio $territorio): void
|
|
{
|
|
$this->territorioScelto = $territorio ? (string) $territorio->id : '';
|
|
$this->numero = (string) ($territorio->numero ?? '');
|
|
$this->zonaId = (string) ($territorio->zona_id ?? '');
|
|
$this->tipologiaId = (string) ($territorio->tipologia_id ?? '');
|
|
$this->confini = (string) ($territorio->confini ?? '');
|
|
}
|
|
|
|
// ─── Confine (bozza, salvataggio automatico) ────────────────────────────
|
|
|
|
/**
|
|
* Arriva dalla mappa dopo un disegno o lo spostamento di un vertice.
|
|
* $nuova: il disegno è una piantina nuova (strumento "Disegna"), non il
|
|
* confine ridisegnato di quella aperta.
|
|
*/
|
|
#[On('geometria-modificata')]
|
|
public function salvaGeometria($geometry, bool $nuova = false): void
|
|
{
|
|
if (! $this->geometriaValida($geometry)) {
|
|
$this->avvisaErrore('Il confine disegnato non è valido: ridisegnalo.');
|
|
|
|
return;
|
|
}
|
|
|
|
$geojson = json_encode($geometry);
|
|
$mappa = (! $nuova && $this->mappaId) ? TerritorioMappa::find($this->mappaId) : null;
|
|
|
|
if ($mappa) {
|
|
$mappa->update(['geojson' => $geojson]);
|
|
} else {
|
|
$mappa = TerritorioMappa::create(['geojson' => $geojson]);
|
|
$this->carica($mappa);
|
|
activity()->causedBy(auth()->user())->log('piantina_creata');
|
|
|
|
if ($this->creaTerritorio) {
|
|
$this->creaTerritorio = false;
|
|
$this->territorioScelto = 'nuovo';
|
|
}
|
|
}
|
|
|
|
$this->salvato($mappa, seleziona: true);
|
|
}
|
|
|
|
/**
|
|
* Anelli chiusi di almeno quattro punti con coordinate nei limiti: un
|
|
* record malformato faceva fallire il disegno di tutte le piantine.
|
|
*/
|
|
private function geometriaValida($geometry): bool
|
|
{
|
|
if (! is_array($geometry) || ! is_array($geometry['coordinates'] ?? null)) {
|
|
return false;
|
|
}
|
|
|
|
$poligoni = match ($geometry['type'] ?? null) {
|
|
'Polygon' => [$geometry['coordinates']],
|
|
'MultiPolygon' => $geometry['coordinates'],
|
|
default => null,
|
|
};
|
|
|
|
if (! $poligoni) {
|
|
return false;
|
|
}
|
|
|
|
foreach ($poligoni as $anelli) {
|
|
if (! is_array($anelli) || $anelli === []) {
|
|
return false;
|
|
}
|
|
foreach ($anelli as $anello) {
|
|
if (! is_array($anello) || count($anello) < 4) {
|
|
return false;
|
|
}
|
|
foreach ($anello as $punto) {
|
|
if (! is_array($punto) || count($punto) < 2
|
|
|| ! is_numeric($punto[0]) || ! is_numeric($punto[1])
|
|
|| abs($punto[0]) > 180 || abs($punto[1]) > 90) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/** Riporta il confine a quello pubblicato. */
|
|
public function scartaModifiche(): void
|
|
{
|
|
$mappa = $this->mappaAperta();
|
|
|
|
if (! $mappa || ! $mappa->bozzaScartabile()) {
|
|
return;
|
|
}
|
|
|
|
$mappa->update(['geojson' => $mappa->geojson_pubblicato]);
|
|
$this->salvato($mappa, seleziona: true);
|
|
$this->avvisa('Confine riportato a quello pubblicato.');
|
|
}
|
|
|
|
public function updatedNome(): void
|
|
{
|
|
$mappa = $this->mappaAperta();
|
|
|
|
if (! $mappa) {
|
|
return;
|
|
}
|
|
|
|
$nome = trim($this->nome);
|
|
$mappa->update(['nome' => $nome !== '' ? mb_substr($nome, 0, 120) : null]);
|
|
$this->salvato($mappa);
|
|
}
|
|
|
|
// ─── Collegamento al territorio ─────────────────────────────────────────
|
|
|
|
public function updatedTerritorioScelto(string $valore): void
|
|
{
|
|
$this->resetValidation();
|
|
$mappa = $this->mappaAperta();
|
|
|
|
if (! $mappa) {
|
|
return;
|
|
}
|
|
|
|
if ($valore === 'nuovo') {
|
|
// Si compilano i campi e si crea con il pulsante: un territorio
|
|
// non nasce da un salvataggio automatico a metà digitazione.
|
|
$this->numero = '';
|
|
$this->zonaId = '';
|
|
$this->tipologiaId = '';
|
|
$this->confini = '';
|
|
|
|
return;
|
|
}
|
|
|
|
if ($valore === '') {
|
|
$numero = $mappa->territorio?->numero;
|
|
$mappa->update([
|
|
'territorio_id' => null,
|
|
// Senza territorio serve un'etichetta, altrimenti la piantina
|
|
// finisce in elenco come un anonimo "Piantina #12".
|
|
'nome' => $mappa->nome ?: ($numero ? "Ex territorio {$numero}" : null),
|
|
]);
|
|
$this->nome = (string) $mappa->nome;
|
|
$this->caricaTerritorio(null);
|
|
$this->salvato($mappa);
|
|
|
|
return;
|
|
}
|
|
|
|
$territorio = Territorio::find($valore);
|
|
if (! $territorio) {
|
|
$this->addError('territorioScelto', 'Il territorio scelto non esiste più.');
|
|
$this->caricaTerritorio($mappa->territorio);
|
|
|
|
return;
|
|
}
|
|
|
|
$occupata = TerritorioMappa::where('territorio_id', $territorio->id)->whereKeyNot($mappa->id)->exists();
|
|
if ($occupata) {
|
|
$this->addError('territorioScelto', "Il territorio {$territorio->numero} ha già una piantina.");
|
|
$this->caricaTerritorio($mappa->territorio);
|
|
|
|
return;
|
|
}
|
|
|
|
$mappa->update(['territorio_id' => $territorio->id]);
|
|
$this->caricaTerritorio($territorio);
|
|
activity()->causedBy(auth()->user())->performedOn($territorio)->log('piantina_collegata');
|
|
$this->salvato($mappa);
|
|
}
|
|
|
|
public function creaTerritorio(): void
|
|
{
|
|
$mappa = $this->mappaAperta();
|
|
|
|
if (! $mappa || $this->territorioScelto !== 'nuovo') {
|
|
return;
|
|
}
|
|
|
|
$this->numero = trim($this->numero);
|
|
$this->confini = trim($this->confini);
|
|
|
|
$this->validate(
|
|
[
|
|
'numero' => ['required', 'string', 'max:20', Rule::unique('territori', 'numero')],
|
|
'zonaId' => ['nullable', Rule::exists('zone', 'id')],
|
|
'tipologiaId' => ['nullable', Rule::exists('tipologie', 'id')],
|
|
'confini' => ['nullable', 'string', 'max:5000'],
|
|
],
|
|
$this->messaggiTerritorio(),
|
|
);
|
|
|
|
try {
|
|
$territorio = DB::transaction(function () use ($mappa) {
|
|
$territorio = Territorio::create($this->valoriTerritorio() + ['attivo' => true]);
|
|
$mappa->update(['territorio_id' => $territorio->id]);
|
|
|
|
return $territorio;
|
|
});
|
|
} catch (\Illuminate\Database\UniqueConstraintViolationException) {
|
|
$this->addError('numero', 'Esiste già un territorio con questo numero.');
|
|
|
|
return;
|
|
}
|
|
|
|
activity()->causedBy(auth()->user())->performedOn($territorio)->log('territorio_creato_da_piantine');
|
|
|
|
$this->caricaTerritorio($territorio);
|
|
$this->salvato($mappa);
|
|
$this->avvisa("Territorio {$territorio->numero} creato e collegato.");
|
|
}
|
|
|
|
// ─── Dati del territorio (salvati subito nel gestionale) ────────────────
|
|
|
|
public function updatedNumero(): void
|
|
{
|
|
$this->salvaCampoTerritorio('numero');
|
|
}
|
|
|
|
public function updatedZonaId(): void
|
|
{
|
|
$this->salvaCampoTerritorio('zonaId');
|
|
}
|
|
|
|
public function updatedTipologiaId(): void
|
|
{
|
|
$this->salvaCampoTerritorio('tipologiaId');
|
|
}
|
|
|
|
public function updatedConfini(): void
|
|
{
|
|
$this->salvaCampoTerritorio('confini');
|
|
}
|
|
|
|
private function salvaCampoTerritorio(string $campo): void
|
|
{
|
|
// In creazione i campi si raccolgono e basta: li salva creaTerritorio().
|
|
$territorio = $this->territorioCollegato();
|
|
if (! $territorio) {
|
|
return;
|
|
}
|
|
|
|
$this->numero = trim($this->numero);
|
|
|
|
$regole = [
|
|
'numero' => ['required', 'string', 'max:20', Rule::unique('territori', 'numero')->ignore($territorio->id)],
|
|
'zonaId' => ['nullable', Rule::exists('zone', 'id')],
|
|
'tipologiaId' => ['nullable', Rule::exists('tipologie', 'id')],
|
|
'confini' => ['nullable', 'string', 'max:5000'],
|
|
];
|
|
|
|
$this->validateOnly($campo, $regole, $this->messaggiTerritorio());
|
|
|
|
// Solo la colonna del campo cambiato: con un altro campo ancora non
|
|
// valido a schermo, riscrivere tutto salverebbe anche quel valore.
|
|
$colonna = ['numero' => 'numero', 'zonaId' => 'zona_id', 'tipologiaId' => 'tipologia_id', 'confini' => 'confini'][$campo];
|
|
$territorio->update([$colonna => $this->valoriTerritorio()[$colonna]]);
|
|
|
|
$this->salvato($this->mappaAperta());
|
|
}
|
|
|
|
private function valoriTerritorio(): array
|
|
{
|
|
return [
|
|
'numero' => trim($this->numero),
|
|
'zona_id' => $this->zonaId !== '' ? (int) $this->zonaId : null,
|
|
'tipologia_id' => $this->tipologiaId !== '' ? (int) $this->tipologiaId : null,
|
|
'confini' => trim($this->confini) !== '' ? trim($this->confini) : null,
|
|
];
|
|
}
|
|
|
|
private function messaggiTerritorio(): array
|
|
{
|
|
return [
|
|
'numero.required' => 'Il territorio ha bisogno di un numero.',
|
|
'numero.unique' => 'Esiste già un territorio con questo numero.',
|
|
'numero.max' => 'Il numero può avere al massimo 20 caratteri.',
|
|
'confini.max' => 'I confini possono avere al massimo 5000 caratteri.',
|
|
];
|
|
}
|
|
|
|
// ─── Zona e tipologia create sul posto ──────────────────────────────────
|
|
|
|
public function creaZona(): void
|
|
{
|
|
$this->nuovaZona = trim($this->nuovaZona);
|
|
$dati = $this->validate(
|
|
['nuovaZona' => ['required', 'string', 'max:100', Rule::unique('zone', 'nome')]],
|
|
[
|
|
'nuovaZona.required' => 'Scrivi il nome della zona.',
|
|
'nuovaZona.unique' => 'Questa zona esiste già: sceglila dall\'elenco.',
|
|
],
|
|
);
|
|
|
|
$zona = Zona::create(['nome' => $dati['nuovaZona'], 'attivo' => true]);
|
|
|
|
$this->zonaId = (string) $zona->id;
|
|
$this->nuovaZona = '';
|
|
$this->updatedZonaId();
|
|
$this->avvisa("Zona «{$zona->nome}» creata e selezionata.");
|
|
}
|
|
|
|
public function creaTipologia(): void
|
|
{
|
|
$this->nuovaTipologia = trim($this->nuovaTipologia);
|
|
$dati = $this->validate(
|
|
['nuovaTipologia' => ['required', 'string', 'max:100', Rule::unique('tipologie', 'nome')]],
|
|
[
|
|
'nuovaTipologia.required' => 'Scrivi il nome della tipologia.',
|
|
'nuovaTipologia.unique' => 'Questa tipologia esiste già: sceglila dall\'elenco.',
|
|
],
|
|
);
|
|
|
|
$tipologia = Tipologia::create(['nome' => $dati['nuovaTipologia'], 'attivo' => true]);
|
|
|
|
$this->tipologiaId = (string) $tipologia->id;
|
|
$this->nuovaTipologia = '';
|
|
$this->updatedTipologiaId();
|
|
$this->avvisa("Tipologia «{$tipologia->nome}» creata e selezionata.");
|
|
}
|
|
|
|
// ─── Pubblicazione ed eliminazione ──────────────────────────────────────
|
|
|
|
public function pubblica(): void
|
|
{
|
|
$mappa = $this->mappaAperta();
|
|
|
|
if (! $mappa) {
|
|
return;
|
|
}
|
|
|
|
if ($motivo = $mappa->motivoNonPubblicabile()) {
|
|
$this->avvisaErrore($motivo);
|
|
|
|
return;
|
|
}
|
|
|
|
$this->dispatch('pubblica-piantina', mappaId: $mappa->id)->to(Pubblicazione::class);
|
|
}
|
|
|
|
#[On('piantina-pubblicata')]
|
|
public function pubblicata(int $mappaId): void
|
|
{
|
|
$mappa = TerritorioMappa::with('territorio.zona')->find($mappaId);
|
|
|
|
if ($mappa) {
|
|
$this->dispatch('piantina-aggiornata', piantina: $this->datiPiantina($mappa));
|
|
}
|
|
}
|
|
|
|
public function elimina(): void
|
|
{
|
|
$mappa = $this->mappaAperta();
|
|
|
|
if (! $mappa) {
|
|
return;
|
|
}
|
|
|
|
$etichetta = $mappa->etichetta();
|
|
$id = $mappa->id;
|
|
|
|
if ($mappa->image_path) {
|
|
Storage::disk('public')->delete($mappa->image_path);
|
|
}
|
|
$mappa->delete();
|
|
|
|
$this->svuota();
|
|
$this->dispatch('piantina-rimossa', mappaId: $id);
|
|
$this->avvisa("{$etichetta} eliminata. Il territorio e il suo PDF restano com'erano.");
|
|
}
|
|
|
|
// ─── Dati per la mappa ──────────────────────────────────────────────────
|
|
|
|
/** Chiamata una volta dalla mappa all'avvio ($wire.datiMappa()). */
|
|
public function datiMappa(PiantineArea $area): array
|
|
{
|
|
return [
|
|
'area' => $area->area(),
|
|
'piantine' => TerritorioMappa::with('territorio.zona')->get()
|
|
->filter(fn (TerritorioMappa $m) => $m->geometria() !== null)
|
|
->map(fn (TerritorioMappa $m) => $this->datiPiantina($m))
|
|
->values()
|
|
->all(),
|
|
'selezionata' => $this->mappaId,
|
|
];
|
|
}
|
|
|
|
private function datiPiantina(TerritorioMappa $mappa): array
|
|
{
|
|
return [
|
|
'mappaId' => $mappa->id,
|
|
'etichetta' => $mappa->etichetta(),
|
|
'collegata' => $mappa->collegata(),
|
|
'stato' => $mappa->stato(),
|
|
'statoEtichetta' => $mappa->statoEtichetta(),
|
|
'geometry' => $mappa->geometria(),
|
|
];
|
|
}
|
|
|
|
/** Dopo ogni salvataggio automatico: ora in testata, mappa e indirizzo allineati. */
|
|
private function salvato(?TerritorioMappa $mappa, bool $seleziona = false): void
|
|
{
|
|
if (! $mappa) {
|
|
return;
|
|
}
|
|
|
|
$mappa = $mappa->fresh(['territorio.zona']);
|
|
$this->salvatoAlle = now()->format('H:i');
|
|
|
|
$this->dispatch('piantina-aggiornata', piantina: $this->datiPiantina($mappa));
|
|
|
|
if ($seleziona) {
|
|
$this->dispatch('piantina-selezionata', mappaId: $mappa->id, inquadra: false);
|
|
}
|
|
|
|
// La piantina aperta resta nell'indirizzo: ricaricando la pagina si
|
|
// torna su questa e non su un editor vuoto.
|
|
$this->dispatch('editor-indirizzo', url: route('piantine.editor', $mappa->id));
|
|
}
|
|
|
|
private function mappaAperta(): ?TerritorioMappa
|
|
{
|
|
return $this->mappaId ? TerritorioMappa::with('territorio.zona')->find($this->mappaId) : null;
|
|
}
|
|
|
|
private function territorioCollegato(): ?Territorio
|
|
{
|
|
if ($this->territorioScelto === '' || $this->territorioScelto === 'nuovo') {
|
|
return null;
|
|
}
|
|
|
|
$mappa = $this->mappaAperta();
|
|
|
|
return $mappa?->territorio;
|
|
}
|
|
|
|
public function render()
|
|
{
|
|
$mappa = $this->mappaAperta();
|
|
|
|
// Nella tendina: i territori attivi senza piantina, più quello già
|
|
// collegato anche se nel frattempo è stato disattivato o cestinato.
|
|
$occupati = TerritorioMappa::whereNotNull('territorio_id')
|
|
->when($mappa, fn ($q) => $q->whereKeyNot($mappa->id))
|
|
->pluck('territorio_id');
|
|
|
|
$territori = Territorio::attivi()
|
|
->with(['zona:id,nome', 'tipologia:id,nome'])
|
|
->whereNotIn('id', $occupati)
|
|
->orderByRaw('LENGTH(numero), numero')
|
|
->get(['id', 'numero', 'zona_id', 'tipologia_id', 'attivo', 'deleted_at']);
|
|
|
|
if ($mappa?->territorio && ! $territori->contains('id', $mappa->territorio_id)) {
|
|
$territori->prepend($mappa->territorio);
|
|
}
|
|
|
|
// Il campo di scelta con ricerca (<x-scelta>): due voci fisse in cima,
|
|
// poi i territori, che qui restano sceglibili anche se cestinati o
|
|
// disattivati (è il collegamento che già c'era).
|
|
$opzioniTerritori = [
|
|
['valore' => '', 'etichetta' => '— nessun territorio —', 'speciale' => true],
|
|
['valore' => 'nuovo', 'etichetta' => '+ Crea un territorio nuovo', 'speciale' => true],
|
|
...$territori->map(function (Territorio $t) {
|
|
$opzione = $t->opzioneScelta(nota: $t->trashed() ? 'nel cestino' : (! $t->attivo ? 'disattivato' : null));
|
|
$opzione['etichetta'] = str_replace('N° ', 'Territorio ', $opzione['etichetta']);
|
|
|
|
return $opzione;
|
|
})->all(),
|
|
];
|
|
|
|
return view('livewire.piantine.piantine-editor', [
|
|
'mappa' => $mappa,
|
|
'areaCaricata' => app(PiantineArea::class)->config()['kml_nome'] !== null,
|
|
'opzioniTerritori' => $opzioniTerritori,
|
|
'zone' => Zona::orderBy('nome')->get(['id', 'nome']),
|
|
'tipologie' => Tipologia::orderBy('nome')->get(['id', 'nome']),
|
|
'title' => $mappa ? $mappa->etichetta() . ' — Editor delle piantine' : 'Editor delle piantine',
|
|
]);
|
|
}
|
|
}
|