import { index as accountsIndex } from '@/actions/App/Http/Controllers/Settings/AccountController'; import { index as automationRulesIndex } from '@/actions/App/Http/Controllers/Settings/AutomationRuleController'; import { index as categoriesIndex } from '@/actions/App/Http/Controllers/Settings/CategoryController'; import { index as labelsIndex } from '@/actions/App/Http/Controllers/Settings/LabelController'; import { index as mcpIndex } from '@/actions/App/Http/Controllers/Settings/McpTokenController'; import Heading from '@/components/heading'; import { Button } from '@/components/ui/button'; import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { Separator } from '@/components/ui/separator'; import { cn, isSameUrl, resolveUrl } from '@/lib/utils'; import { edit as editAccount } from '@/routes/account'; import { edit as editAppearance } from '@/routes/appearance'; import { edit as editDeleteAccount } from '@/routes/delete-account'; import { billing } from '@/routes/settings'; import { NavDivider, NavSectionHeader, SharedData, type NavItem, } from '@/types'; import { __ } from '@/utils/i18n'; import { Link, router, usePage } from '@inertiajs/react'; import { Menu } from 'lucide-react'; import { type PropsWithChildren } from 'react'; const getNavItems = ( subscriptionsEnabled: boolean, isDemoAccount: boolean, mcpEnabled: boolean, ): (NavItem | NavSectionHeader | NavDivider)[] => [ { type: 'nav-item' as const, title: 'Bank accounts', href: accountsIndex(), icon: null, }, { type: 'nav-item' as const, title: 'Connections', href: '/settings/connections', icon: null, }, { type: 'nav-item' as const, title: 'Automation rules', href: automationRulesIndex(), icon: null, }, { type: 'nav-item' as const, title: 'Categories', href: categoriesIndex(), icon: null, }, { type: 'nav-item' as const, title: 'Labels', href: labelsIndex(), icon: null, }, ...(mcpEnabled ? [ { type: 'nav-item' as const, title: 'AI Connector', href: mcpIndex(), icon: null, }, ] : []), { type: 'divider' }, { type: 'section-header', title: 'Profile Settings', }, ...(!isDemoAccount ? [ { type: 'nav-item' as const, title: 'User account', href: editAccount(), icon: null, }, ] : []), ...(subscriptionsEnabled && !isDemoAccount ? [ { type: 'nav-item' as const, title: 'Manage Plan', href: billing(), icon: null, }, ] : []), { type: 'nav-item' as const, title: 'Appearance', href: editAppearance(), icon: null, }, ...(!isDemoAccount ? [ { type: 'divider' as const }, { type: 'nav-item' as const, title: 'Delete Account', href: editDeleteAccount(), icon: null, }, ] : []), ]; function renderMobileNavGroups( items: (NavItem | NavSectionHeader | NavDivider)[], ) { const elements: React.ReactNode[] = []; let currentGroupLabel: string | null = null; let currentGroupItems: NavItem[] = []; const flushGroup = () => { if (currentGroupItems.length === 0) { return; } const groupKey = currentGroupLabel ?? 'default'; if (currentGroupLabel) { elements.push( {__(currentGroupLabel)} {currentGroupItems.map((item) => ( {__(item.title)} ))} , ); } else { elements.push( ...currentGroupItems.map((item) => ( {__(item.title)} )), ); } currentGroupItems = []; }; for (const item of items) { if (item.type === 'divider') { flushGroup(); elements.push(); currentGroupLabel = null; } else if (item.type === 'section-header') { flushGroup(); currentGroupLabel = item.title; } else { currentGroupItems.push(item); } } flushGroup(); return elements; } export default function SettingsLayout({ children }: PropsWithChildren) { const { subscriptionsEnabled, auth, features } = usePage().props; const isDemoAccount = auth?.isDemoAccount ?? false; // When server-side rendering, we only render the layout on the client... if (typeof window === 'undefined') { return null; } const currentPath = window.location.pathname; const sidebarNavItems = getNavItems( subscriptionsEnabled, isDemoAccount, features.mcp, ); const activeNavItem = sidebarNavItems.find( (item): item is NavItem => item.type === 'nav-item' && isSameUrl(currentPath, item.href), ); return ( {/* Mobile: dropdown select */} router.visit(value)} > {renderMobileNavGroups(sidebarNavItems)} {/* Desktop: sidebar nav */} {children} ); }