import { createFileRoute, Outlet, Link, redirect, useRouter } from '@tanstack/react-router' import { useQuery } from '@tanstack/react-query' import { queryOptions } from '@tanstack/react-query' import { useEffect, useState } from 'react' import { api } from '@/lib/api-client' import { useAuthStore } from '@/stores/auth.store' import { myPermissionsOptions } from '@/api/rbac' import { moduleListOptions } from '@/api/modules' import { Avatar } from '@/components/shared/avatar-upload' import { Button } from '@/components/ui/button' import { Users, UserRound, HelpCircle, Shield, UserCog, LogOut, User, Wrench, Package, ClipboardList, FolderOpen, KeyRound, Settings, PanelLeftClose, PanelLeft, CalendarDays, GraduationCap, CalendarRange, BookOpen, BookMarked, Package2, Tag, Truck, ShoppingCart } from 'lucide-react' export const Route = createFileRoute('/_authenticated')({ beforeLoad: () => { const { token } = useAuthStore.getState() if (!token) { throw redirect({ to: '/login' }) } }, component: AuthenticatedLayout, }) function StoreLogo() { const token = useAuthStore((s) => s.token) const [src, setSrc] = useState(null) const { data: storeData } = useQuery(queryOptions({ queryKey: ['store'], queryFn: () => api.get<{ id: string; name: string }>('/v1/store'), enabled: !!token, })) const { data: filesData } = useQuery(queryOptions({ queryKey: ['files', 'company', storeData?.id ?? ''], queryFn: () => api.get<{ data: { id: string; path: string }[] }>('/v1/files', { entityType: 'company', entityId: storeData?.id }), enabled: !!storeData?.id, })) const logoFile = filesData?.data?.find((f) => f.path.includes('/logo-')) useEffect(() => { if (!logoFile || !token) { setSrc(null); return } let cancelled = false let blobUrl: string | null = null async function load() { try { const res = await fetch(`/v1/files/serve/${logoFile!.path}`, { headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok || cancelled) return const blob = await res.blob() if (!cancelled) { blobUrl = URL.createObjectURL(blob); setSrc(blobUrl) } } catch { /* ignore */ } } load() return () => { cancelled = true; if (blobUrl) URL.revokeObjectURL(blobUrl) } }, [logoFile?.path, token]) if (src) { return {storeData?.name } return

{storeData?.name ?? 'LunarFront'}

} function NavLink({ to, icon, label, collapsed }: { to: string; icon: React.ReactNode; label: string; collapsed?: boolean }) { return ( {icon} {!collapsed && label} ) } function NavGroup({ label, children, collapsed }: { label: string; children: React.ReactNode; collapsed?: boolean }) { const [open, setOpen] = useState(true) if (collapsed) return
{children}
return (
{open &&
{children}
}
) } function AuthenticatedLayout() { const router = useRouter() const user = useAuthStore((s) => s.user) const logout = useAuthStore((s) => s.logout) const hasPermission = useAuthStore((s) => s.hasPermission) const setPermissions = useAuthStore((s) => s.setPermissions) const permissionsLoaded = useAuthStore((s) => s.permissionsLoaded) // Fetch permissions on mount const { data: permData } = useQuery({ ...myPermissionsOptions(), enabled: !!useAuthStore.getState().token, }) // Fetch enabled modules const { data: modulesData } = useQuery({ ...moduleListOptions(), enabled: !!useAuthStore.getState().token, }) const enabledModules = new Set( (modulesData?.data ?? []).filter((m) => m.enabled && m.licensed).map((m) => m.slug), ) const isModuleEnabled = (slug: string) => enabledModules.has(slug) useEffect(() => { if (permData?.permissions) { setPermissions(permData.permissions) } }, [permData, setPermissions]) function handleLogout() { logout() router.navigate({ to: '/login', replace: true }) } const canViewAccounts = !permissionsLoaded || hasPermission('accounts.view') const canViewRepairs = !permissionsLoaded || hasPermission('repairs.view') const canViewLessons = !permissionsLoaded || hasPermission('lessons.view') const canViewInventory = !permissionsLoaded || hasPermission('inventory.view') const canViewUsers = !permissionsLoaded || hasPermission('users.view') const canViewPOS = !permissionsLoaded || hasPermission('pos.view') const [collapsed, setCollapsed] = useState(false) return (
) }