@php use App\Enums\ProofStatus; use App\Models\SubscriptionPayment; $settings = app(\App\Services\SettingsRepository::class); $user = auth()->user(); // Cheap enough to run on every page, and it is the number the team lives by. $pending = SubscriptionPayment::where('status', ProofStatus::Pending)->count(); /* * Navigation is data, not markup. Each entry names the capability it * needs, so an accountant never sees the staff screen and a support agent * never sees the plan editor. */ $sections = [ [ 'label' => null, 'items' => [ ['route' => 'dashboard', 'label' => 'Dashboard', 'icon' => 'home'], ['route' => 'payments.queue', 'label' => 'Verification Queue', 'icon' => 'inbox', 'can' => 'verify', 'badge' => $pending, 'accent' => true], ], ], [ 'label' => 'Customers', 'items' => [ ['route' => 'tenants.index', 'label' => 'Shops', 'icon' => 'building'], ['route' => 'subscriptions.index', 'label' => 'Subscriptions', 'icon' => 'sparkles'], ['route' => 'invoices.index', 'label' => 'Invoices', 'icon' => 'receipt'], ['route' => 'payments.index', 'label' => 'Payment History', 'icon' => 'exchange'], ], ], [ 'label' => 'Catalogue', 'items' => [ ['route' => 'products.index', 'label' => 'Products', 'icon' => 'box', 'can' => 'catalog'], ['route' => 'plans.index', 'label' => 'Plans & Pricing', 'icon' => 'layers', 'can' => 'catalog'], ['route' => 'accounts.index', 'label' => 'Receiving Accounts', 'icon' => 'wallet', 'can' => 'catalog'], ], ], [ 'label' => 'Reports', 'items' => [ ['route' => 'reports.revenue', 'label' => 'Revenue', 'icon' => 'chart'], ['route' => 'reports.growth', 'label' => 'Growth & Churn', 'icon' => 'trending'], ], ], [ 'label' => 'System', 'items' => [ ['route' => 'announcements.index', 'label' => 'Announcements', 'icon' => 'info', 'can' => 'catalog'], ['route' => 'staff.index', 'label' => 'Staff Users', 'icon' => 'user-cog', 'can' => 'staff'], ['route' => 'activity.index', 'label' => 'Activity Log', 'icon' => 'clock'], ['route' => 'settings.index', 'label' => 'Settings', 'icon' => 'cog', 'can' => 'catalog'], ], ], ]; /* * Which single nav entry should light up. * * Matching "everything under the same module" lights up all four Setup * links at once, because they all live under `settings.`. Matching only the * exact route leaves nothing lit while you are on products.create. * * So instead of asking each entry "are you active?", ask which entry is the * *best* match for the current route, and light only that one. Specificity * wins: an exact hit beats a nested hit, which beats a same-module hit. */ $navRoutes = []; foreach ($sections as $section) { foreach ($section['items'] as $item) { $navRoutes[] = $item['route']; } } $score = function (string $route) : int { $current = (string) request()->route()?->getName(); if ($current === '') { return 0; } if ($current === $route) { return 1000; // settings.taxes } if (str_starts_with($current, $route.'.')) { return 500 + substr_count($route, '.'); // settings.receipts.edit } $module = \Illuminate\Support\Str::beforeLast($route, '.'); if ($module !== $route && ($current === $module || str_starts_with($current, $module.'.'))) { return 1 + substr_count($module, '.'); // products.create -> Products } return 0; }; $bestRoute = null; $bestScore = 0; foreach ($navRoutes as $candidate) { if (($points = $score($candidate)) > $bestScore) { $bestScore = $points; $bestRoute = $candidate; } } $isActive = fn (string $route): bool => $route === $bestRoute; $visible = function (array $item) use ($user): bool { return match ($item['can'] ?? null) { 'verify' => (bool) $user?->canVerifyPayments(), 'catalog' => (bool) $user?->canManageCatalog(), 'tenants' => (bool) $user?->canManageTenants(), 'staff' => (bool) $user?->canManageStaff(), default => true, }; }; @endphp {{-- Below lg the sidebar collapses off-canvas behind this button. --}}