feat: implement sidebar and random pages for test
This commit is contained in:
123
src/components/AppSidebar.tsx
Normal file
123
src/components/AppSidebar.tsx
Normal file
@@ -0,0 +1,123 @@
|
||||
import { Link, useLocation } from 'react-router'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarHeader,
|
||||
SidebarContent,
|
||||
SidebarFooter,
|
||||
SidebarNav,
|
||||
SidebarNavItem
|
||||
} from '@/components/ui/sidebar'
|
||||
import { useAuth } from '@/contexts/AuthContext'
|
||||
import {
|
||||
Home,
|
||||
Settings,
|
||||
Users,
|
||||
Activity,
|
||||
LogOut
|
||||
} from 'lucide-react'
|
||||
|
||||
const navigationItems = [
|
||||
{
|
||||
title: 'Dashboard',
|
||||
href: '/dashboard',
|
||||
icon: Home,
|
||||
},
|
||||
{
|
||||
title: 'Activity',
|
||||
href: '/activity',
|
||||
icon: Activity,
|
||||
},
|
||||
{
|
||||
title: 'Settings',
|
||||
href: '/settings',
|
||||
icon: Settings,
|
||||
},
|
||||
]
|
||||
|
||||
const adminNavigationItems = [
|
||||
{
|
||||
title: 'Users',
|
||||
href: '/admin/users',
|
||||
icon: Users,
|
||||
},
|
||||
]
|
||||
|
||||
export function AppSidebar() {
|
||||
const { user, logout } = useAuth()
|
||||
const location = useLocation()
|
||||
|
||||
const handleLogout = async () => {
|
||||
try {
|
||||
await logout()
|
||||
} catch (error) {
|
||||
console.error('Logout failed:', error)
|
||||
}
|
||||
}
|
||||
|
||||
if (!user) return null
|
||||
|
||||
const allNavItems = [
|
||||
...navigationItems,
|
||||
...(user.role === 'admin' ? adminNavigationItems : [])
|
||||
]
|
||||
|
||||
return (
|
||||
<Sidebar className="w-64 border-r">
|
||||
<SidebarHeader>
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="w-8 h-8 bg-primary rounded-lg flex items-center justify-center">
|
||||
<span className="text-primary-foreground font-bold text-sm">SB</span>
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="text-lg font-semibold">Soundboard</h2>
|
||||
<p className="text-xs text-muted-foreground">v2.0</p>
|
||||
</div>
|
||||
</div>
|
||||
</SidebarHeader>
|
||||
|
||||
<SidebarContent>
|
||||
<SidebarNav>
|
||||
{allNavItems.map((item) => {
|
||||
const Icon = item.icon
|
||||
const isActive = location.pathname === item.href
|
||||
|
||||
return (
|
||||
<Link key={item.href} to={item.href}>
|
||||
<SidebarNavItem active={isActive}>
|
||||
<Icon className="h-4 w-4" />
|
||||
{item.title}
|
||||
</SidebarNavItem>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</SidebarNav>
|
||||
</SidebarContent>
|
||||
|
||||
<SidebarFooter>
|
||||
<div className="flex items-center gap-3 p-3 rounded-md bg-sidebar-accent/50">
|
||||
{user.picture && (
|
||||
<img
|
||||
src={user.picture}
|
||||
alt="Profile"
|
||||
className="w-8 h-8 rounded-full"
|
||||
/>
|
||||
)}
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="text-sm font-medium truncate">{user.name}</p>
|
||||
<p className="text-xs text-muted-foreground truncate">{user.email}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={handleLogout}
|
||||
className="w-full justify-start"
|
||||
>
|
||||
<LogOut className="h-4 w-4 mr-2" />
|
||||
Sign out
|
||||
</Button>
|
||||
</SidebarFooter>
|
||||
</Sidebar>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user