reset('search', 'datacenter', 'status'); } public function render() { $hosts = Host::query() ->withCount('instances') ->when($this->search !== '', function ($q) { $term = '%'.$this->search.'%'; $q->where(fn ($w) => $w->where('name', 'like', $term)->orWhere('public_ip', 'like', $term)); }) ->when($this->datacenter !== '', fn ($q) => $q->where('datacenter', $this->datacenter)) ->when($this->status !== '', fn ($q) => $q->where('status', $this->status)) ->orderBy('datacenter')->orderBy('name') ->get(); return view('livewire.admin.hosts', [ 'hosts' => $hosts, 'datacenters' => Datacenter::query()->orderBy('name')->get(), 'statuses' => ['pending', 'onboarding', 'active', 'error', 'disabled'], 'total' => Host::query()->count(), ...$this->vpnPeerState(), ]); } /** * One hub call for the whole list, not one per host — peers() already * returns every peer keyed by public key, so a row just looks itself up. * * The hub can be down, or (dev/self-hosted) the `vpn` compose profile not * running at all; either way this must not turn into a page-breaking * exception. $hubReachable false is what tells vpnState() to answer * "unknown" instead of guessing "silent" from an empty map — a wrong green * (or a wrong amber) is worse than an honest blank. * * @return array{vpnPeersByKey: array, vpnHubReachable: bool} */ private function vpnPeerState(): array { try { return ['vpnPeersByKey' => app(WireguardHub::class)->peers(), 'vpnHubReachable' => true]; } catch (\Throwable) { return ['vpnPeersByKey' => [], 'vpnHubReachable' => false]; } } }