{{-- Polling pauses while a config is on screen: every poll re-renders this page, and that would put the private key into an HTTP response every five seconds. Traffic figures can wait the minute someone needs to copy a key. --}}

{{ __('vpn.title') }}

{{ __('vpn.subtitle') }}

@if ($hubEndpoint === '' || $hubPublicKey === '')

{{ __('vpn.hub_incomplete_title') }}

{{ __('vpn.hub_incomplete_body') }}

@endif {{-- Shown once. The private key exists only in this response; a reload loses it. --}} @if ($newConfig)

{{ __('vpn.config_ready', ['name' => $newConfigName]) }}

{{ __('vpn.config_once') }}

{{ $newConfig }}
{{ __('vpn.download') }} {{ $showQr ? __('vpn.qr_hide') : __('vpn.qr_show') }} {{-- Only surfaces when copying is impossible (no clipboard API outside a secure context) — silence would look like a dead button. --}}

{{ __('vpn.copy_failed') }}

@if ($qrSvg)
{!! $qrSvg !!}

{{ __('vpn.qr_hint') }}

@endif
@endif
{{-- Peer list --}}

{{ __('vpn.peers') }}

{{ $lastSync ? __('vpn.last_sync', ['time' => \Illuminate\Support\Carbon::parse($lastSync)->diffForHumans()]) : __('vpn.never_synced') }}
@if ($peers->isEmpty())

{{ __('vpn.empty') }}

@else
@foreach ($peers as $peer) @php $status = $peer->status(); $tone = [ 'online' => 'border-success-border bg-success-bg text-success', 'idle' => 'border-line-strong bg-surface-2 text-muted', 'blocked' => 'border-danger-border bg-danger-bg text-danger', 'pending' => 'border-warning-border bg-warning-bg text-warning', ][$status]; @endphp @endforeach
{{ __('vpn.peer') }} {{ __('vpn.owner') }} {{ __('vpn.address') }} {{ __('vpn.traffic') }} {{ __('vpn.handshake') }} {{ __('vpn.status') }} {{ __('vpn.actions') }}
{{ $peer->name }}
@if ($peer->host) {{ __('vpn.host_peer') }} @else {{ __('vpn.operator_peer') }} @endif
@if ($peer->owner) {{ $peer->owner->name }} @if ($peer->user_id === auth()->id()) {{ __('vpn.you') }} @endif @else {{ $peer->host ? __('vpn.host_peer') : __('vpn.no_owner') }} @endif
{{ $peer->allowed_ip }}
@if ($peer->endpoint)
{{ $peer->endpoint }}
@endif
↓ {{ \App\Support\Bytes::human($peer->rx_bytes) }}
↑ {{ \App\Support\Bytes::human($peer->tx_bytes) }}
{{ $peer->last_handshake_at?->diffForHumans() ?? __('vpn.never') }} {{ __('vpn.status_'.$status) }}
@can('downloadConfig', $peer) @endcan @can('block', $peer) @endcan @can('delete', $peer) @endcan
@endif
{{-- New access --}} @if ($canManage)

{{ __('vpn.add') }}

{{ __('vpn.owner_hint') }}

@error('ownerId')

{{ $message }}

@enderror
@error('storeConfig')

{{ $message }}

@enderror
{{ __('vpn.add') }} @endif {{-- Hub facts an operator needs when configuring a peer by hand --}}

{{ __('vpn.hub') }}

{{ __('vpn.endpoint') }}
{{ $hubEndpoint ?: '—' }}
{{ __('vpn.hub_key') }}
{{ $hubPublicKey ?: '—' }}
{{ __('vpn.subnet') }}
{{ config('provisioning.wireguard.subnet') }}