Skip to content

Commit 1afe8b1

Browse files
committed
refactor(dashboard): Simplify CompanyHeader and CompanySidebar components
- Remove complex breadcrumb generation logic from CompanyHeader - Streamline header layout with minimal notification center - Add sidebar collapse/expand functionality to CompanySidebar - Implement toggle button for sidebar width - Improve responsive design and user interaction for sidebar - Reduce visual complexity while maintaining core functionality - Optimize layout for better mobile and desktop experience
1 parent 60f4e70 commit 1afe8b1

File tree

2 files changed

+84
-121
lines changed

2 files changed

+84
-121
lines changed
Lines changed: 2 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,12 @@
11
'use client'
22

33
import React from 'react'
4-
import { SidebarTrigger } from '@/components/ui/sidebar'
5-
import { Separator } from '@/components/ui/separator'
6-
import {
7-
Breadcrumb,
8-
BreadcrumbItem,
9-
BreadcrumbLink,
10-
BreadcrumbList,
11-
BreadcrumbPage,
12-
BreadcrumbSeparator,
13-
} from '@/components/ui/breadcrumb'
14-
import { usePathname } from 'next/navigation'
15-
import { useCompanyContext } from '@/contexts/CompanyContext'
164
import { NotificationCenter } from '@/components/notifications'
175

186
export function CompanyHeader() {
19-
const pathname = usePathname()
20-
const { currentCompany } = useCompanyContext()
21-
22-
// Generate breadcrumbs from pathname
23-
const generateBreadcrumbs = () => {
24-
const paths = pathname.split('/').filter(Boolean)
25-
const breadcrumbs: { label: string; href?: string }[] = []
26-
27-
// Start with Dashboard
28-
breadcrumbs.push({ label: 'Dashboard', href: `/dashboard/company/${currentCompany?.slug}` })
29-
30-
// Skip 'dashboard' and 'company' and company slug in paths
31-
const relevantPaths = paths.slice(3)
32-
33-
relevantPaths.forEach((path, index) => {
34-
const label = path
35-
.split('-')
36-
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
37-
.join(' ')
38-
39-
if (index === relevantPaths.length - 1) {
40-
// Last item - no link
41-
breadcrumbs.push({ label })
42-
} else {
43-
// Intermediate items - with link
44-
const href = `/dashboard/company/${currentCompany?.slug}/${relevantPaths
45-
.slice(0, index + 1)
46-
.join('/')}`
47-
breadcrumbs.push({ label, href })
48-
}
49-
})
50-
51-
return breadcrumbs
52-
}
53-
54-
const breadcrumbs = generateBreadcrumbs()
55-
567
return (
57-
<header className="flex h-16 shrink-0 items-center gap-2 border-b border-zinc-800 bg-gradient-to-r from-[#181f36] to-[#10172a] px-4">
58-
<SidebarTrigger className="-ml-1 text-zinc-400 hover:text-white" />
59-
<Separator orientation="vertical" className="mr-2 h-4 bg-zinc-700" />
60-
<Breadcrumb>
61-
<BreadcrumbList>
62-
{breadcrumbs.map((crumb, index) => (
63-
<React.Fragment key={index}>
64-
{index > 0 && <BreadcrumbSeparator className="text-zinc-600" />}
65-
<BreadcrumbItem>
66-
{crumb.href ? (
67-
<BreadcrumbLink
68-
href={crumb.href}
69-
className="text-zinc-400 hover:text-white transition-colors"
70-
>
71-
{crumb.label}
72-
</BreadcrumbLink>
73-
) : (
74-
<BreadcrumbPage className="text-white font-medium">
75-
{crumb.label}
76-
</BreadcrumbPage>
77-
)}
78-
</BreadcrumbItem>
79-
</React.Fragment>
80-
))}
81-
</BreadcrumbList>
82-
</Breadcrumb>
83-
<div className="ml-auto">
84-
<NotificationCenter />
85-
</div>
8+
<header className="flex h-16 shrink-0 items-center justify-end gap-2 bg-transparent px-4">
9+
<NotificationCenter />
8610
</header>
8711
)
8812
}

