@@ -29,6 +29,9 @@ import {
2929 Link2 ,
3030 MessageCircle ,
3131 User ,
32+ Activity ,
33+ AlertTriangle ,
34+ PackageOpen ,
3235} from 'lucide-react'
3336import { cn } from '@/lib/utils'
3437import { useAuth } from '@/hooks/useAuth'
@@ -85,6 +88,18 @@ const settingsSubNav: {
8588 } ,
8689]
8790
91+ /** Admin sub-navigation items */
92+ const adminSubNav : { to : string ; icon : typeof BarChart3 ; label : string } [ ] = [
93+ { to : '/admin' , icon : BarChart3 , label : 'Overview' } ,
94+ { to : '/admin/workspaces' , icon : Building2 , label : 'Workspaces' } ,
95+ { to : '/admin/abuse' , icon : AlertTriangle , label : 'Abuse' } ,
96+ { to : '/admin/activity' , icon : Activity , label : 'Activity' } ,
97+ { to : '/admin/beta-users' , icon : Users , label : 'Beta Users' } ,
98+ { to : '/admin/licenses' , icon : ShieldCheck , label : 'Licenses' } ,
99+ { to : '/admin/marketplace' , icon : Store , label : 'Marketplace' } ,
100+ { to : '/admin/review-queue' , icon : PackageOpen , label : 'Review Queue' } ,
101+ ]
102+
88103export function RootLayout ( ) {
89104 const { user, signOut } = useAuth ( )
90105 const { isSuperAdmin } = useSuperAdmin ( )
@@ -96,14 +111,15 @@ export function RootLayout() {
96111 const [ sidebarOpen , setSidebarOpen ] = useState ( false )
97112
98113 const isOnSettings = location . pathname === '/settings' || location . pathname . startsWith ( '/settings/' )
114+ const isOnAdmin = location . pathname === '/admin' || location . pathname . startsWith ( '/admin/' )
99115 const [ settingsExpanded , setSettingsExpanded ] = useState ( isOnSettings )
116+ const [ adminExpanded , setAdminExpanded ] = useState ( isOnAdmin )
100117
101- // Auto-expand settings when navigating to a settings page
118+ // Auto-expand collapsible sections when navigating to them
102119 useEffect ( ( ) => {
103- if ( isOnSettings ) {
104- setSettingsExpanded ( true )
105- }
106- } , [ isOnSettings ] )
120+ if ( isOnSettings ) setSettingsExpanded ( true )
121+ if ( isOnAdmin ) setAdminExpanded ( true )
122+ } , [ isOnSettings , isOnAdmin ] )
107123
108124 const metadata = ( user ?. user_metadata ?? { } ) as Record < string , unknown >
109125 const displayName = ( typeof metadata . full_name === 'string' ? metadata . full_name : null )
@@ -164,11 +180,6 @@ export function RootLayout() {
164180 // Collapsed mode: icon-only on tablet
165181 const collapsed = isTablet
166182
167- // Build full nav items including admin if super admin
168- const allNavItems = isSuperAdmin
169- ? [ ...navItems , { to : '/admin' as const , icon : Shield , label : 'Admin' } ]
170- : navItems
171-
172183 return (
173184 < div className = "flex h-screen overflow-hidden bg-gray-950" >
174185 { /* Backdrop overlay for mobile sidebar */ }
@@ -218,7 +229,7 @@ export function RootLayout() {
218229
219230 { /* Navigation */ }
220231 < nav className = { cn ( 'flex-1 overflow-y-auto py-4' , collapsed ? 'px-2' : 'px-3' ) } >
221- { allNavItems . map ( ( { to, icon : Icon , label } ) => (
232+ { navItems . map ( ( { to, icon : Icon , label } ) => (
222233 < NavLink
223234 key = { to }
224235 to = { to }
@@ -318,6 +329,74 @@ export function RootLayout() {
318329 </ div >
319330 </ div >
320331 ) }
332+
333+ { /* ─── Admin collapsible group (super admin only) ─── */ }
334+ { isSuperAdmin && (
335+ collapsed ? (
336+ < NavLink
337+ to = "/admin"
338+ className = { cn (
339+ 'flex items-center justify-center rounded-lg p-2.5 text-sm font-medium transition-colors' ,
340+ isOnAdmin
341+ ? 'bg-gray-800 text-gray-100'
342+ : 'text-gray-400 hover:bg-gray-800/50 hover:text-gray-200' ,
343+ ) }
344+ title = "Admin"
345+ >
346+ < Shield className = "h-5 w-5 shrink-0" />
347+ </ NavLink >
348+ ) : (
349+ < div className = "mt-1" >
350+ < button
351+ type = "button"
352+ onClick = { ( ) => setAdminExpanded ( prev => ! prev ) }
353+ className = { cn (
354+ 'flex w-full items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium transition-colors' ,
355+ isOnAdmin
356+ ? 'bg-gray-800 text-gray-100'
357+ : 'text-gray-400 hover:bg-gray-800/50 hover:text-gray-200' ,
358+ ) }
359+ >
360+ < Shield className = "h-5 w-5 shrink-0" />
361+ < span className = "flex-1 text-left" > Admin</ span >
362+ < ChevronDown
363+ className = { cn (
364+ 'h-4 w-4 shrink-0 transition-transform duration-200' ,
365+ adminExpanded && 'rotate-180' ,
366+ ) }
367+ />
368+ </ button >
369+
370+ < div
371+ className = { cn (
372+ 'overflow-hidden transition-all duration-200' ,
373+ adminExpanded ? 'max-h-[400px] opacity-100' : 'max-h-0 opacity-0' ,
374+ ) }
375+ >
376+ < div className = "mt-1 space-y-0.5 pl-2" >
377+ { adminSubNav . map ( ( { to, icon : Icon , label } ) => (
378+ < NavLink
379+ key = { to }
380+ to = { to }
381+ end
382+ className = { ( { isActive } ) =>
383+ cn (
384+ 'flex items-center gap-2.5 rounded-md px-3 py-1.5 text-[13px] font-medium transition-colors' ,
385+ isActive
386+ ? 'bg-gray-800/80 text-gray-200'
387+ : 'text-gray-500 hover:bg-gray-800/40 hover:text-gray-300' ,
388+ )
389+ }
390+ >
391+ < Icon className = "h-3.5 w-3.5 shrink-0" />
392+ { label }
393+ </ NavLink >
394+ ) ) }
395+ </ div >
396+ </ div >
397+ </ div >
398+ )
399+ ) }
321400 </ nav >
322401
323402 { /* User footer — hidden when collapsed */ }
0 commit comments