22
33import React , { useState , useEffect } from 'react' ;
44import { useRouter , usePathname } from 'next/navigation' ;
5- import { LayoutDashboard , Building2 , FileText , MessageSquare , LogOut , Menu , X , Settings , Users , AlertTriangle , Bot } from 'lucide-react' ;
5+ import { LayoutDashboard , Building2 , FileText , MessageSquare , LogOut , Menu , X , Settings , Users , AlertTriangle , Bot , AlignLeft , ChevronLeft , ChevronRight } from 'lucide-react' ;
66import Sidebar , { SidebarSection } from '@/components/ui/Sidebar' ;
77import { useAuth } from '@/contexts/AuthContext' ;
88import { useBusiness , BusinessProvider } from '@/contexts/BusinessContext' ;
@@ -67,85 +67,110 @@ function DashboardLayoutInner({
6767
6868 return (
6969 < ProtectedRoute >
70- < div className = "min- h-screen bg-[var(--bg-secondary)] flex font-sans" >
70+ < div className = "flex h-screen bg-[var(--bg-secondary)] font-sans overflow-hidden " >
7171
7272 { /* Mobile Header */ }
73- < div className = "lg:hidden fixed top-0 left-0 right-0 z-50 bg-[var(--bg-primary)] border-b border-[var(--border-subtle)] px-4 py-3 flex items-center justify-between" >
74- < h1 className = "text-h2 font-space tracking-tight text-[var(--brand-primary)] font-bold" > Taimako</ h1 >
73+ < div className = "lg:hidden fixed top-0 left-0 right-0 z-50 bg-[var(--bg-primary)] border-b border-[var(--border-subtle)] px-4 py-3 flex items-center justify-between h-16 " >
74+ < h1 className = "text-xl font-space tracking-tight text-[var(--brand-primary)] font-bold" > Taimako</ h1 >
7575 < button
76- onClick = { ( ) => setMobileMenuOpen ( ! mobileMenuOpen ) }
76+ onClick = { ( ) => setMobileMenuOpen ( true ) }
7777 className = "p-2 hover:bg-[var(--bg-secondary)] rounded-[var(--radius-sm)] transition-colors text-[var(--text-primary)]"
78+ aria-label = "Open Menu"
7879 >
79- { mobileMenuOpen ? < X className = "w-6 h-6" /> : < Menu className = "w-6 h-6" /> }
80+ < AlignLeft className = "w-6 h-6" />
8081 </ button >
8182 </ div >
8283
8384 { /* Sidebar - Desktop */ }
84- < div className = { sidebarCollapsed ? "hidden lg:block w-16 transition-all duration-300 relative z-40" : "hidden lg:block w-60 transition-all duration-300 relative z-40" } >
85- < div className = "fixed top-0 left-0 h-full bg-[var(--bg-primary)] border-r border-[var(--border-subtle)]" >
86- < div className = "h-full flex flex-col w-full" >
87- { /* Sidebar Header */ }
88- < div className = "p-6 border-b border-[var(--border-subtle)] flex items-center justify-between" >
89- { ! sidebarCollapsed && (
90- < h1 className = "text-xl font-space font-bold text-[var(--brand-primary)] tracking-tight" > Taimako</ h1 >
91- ) }
92- < button onClick = { ( ) => setSidebarCollapsed ( ! sidebarCollapsed ) } className = "p-1 hover:bg-[var(--bg-tertiary)] rounded text-[var(--text-secondary)]" >
93- { sidebarCollapsed ? < Menu className = "w-4 h-4" /> : < Menu className = "w-4 h-4" /> }
94- </ button >
95- </ div >
85+ < aside
86+ className = { `hidden lg:flex flex-col border-r border-[var(--border-subtle)] bg-[var(--bg-primary)] transition-all duration-300 ease-in-out relative z-40 ${ sidebarCollapsed ? 'w-16' : 'w-64'
87+ } `}
88+ >
89+ { /* Sidebar Header */ }
90+ < div className = "h-16 flex items-center justify-between px-4 border-b border-[var(--border-subtle)] flex-shrink-0" >
91+ { ! sidebarCollapsed && (
92+ < h1 className = "text-xl font-space font-bold text-[var(--brand-primary)] tracking-tight truncate" > Taimako</ h1 >
93+ ) }
94+ < button
95+ onClick = { ( ) => setSidebarCollapsed ( ! sidebarCollapsed ) }
96+ className = { `p-1.5 hover:bg-[var(--bg-tertiary)] rounded-md text-[var(--text-secondary)] transition-colors ${ sidebarCollapsed ? 'mx-auto' : '' } ` }
97+ aria-label = { sidebarCollapsed ? "Expand Sidebar" : "Collapse Sidebar" }
98+ >
99+ { sidebarCollapsed ? < ChevronRight className = "w-4 h-4" /> : < ChevronLeft className = "w-4 h-4" /> }
100+ </ button >
101+ </ div >
96102
97- { /* Sidebar Navigation */ }
98- < div className = "flex-1 overflow-y-auto w-full " >
99- < Sidebar sections = { sidebarSections } collapsed = { sidebarCollapsed } />
100- </ div >
103+ { /* Sidebar Navigation */ }
104+ < div className = "flex-1 overflow-y-auto overflow-x-hidden custom-scrollbar " >
105+ < Sidebar sections = { sidebarSections } collapsed = { sidebarCollapsed } />
106+ </ div >
101107
102- { /* Sidebar Footer */ }
103- < div className = "p-4 border-t border-[var(--border-subtle)]" >
104- < div className = "flex flex-col gap-2" >
105- < div className = { `flex items-center gap-3 px-2 ${ sidebarCollapsed ? 'justify-center' : '' } ` } >
106- < div className = "w-8 h-8 rounded-full bg-[var(--brand-secondary)] flex items-center justify-center text-white font-bold text-xs flex-shrink-0" >
107- { user ?. name ?. [ 0 ] || user ?. email ?. [ 0 ] || 'U' }
108- </ div >
109- { ! sidebarCollapsed && (
110- < div className = "flex-1 overflow-hidden min-w-0" >
111- < div className = "text-sm font-medium text-[var(--text-primary)] truncate" title = { user ?. name } > { user ?. name || 'User' } </ div >
112- < div className = "text-xs text-[var(--text-tertiary)] truncate" title = { user ?. email } > { user ?. email } </ div >
113- </ div >
114- ) }
115- </ div >
116- < Button
117- variant = "ghost"
118- className = { `w-full ${ sidebarCollapsed ? 'justify-center px-0' : 'justify-start' } mt-2 text-[var(--text-secondary)] hover:text-[var(--status-error)] hover:bg-[var(--bg-tertiary)]` }
119- onClick = { logout }
120- >
121- < LogOut className = "w-4 h-4" />
122- { ! sidebarCollapsed && < span className = "ml-2" > Logout</ span > }
123- </ Button >
108+ { /* Sidebar Footer */ }
109+ < div className = "p-4 border-t border-[var(--border-subtle)] flex-shrink-0" >
110+ < div className = "flex flex-col gap-2" >
111+ < div className = { `flex items-center gap-3 px-2 ${ sidebarCollapsed ? 'justify-center' : '' } ` } >
112+ < div className = "w-8 h-8 rounded-full bg-[var(--brand-secondary)] flex items-center justify-center text-white font-bold text-xs flex-shrink-0 ring-2 ring-white" >
113+ { user ?. name ?. [ 0 ] || user ?. email ?. [ 0 ] || 'U' }
124114 </ div >
115+ { ! sidebarCollapsed && (
116+ < div className = "flex-1 overflow-hidden min-w-0" >
117+ < div className = "text-sm font-medium text-[var(--text-primary)] truncate" title = { user ?. name } > { user ?. name || 'User' } </ div >
118+ < div className = "text-xs text-[var(--text-tertiary)] truncate" title = { user ?. email } > { user ?. email } </ div >
119+ </ div >
120+ ) }
125121 </ div >
122+ < Button
123+ variant = "ghost"
124+ className = { `w-full ${ sidebarCollapsed ? 'justify-center px-0' : 'justify-start' } mt-2 text-[var(--text-secondary)] hover:text-[var(--status-error)] hover:bg-[var(--bg-tertiary)]` }
125+ onClick = { logout }
126+ >
127+ < LogOut className = "w-4 h-4" />
128+ { ! sidebarCollapsed && < span className = "ml-2" > Logout</ span > }
129+ </ Button >
126130 </ div >
127131 </ div >
128- </ div >
132+ </ aside >
129133
130- { /* Mobile Sidebar */ }
134+ { /* Mobile Sidebar Overlay */ }
131135 { mobileMenuOpen && (
132- < div className = "lg:hidden fixed inset-0 z-50 bg-black/40 backdrop-blur-sm" onClick = { ( ) => setMobileMenuOpen ( false ) } >
136+ < div className = "lg:hidden fixed inset-0 z-[60]" >
137+ { /* Backdrop */ }
133138 < div
134- className = "w-72 h-full bg-[var(--bg-primary)] border-r border-[var(--border-subtle)] shadow-2xl"
139+ className = "absolute inset-0 bg-black/40 backdrop-blur-sm transition-opacity opacity-100"
140+ onClick = { ( ) => setMobileMenuOpen ( false ) }
141+ />
142+
143+ { /* Drawer */ }
144+ < div
145+ className = "absolute top-0 left-0 bottom-0 w-72 bg-[var(--bg-primary)] shadow-2xl transform transition-transform duration-300 ease-out translate-x-0"
135146 onClick = { ( e ) => e . stopPropagation ( ) }
136147 >
137- < div className = "h-full flex flex-col" >
138- < div className = "p-6 border-b border-[var(--border-subtle)] flex justify-between items-center" >
139- < h1 className = "text-2xl font-space font-bold text-[var(--brand-primary)]" > Taimako</ h1 >
140- < button onClick = { ( ) => setMobileMenuOpen ( false ) } > < X className = "w-6 h-6 text-[var(--text-secondary)]" /> </ button >
148+ < div className = "flex flex-col h-full" >
149+ < div className = "h-16 flex items-center justify-between px-6 border-b border-[var(--border-subtle)]" >
150+ < h1 className = "text-xl font-space font-bold text-[var(--brand-primary)]" > Taimako</ h1 >
151+ < button
152+ onClick = { ( ) => setMobileMenuOpen ( false ) }
153+ className = "p-2 -mr-2 text-[var(--text-secondary)] hover:bg-[var(--bg-tertiary)] rounded-md"
154+ >
155+ < X className = "w-5 h-5" />
156+ </ button >
141157 </ div >
142158
143159 < div className = "flex-1 overflow-y-auto" >
144- < Sidebar sections = { sidebarSections } />
160+ < Sidebar sections = { sidebarSections } onItemClick = { ( ) => setMobileMenuOpen ( false ) } />
145161 </ div >
146162
147163 < div className = "p-6 border-t border-[var(--border-subtle)]" >
148- < Button onClick = { logout } variant = "ghost" className = "w-full justify-start text-[var(--text-secondary)]" >
164+ < div className = "flex items-center gap-3 mb-6" >
165+ < div className = "w-10 h-10 rounded-full bg-[var(--brand-secondary)] flex items-center justify-center text-white font-bold text-sm ring-2 ring-white" >
166+ { user ?. name ?. [ 0 ] || user ?. email ?. [ 0 ] || 'U' }
167+ </ div >
168+ < div className = "flex-1 overflow-hidden" >
169+ < div className = "text-sm font-medium text-[var(--text-primary)] truncate" > { user ?. name || 'User' } </ div >
170+ < div className = "text-xs text-[var(--text-tertiary)] truncate" > { user ?. email } </ div >
171+ </ div >
172+ </ div >
173+ < Button onClick = { logout } variant = "ghost" className = "w-full justify-start text-[var(--text-secondary)] hover:bg-[var(--bg-tertiary)]" >
149174 < LogOut className = "w-5 h-5 mr-3" /> Logout
150175 </ Button >
151176 </ div >
@@ -154,40 +179,35 @@ function DashboardLayoutInner({
154179 </ div >
155180 ) }
156181
157- { /* Main Content */ }
158- < div className = "flex-1 flex flex-col min-w-0 transition-all duration-300 " >
182+ { /* Main Content Area */ }
183+ < main className = "flex-1 flex flex-col min-w-0 bg-[var(--bg-secondary)] overflow-hidden relative " >
159184
160- { /* Missing Key Warning Banner */ }
185+ { /* Missing Key Warning */ }
161186 { apiKeyMissing && ! checkingKey && (
162- < div className = "bg-[var(--warning-bg)] border-l-4 border-[var(--warning)] p-4 sticky top-0 z-30 shadow-md " >
187+ < div className = "bg-[var(--warning-bg)] border-l-4 border-[var(--warning)] p-4 shadow-sm z-30 flex-shrink-0 " >
163188 < div className = "flex items-center" >
164189 < div className = "flex-shrink-0" >
165190 < AlertTriangle className = "h-5 w-5 text-[var(--warning)]" aria-hidden = "true" />
166191 </ div >
167192 < div className = "ml-3" >
168193 < p className = "text-sm text-[var(--warning-text)]" >
169194 < span className = "font-bold" > Action Required: </ span >
170- You must set your Google Gemini API Key in < span className = "font-bold cursor-pointer underline" onClick = { ( ) => router . push ( '/dashboard/business' ) } > Settings</ span > to use the AI features. Access to other pages is restricted until configured .
195+ You must set your Google Gemini API Key in < span className = "font-bold cursor-pointer underline hover:text-opacity-80 " onClick = { ( ) => router . push ( '/dashboard/business' ) } > Settings</ span > to use AI features.
171196 </ p >
172197 </ div >
173198 </ div >
174199 </ div >
175200 ) }
176201
177- < div className = { `h-full ${ apiKeyMissing ? '' : 'pt-16 lg:pt-0' } ` } >
178- { /* If blocked, mobile header might overlap if we don't account for paddingTop.
179- The original had pt-16 lg:pt-0. If we add banner, we shift content down.
180- Actually, just keep original padding. Content is children.
181- */ }
182- < div className = "pt-16 lg:pt-0 h-full" >
183- < main className = "p-4 lg:p-8 h-full overflow-y-auto" >
184- < div className = "max-w-[1440px] mx-auto w-full h-full" >
185- { children }
186- </ div >
187- </ main >
202+ { /* Scrollable Content */ }
203+ < div className = "flex-1 overflow-y-auto scroll-smooth" >
204+ < div className = "pt-16 lg:pt-0 min-h-full" >
205+ < div className = "p-4 lg:p-8 max-w-[1600px] mx-auto w-full" >
206+ { children }
207+ </ div >
188208 </ div >
189209 </ div >
190- </ div >
210+ </ main >
191211 </ div >
192212 </ ProtectedRoute >
193213 ) ;
0 commit comments