components/dashboard/CompanySidebar.tsx

Lines changed: 82 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import {
1010
Menu,
1111
Building2,
1212
Check,
13+
PanelLeftClose,
14+
PanelLeftOpen,
1315
} from 'lucide-react'
1416
import {
1517
DropdownMenu,
@@ -63,7 +65,9 @@ export function CompanySidebar({
6365
header,
6466
}: CompanySidebarProps) {
6567
const [mobileOpen, setMobileOpen] = useState(false)
68+
const [collapsed, setCollapsed] = useState(false)
6669
const closeSidebar = () => setMobileOpen(false)
70+
const toggleCollapsed = () => setCollapsed(!collapsed)
6771
const pathname = usePathname()
6872
const { navigateTo } = useSafeNavigation()
6973
const { currentCompany, userCompanies, switchCompany } = useCompanyContext()
@@ -223,8 +227,25 @@ export function CompanySidebar({
223227
</Sheet>
224228

225229
{/* desktop sidebar */}
226-
<aside className="hidden md:block fixed left-0 top-0 h-screen w-64 bg-black border-r border-zinc-800 z-40 shadow-xl shadow-black/30 overflow-y-auto">
227-
<SidebarHeader>
230+
<aside className={`hidden md:flex flex-col fixed left-0 top-0 h-screen bg-gradient-to-b from-zinc-950 via-zinc-900 to-zinc-950 border-r border-zinc-800 z-40 shadow-xl shadow-black/30 transition-all duration-300 ${collapsed ? 'w-20' : 'w-64'}`}>
231+
{/* Toggle Button */}
232+
<div className="flex items-center justify-end p-2 border-b border-zinc-800/50">
233+
<Button
234+
variant="ghost"
235+
size="icon"
236+
onClick={toggleCollapsed}
237+
className="h-8 w-8 hover:bg-purple-700/20 text-zinc-400 hover:text-white transition-colors"
238+
title={collapsed ? 'Expand Sidebar' : 'Collapse Sidebar'}
239+
>
240+
{collapsed ? (
241+
<PanelLeftOpen className="h-4 w-4" />
242+
) : (
243+
<PanelLeftClose className="h-4 w-4" />
244+
)}
245+
</Button>
246+
</div>
247+
248+
<SidebarHeader className="px-3 py-3">
228249
<SidebarMenu>
229250
<SidebarMenuItem>
230251
{/* Company Switcher */}
@@ -233,9 +254,10 @@ export function CompanySidebar({
233254
<DropdownMenuTrigger asChild>
234255
<SidebarMenuButton
235256
size="lg"
236-
className="hover:bg-purple-700/20 transition-colors rounded-xl p-2"
257+
className="hover:bg-purple-700/20 transition-colors rounded-xl p-2 w-full"
258+
title={collapsed ? currentCompany?.name : undefined}
237259
>
238-
<div className="flex aspect-square size-10 items-center justify-center rounded-xl bg-gradient-to-br from-primary to-purple-600 text-white shadow-md">
260+
<div className="flex aspect-square size-10 items-center justify-center rounded-xl bg-gradient-to-br from-primary to-purple-600 text-white shadow-md flex-shrink-0">
239261
{currentCompany?.logo_url ? (
240262
// eslint-disable-next-line @next/next/no-img-element
241263
<img
@@ -247,15 +269,19 @@ export function CompanySidebar({
247269
<Building2 className="size-5" />
248270
)}
249271
</div>
250-
<div className="grid flex-1 text-left text-sm leading-tight ml-3">
251-
<span className="truncate font-bold text-lg tracking-tight text-white drop-shadow">
252-
{currentCompany?.name || 'Company'}
253-
</span>
254-
<span className="truncate text-xs text-zinc-400">
255-
Switch company
256-
</span>
257-
</div>
258-
<ChevronDown className="ml-auto size-4 text-zinc-400" />
272+
{!collapsed && (
273+
<>
274+
<div className="grid flex-1 text-left text-sm leading-tight ml-3 min-w-0">
275+
<span className="truncate font-bold text-lg tracking-tight text-white drop-shadow">
276+
{currentCompany?.name || 'Company'}
277+
</span>
278+
<span className="truncate text-xs text-zinc-400">
279+
Switch company
280+
</span>
281+
</div>
282+
<ChevronDown className="ml-auto size-4 text-zinc-400 flex-shrink-0" />
283+
</>
284+
)}
259285
</SidebarMenuButton>
260286
</DropdownMenuTrigger>
261287
<DropdownMenuContent
@@ -303,10 +329,11 @@ export function CompanySidebar({
303329
<SidebarMenuButton
304330
size="lg"
305331
asChild
306-
className="hover:bg-purple-700/20 transition-colors rounded-xl p-2"
332+
className="hover:bg-purple-700/20 transition-colors rounded-xl p-2 w-full"
333+
title={collapsed ? currentCompany?.name : undefined}
307334
>
308-
<Link href={`/dashboard/company/${currentCompany?.slug}`}>
309-
<div className="flex aspect-square size-10 items-center justify-center rounded-xl bg-gradient-to-br from-primary to-purple-600 text-white shadow-md">
335+
<Link href={`/dashboard/company/${currentCompany?.slug}`} className="flex items-center">
336+
<div className="flex aspect-square size-10 items-center justify-center rounded-xl bg-gradient-to-br from-primary to-purple-600 text-white shadow-md flex-shrink-0">
310337
{currentCompany?.logo_url ? (
311338
// eslint-disable-next-line @next/next/no-img-element
312339
<img
@@ -318,14 +345,16 @@ export function CompanySidebar({
318345
<Building2 className="size-5" />
319346
)}
320347
</div>
321-
<div className="grid flex-1 text-left text-sm leading-tight ml-3">
322-
<span className="truncate font-bold text-lg tracking-tight text-white drop-shadow">
323-
{currentCompany?.name || 'Company'}
324-
</span>
325-
<span className="truncate text-xs text-zinc-400">
326-
Company Portal
327-
</span>
328-
</div>
348+
{!collapsed && (
349+
<div className="grid flex-1 text-left text-sm leading-tight ml-3 min-w-0">
350+
<span className="truncate font-bold text-lg tracking-tight text-white drop-shadow">
351+
{currentCompany?.name || 'Company'}
352+
</span>
353+
<span className="truncate text-xs text-zinc-400">
354+
Company Portal
355+
</span>
356+
</div>
357+
)}
329358
</Link>
330359
</SidebarMenuButton>
331360
)}
@@ -336,26 +365,31 @@ export function CompanySidebar({
336365
<SidebarContent className="flex-1 overflow-y-auto scrollbar-thin scrollbar-thumb-zinc-800 scrollbar-track-transparent py-2">
337366
{sidebarItems.map((group) => (
338367
<SidebarGroup key={group.title}>
339-
<SidebarGroupLabel className="uppercase text-xs font-semibold text-purple-400 tracking-wider px-6 py-2 mt-2 mb-1">
340-
{group.title}
341-
</SidebarGroupLabel>
368+
{!collapsed && (
369+
<SidebarGroupLabel className="uppercase text-xs font-semibold text-purple-400 tracking-wider px-4 py-2 mt-2 mb-1">
370+
{group.title}
371+
</SidebarGroupLabel>
372+
)}
342373
<SidebarGroupContent>
343374
<SidebarMenu>
344375
{group.items.map((item) => (
345376
<SidebarMenuItem key={item.title}>
346377
<SidebarMenuButton
347378
asChild
348-
className={`group flex items-center gap-3 px-6 py-2 rounded-lg transition-all hover:bg-purple-700/10 active:bg-purple-800/20 focus:bg-purple-800/20 text-zinc-200 hover:text-white font-medium ${
379+
className={`group flex items-center gap-3 mx-2 px-3 py-2 rounded-lg transition-all hover:bg-purple-700/10 active:bg-purple-800/20 focus:bg-purple-800/20 text-zinc-200 hover:text-white font-medium ${
349380
pathname === item.url
350381
? 'bg-purple-800/30 text-white'
351382
: ''
352-
}`}
383+
} ${collapsed ? 'justify-center' : ''}`}
384+
title={collapsed ? item.title : undefined}
353385
>
354386
<Link href={item.url} className="flex items-center w-full">
355-
<span className="mr-3 text-purple-400 group-hover:text-purple-300">
387+
<span className={`text-purple-400 group-hover:text-purple-300 ${collapsed ? '' : 'mr-3'}`}>
356388
{React.createElement(item.icon, { className: 'size-5' })}
357389
</span>
358-
<span className="truncate text-base">{item.title}</span>
390+
{!collapsed && (
391+
<span className="truncate text-base">{item.title}</span>
392+
)}
359393
</Link>
360394
</SidebarMenuButton>
361395
</SidebarMenuItem>
@@ -366,27 +400,32 @@ export function CompanySidebar({
366400
))}
367401
</SidebarContent>
368402

369-
<SidebarFooter className="mt-auto border-t border-zinc-800 bg-gradient-to-t from-[#181f36] to-transparent px-4 py-4">
403+
<SidebarFooter className="mt-auto border-t border-zinc-800 bg-gradient-to-t from-zinc-950 to-transparent px-3 py-3">
370404
<SidebarMenu>
371405
<SidebarMenuItem>
372406
<DropdownMenu>
373407
<DropdownMenuTrigger asChild>
374408
<SidebarMenuButton
375409
size="lg"
376410
className="w-full flex items-center gap-3 rounded-xl p-2 hover:bg-purple-700/20 transition-colors data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
411+
title={collapsed ? name : undefined}
377412
>
378-
<div className="flex aspect-square size-10 items-center justify-center rounded-xl bg-gradient-to-br from-primary to-purple-600 text-white font-semibold shadow-md">
413+
<div className="flex aspect-square size-10 items-center justify-center rounded-xl bg-gradient-to-br from-primary to-purple-600 text-white font-semibold shadow-md flex-shrink-0">
379414
{avatar}
380415
</div>
381-
<div className="grid flex-1 text-left text-sm leading-tight ml-2">
382-
<span className="truncate font-semibold text-white">
383-
{name}
384-
</span>
385-
<span className="truncate text-xs text-purple-300">
386-
{currentCompany?.name}
387-
</span>
388-
</div>
389-
<ChevronDown className="ml-auto size-4 text-zinc-400" />
416+
{!collapsed && (
417+
<>
418+
<div className="grid flex-1 text-left text-sm leading-tight min-w-0">
419+
<span className="truncate font-semibold text-white">
420+
{name}
421+
</span>
422+
<span className="truncate text-xs text-purple-300">
423+
{currentCompany?.name}
424+
</span>
425+
</div>
426+
<ChevronDown className="ml-auto size-4 text-zinc-400 flex-shrink-0" />
427+
</>
428+
)}
390429
</SidebarMenuButton>
391430
</DropdownMenuTrigger>
392431
<DropdownMenuContent
@@ -446,7 +485,7 @@ export function CompanySidebar({
446485
</aside>
447486

448487
{/* main content */}
449-
<div className="md:ml-64 flex-1 flex flex-col min-h-screen bg-gradient-to-br from-[#181f36] via-[#10172a] to-[#181f36]">
488+
<div className={`flex-1 flex flex-col min-h-screen bg-gradient-to-br from-[#181f36] via-[#10172a] to-[#181f36] transition-all duration-300 ${collapsed ? 'md:ml-20' : 'md:ml-64'}`}>
450489
<SidebarInset className="bg-black">
451490
{header}
452491
<div className="flex flex-1 flex-col gap-4 p-4 pt-0">{children}</div>

0 commit comments

Comments
 (0)