'Tutte', 'bozze' => 'Bozze', 'da-pubblicare' => 'Da pubblicare', 'pubblicate' => 'Pubblicate', 'scollegate' => 'Scollegate', ]; #[Url(as: 'q', except: '')] public string $cerca = ''; #[Url(except: 'tutte')] public string $filtro = 'tutte'; public $kmlFile = null; public function updatedFiltro(): void { if (! array_key_exists($this->filtro, self::FILTRI)) { $this->filtro = 'tutte'; } } // ─── Area città (KML) ─────────────────────────────────────────────────── public function caricaKml(PiantineArea $area): void { $this->validate( ['kmlFile' => 'required|file|max:10240'], [], ['kmlFile' => 'file KML'], ); $estensione = strtolower($this->kmlFile->getClientOriginalExtension()); if (! in_array($estensione, ['kml', 'xml'], true)) { $this->addError('kmlFile', 'Il file deve essere un .kml (o .xml in formato KML).'); return; } try { $quante = $area->salvaKml( file_get_contents($this->kmlFile->getRealPath()), $this->kmlFile->getClientOriginalName(), ); } catch (\Throwable $e) { $this->addError('kmlFile', $e->getMessage()); return; } $this->kmlFile = null; activity()->causedBy(auth()->user())->log('piantine_kml_caricato'); $this->avvisa("Area della città aggiornata: {$quante} geometrie riconosciute nel KML."); } // ─── Piantine ─────────────────────────────────────────────────────────── public function pubblica(int $mappaId): void { $mappa = TerritorioMappa::with('territorio.zona')->find($mappaId); if (! $mappa) { $this->avvisaErrore('La piantina non esiste più.'); return; } if ($motivo = $mappa->motivoNonPubblicabile()) { $this->avvisaErrore("{$mappa->etichetta()}: {$motivo}"); return; } $this->dispatch('pubblica-piantina', mappaId: $mappa->id)->to(Pubblicazione::class); } /** La finestra di pubblicazione ha finito: basta ridisegnare l'elenco. */ #[On('piantina-pubblicata')] public function pubblicata(): void {} public function elimina(int $mappaId): void { $mappa = TerritorioMappa::with('territorio')->find($mappaId); if (! $mappa) { return; } $etichetta = $mappa->etichetta(); if ($mappa->image_path) { Storage::disk('public')->delete($mappa->image_path); } $mappa->delete(); $this->avvisa("{$etichetta} eliminata. Il territorio e il suo PDF restano com'erano."); } // ─── Storico versioni ─────────────────────────────────────────────────── public function ripristinaVersione(int $versioneId, PiantinaPdfService $pdfService): void { $versione = TerritorioPdfVersione::with('territorio')->find($versioneId); if (! $versione) { return; } $numero = $versione->territorio?->numero ?? '?'; try { $pdfService->ripristina($versione); } catch (\Throwable $e) { $this->avvisaErrore($e->getMessage()); return; } $this->avvisa("Versione precedente ripristinata per il territorio {$numero}. Il PDF che c'era è nello storico."); } public function eliminaVersione(int $versioneId): void { $versione = TerritorioPdfVersione::find($versioneId); if (! $versione) { return; } Storage::disk('public')->delete($versione->pdf_path); $versione->delete(); $this->avvisa('Versione eliminata definitivamente.'); } // ─── Dati per la vista ────────────────────────────────────────────────── /** * Tutte le piantine con il loro stato, in memoria: sono qualche centinaio * al massimo, e lo stato dipende dall'impronta, che si calcola in PHP. * * @return Collection */ private function piantine(): Collection { return TerritorioMappa::with('territorio.zona') ->get() ->sortBy(fn (TerritorioMappa $m) => [ $m->territorio_id === null ? 1 : 0, strlen((string) $m->territorio?->numero), (string) $m->territorio?->numero, mb_strtolower((string) $m->nome), ]) ->values(); } private function corrisponde(TerritorioMappa $mappa, string $filtro): bool { return match ($filtro) { 'bozze' => $mappa->stato() === TerritorioMappa::STATO_BOZZA, 'da-pubblicare' => $mappa->stato() === TerritorioMappa::STATO_MODIFICATA, 'pubblicate' => $mappa->stato() === TerritorioMappa::STATO_PUBBLICATA, 'scollegate' => ! $mappa->collegata(), default => true, }; } public function render(PiantineArea $area) { $piantine = $this->piantine(); $conteggi = collect(self::FILTRI) ->map(fn ($etichetta, $filtro) => $piantine->filter(fn ($m) => $this->corrisponde($m, $filtro))->count()); $cerca = mb_strtolower(trim($this->cerca)); $elenco = $piantine ->filter(fn ($m) => $this->corrisponde($m, $this->filtro)) ->filter(fn (TerritorioMappa $m) => $cerca === '' || str_contains(mb_strtolower(implode(' ', [ $m->etichetta(), $m->territorio?->numero, $m->nome, $m->territorio?->zona?->nome, ])), $cerca)) ->values(); return view('livewire.piantine.piantine-manager', [ 'config' => $area->config(), 'elenco' => $elenco, 'totale' => $piantine->count(), 'conteggi' => $conteggi, 'versioni' => TerritorioPdfVersione::with('territorio') ->orderByDesc('sostituito_il') ->orderByDesc('id') ->paginate(15, pageName: 'versioni'), 'title' => 'Piantine dei territori', ]); } }