@if (auth()->user()->roles()->exists() || auth()->user()->permissions()->exists()) {{-- One navigation, for everyone who has a role. A Wi-Fi seller used to get a separate cut-down "Reseller Panel" holding a dashboard, customers and a wallet — which made no sense for someone who brings their own MikroTik and runs their own hotspot off it. They need the routers, the hotspot manager, the portal designer and the rest exactly as the platform owner does. What each audience may see is decided per page and per host now, not by handing them a different menu. --}} {{-- Admin navigation. Grouped the way an ISP thinks about its own business — who the subscribers are, what the network is doing, where the money is — rather than by which subsystem a page happens to belong to. Anything that does not fit those groups lives under "Extra" at the bottom instead of being forced into one. --}} @php // Opens a group when the page you are on lives inside it. $isOn = fn (array $routes) => collect($routes)->contains(fn ($r) => request()->routeIs($r)); $deviceRoutes = ['mikrotik-sync', 'mikrotik-link', 'mikrotik-hotspot-manager', 'portal-designer', 'equipment']; $routerSetupRoutes = ['mikrotik-ip-setup', 'mikrotik-pppoe-setup', 'mikrotik-radius-setup', 'mikrotik-firewall-setup', 'mikrotik-walled-garden', 'mikrotik-queue-setup', 'mikrotik-vpn-setup', 'mikrotik-interface-setup', 'mikrotik-backup-setup']; $billingRoutes = ['payment-ledger', 'payment-collection', 'payment-invoice', 'collection-edit', 'admin.expenses', 'admin.purchase-requests']; $commsRoutes = ['sms-setup', 'sms-notifications', 'whatsapp', 'campaigns', 'promo-banners']; $analyticsRoutes = ['admin.profit-summary', 'collection-report.index', 'customer-summary', 'dis-report']; $accessRoutes = ['admin-users', 'admin-roles', 'admin-tenants']; $logRoutes = ['admin.activity-logs', 'admin.login-logs', 'admin.system-logs', 'mikrotik-log-viewer']; // The platform owner oversees sellers; they do not run a network of // their own. Anything that configures hardware is a seller's job and // is hidden from them, so the console stays about the business. $isPlatformOwner = auth()->user()?->hasRole('Super Admin') ?? false; // Cheap counts for the at-a-glance badges. Both models scope // themselves to the signed-in seller, so the owner sees the totals // across every tenant and a seller sees only their own. $subscriberCount = \App\Models\CustomersInfo::count(); $routerCount = \App\Models\RouterList::count(); // How many devices are online right now. // // Read from the accounting table the minute poller writes, not from // the routers: the Live sessions page queries every router over the // tunnel, and doing that on every page render would put a router // round-trip in front of the whole admin. The trade is that this // badge can be up to a minute stale, which is the right trade for a // number in a sidebar. `ended_at` is null while a session is up. $liveCount = \App\Models\HotspotAccounting::whereNull('ended_at') ->where('last_seen_at', '>=', now()->subMinutes(3)) ->count(); @endphp @else @endif