apertoAlle = now()->timestamp; } public function invia(RichiesteServizio $richieste): void { if ($this->sito !== '' || now()->timestamp - $this->apertoAlle < self::SECONDI_MINIMI) { $this->inviata = true; return; } $chiave = 'richiesta-pubblica:' . sha1((string) request()->ip()); if (RateLimiter::tooManyAttempts($chiave, self::MASSIMO_ORA)) { $this->addError('nome', "Hai già mandato diverse richieste: riprova fra un po'."); return; } $this->validate([ 'tipo' => 'required|in:' . Richiesta::NUOVO . ',' . Richiesta::RICONSEGNA, 'nome' => 'required|string|min:3|max:100', 'numero' => ['nullable', 'required_if:tipo,' . Richiesta::RICONSEGNA, 'string', 'max:20', function ($attributo, $valore, $errore) { if ($this->tipo === Richiesta::RICONSEGNA && ! self::territori()->whereRaw('LOWER(numero) = ?', [Str::lower(trim((string) $valore))])->exists()) { $errore("Scegli il territorio dall'elenco."); } }], 'note' => 'nullable|string|max:1000', ], [ 'nome.required' => 'Scrivi nome e cognome.', 'nome.min' => 'Scrivi nome e cognome.', 'numero.required_if' => 'Scegli il territorio che riconsegni.', ]); RateLimiter::hit($chiave, 3600); $richieste->registra($this->tipo, $this->nome, $this->numero, $this->note); $this->reset(['nome', 'numero', 'note']); $this->inviata = true; } public function nuova(): void { $this->reset(['tipo', 'nome', 'numero', 'note', 'inviata']); $this->apertoAlle = now()->timestamp; } /** * I territori che si possono riconsegnare: quelli attivi e quelli ancora * fuori anche se nel frattempo disattivati. */ private static function territori(): Builder { return Territorio::query()->where(fn ($q) => $q->where('attivo', true) ->orWhereHas('assegnazioni', fn ($a) => $a->whereNull('returned_at'))); } /** * Le proposte del campo con ricerca (): solo numero e zona. Il * valore è il numero, come lo salva la richiesta. */ private static function opzioniTerritori(): array { return self::territori()->with('zona')->get() ->sortBy('numero', SORT_NATURAL) ->map(fn (Territorio $t) => array_filter([ 'valore' => (string) $t->numero, 'etichetta' => "N° {$t->numero}", 'dettaglio' => $t->zona?->nome, 'chiavi' => [(string) $t->numero, (string) $t->zona?->nome], ], fn ($v) => $v !== null)) ->values() ->all(); } public function render() { return view('livewire.richieste.modulo-richiesta', [ 'congregazione' => Setting::instance()->congregazione_nome ?: 'TerManager2', // Solo quando serve: chi chiede un territorio nuovo non vede l'elenco. 'opzioniTerritori' => $this->tipo === Richiesta::RICONSEGNA && ! $this->inviata ? self::opzioniTerritori() : [], ])->layout('components.layouts.guest', ['title' => 'Richiesta territorio']); } }