import { APP_CONFIGS } from '@/frontend/config/appMenus' import { useLogout, useSession } from '@/frontend/hooks/useAuth' import React from 'react' import { ActionIcon, Alert, AppShell, Avatar, Box, Burger, Button, Center, Group, Loader, LoadingOverlay, Menu, NavLink, Select, Stack, Text, ThemeIcon, Title, useComputedColorScheme, useMantineColorScheme } from '@mantine/core' import { useDisclosure } from '@mantine/hooks' import { useQuery } from '@tanstack/react-query' import { Link, useLocation, useMatches, useNavigate, useParams } from '@tanstack/react-router' import { TbAlertTriangle, TbApps, TbArrowLeft, TbChevronRight, TbClock, TbDashboard, TbDeviceMobile, TbHistory, TbLogout, TbMoon, TbSettings, TbSun, TbUser, TbUserCircle } from 'react-icons/tb' interface DashboardLayoutProps { children: React.ReactNode } export function DashboardLayout({ children }: DashboardLayoutProps) { const [mobileOpened, { toggle: toggleMobile }] = useDisclosure() const [desktopOpened, { toggle: toggleDesktop }] = useDisclosure(true) const { toggleColorScheme } = useMantineColorScheme() const computedColorScheme = useComputedColorScheme('light', { getInitialValueInEffect: true }) const location = useLocation() const navigate = useNavigate() const { appId } = useParams({ strict: false }) as { appId?: string } const matches = useMatches() const currentPath = matches[matches.length - 1]?.pathname // ─── Connect to auth system ────────────────────────── const { data: sessionData, isLoading: sessionLoading } = useSession() const user = sessionData?.user const logout = useLogout() // Redirect USER role to profile (pending approval) React.useEffect(() => { if (!sessionLoading && user?.role === 'USER') { navigate({ to: '/profile' }) } }, [user?.role, sessionLoading, navigate]) // ─── Fetch registered apps from database ───────────── const { data: appsData } = useQuery({ queryKey: ['apps'], queryFn: () => fetch('/api/apps', { credentials: 'include' }).then((r) => r.json()), staleTime: 60_000, }) // ─── Fetch system status from database ─────────────── const { data: systemStatus } = useQuery({ queryKey: ['system', 'status'], queryFn: () => fetch('/api/system/status', { credentials: 'include' }).then((r) => r.json()), refetchInterval: 30_000, // refresh every 30 seconds staleTime: 15_000, }) const globalNav = [ { label: 'Dashboard', icon: TbDashboard, to: '/dashboard' }, { label: 'Applications', icon: TbApps, to: '/apps' }, { label: 'Log Activity', icon: TbHistory, to: '/logs' }, { label: 'Error Reports', icon: TbAlertTriangle, to: '/bug-reports' }, { label: 'Users', icon: TbUser, to: '/users' }, ] const activeApp = appId ? APP_CONFIGS[appId] : null const navLinks = activeApp ? activeApp.menus : globalNav // Build app selector data from API const appSelectData = (appsData || []).map((app: any) => ({ value: app.id, label: app.name, })) // System status indicator const isOperational = systemStatus?.status === 'operational' const statusColor = isOperational ? '#10b981' : '#f59e0b' const statusText = isOperational ? 'All Systems Operational' : 'System Degraded' const handleLogout = () => { logout.mutate() } // Prevent dashboard flash for USER role while redirect is happening if (sessionLoading || user?.role === 'USER') { return (