@php $stats = $this->stats; $counts = $this->counts; $rows = $this->rows; @endphp
{{-- ── Header ─────────────────────────────────────────────────── --}}

{{ __('Your') }} {{ __('subscribers.') }}

{{ number_format($stats['all']) }} {{ __('users') }} {{ __('on the network') }} @if ($stats['at_risk'] > 0) · {{ number_format($stats['at_risk']) }} {{ __('at risk') }} {{ __('of not renewing.') }} @endif

@if ($flash)
{{ $flash }}
@endif {{-- ── Stat strip ─────────────────────────────────────────────── --}}
{{ __('All users') }} {{ number_format($stats['all']) }} {{ __('across the network') }}
{{ __('Expiring in 7 days') }} {{ number_format($stats['expiring']) }} {{ __('subscriptions ending in the next week') }}
{{ __('Online') }} {{ number_format($stats['online']) }} {{ $stats['online_share'] }}% · {{ __('connected right now') }}
{{ __('New this week') }} {{ number_format($stats['new_week']) }} {{ __('first joined in last 7 days') }}
{{ __('At risk') }} {{ number_format($stats['at_risk']) }} {{ __('no session in 30+ days') }}
{{-- ── Tabs and tools ─────────────────────────────────────────── --}}
@foreach ([ 'all' => [__('All'), $counts['all']], 'hotspot' => [__('Hotspot'), $counts['hotspot']], 'pppoe' => [__('PPPoE'), $counts['pppoe']], 'bindings' => [__('Bindings'), $counts['bindings']], ] as $key => [$label, $count]) @endforeach
@if ($showFilters)
{{ __('Sorted by') }} {{ __(\App\Livewire\Subscribers\Index::SORTS[$sort]) }}
@endif {{-- ── Table ──────────────────────────────────────────────────── --}}
@forelse ($rows as $row) @php $initials = strtoupper(mb_substr(preg_replace('/[^A-Za-z0-9]/', '', (string) $row->label) ?: '?', 0, 2)); // A stable colour per subscriber, so the same person // keeps the same dot every time you open the page. $hue = crc32((string) $row->key) % 360; @endphp {{-- The whole row opens the profile. The click is forwarded to the real link rather than setting window.location, so wire:navigate still applies and the page swaps rather than reloads. Anything already interactive is left alone — the checkbox, the row menu, the name itself — otherwise ticking a box or opening the menu would navigate away underneath you. A drag that selected text is not a click either. --}} url) x-data x-on:click=" if ($event.target.closest('a, button, input, label, .dropdown')) return; if (window.getSelection().toString() !== '') return; $el.querySelector('[data-row-link]').click(); " @endif> @empty @endforelse
{{ __('Contact') }} {{ __('Phone & email') }} {{ __('Plan') }} {{ __('Expiry') }} {{ __('Last online') }} {{ __('NAS') }}
{{ $initials }} @if ($row->url) {{ $row->label }} @else {{ $row->label }} @endif {{-- Hover card: enough to answer "who is this" without leaving the list. Teleported to the body so the table's own scrollbox cannot clip it. --}}
{{ $row->phone ?: ($row->mac ?: '—') }} @if ($row->email) {{ $row->email }} @endif {{ $row->plan ?: '—' }} @if ($row->plan_price) {{ money($row->plan_price, 0) }} @elseif ($row->purchases) {{ trans_choice(':count purchase|:count purchases', $row->purchases, ['count' => $row->purchases]) }} · {{ money($row->spent, 0) }} @endif @if ($row->expires_at) @if ($row->expires_at->isPast()) {{ __('Expired') }} @elseif ($row->expires_at->isToday()) {{ __('Expires today') }} @else {{ $row->expires_at->format('d M Y') }} @endif {{ $row->expires_at->format('H:i') }} @else @endif @if ($row->is_live) {{ __('Online') }} @elseif ($seen = $this->lastSeen[$row->key] ?? null) @php $seenAt = \Carbon\Carbon::parse($seen); @endphp {{ $seenAt->isToday() ? __('Today') : $seenAt->format('d M Y') }} {{ $seenAt->format('H:i') }} @else {{ __('Never') }} @endif {{ $row->router ?: '—' }}
@if ($tab === 'bindings') {{ __('No IP bindings on your routers. These are MAC addresses let through without paying — you add them on the MikroTik.') }} @elseif ($search !== '') {{ __('Nothing matches ":term".', ['term' => $search]) }} @else {{ __('Nobody here yet.') }} @endif