beetask/new-frontend/src/components/layout/Sidebar.tsx

172 lines
6.1 KiB
TypeScript

import { NavLink } from 'react-router-dom'
import {
LayoutDashboard,
ListTodo,
FolderKanban,
Tags,
BarChart3,
Users,
Settings,
X,
Building2,
Sun,
Moon,
} from 'lucide-react'
import { Chip, ChipLabel } from '@heroui/react'
import { useAuth } from '../../contexts/AuthContext'
import { useTheme } from '../../contexts/ThemeContext'
interface SidebarProps {
isMobileOpen: boolean
onCloseMobile: () => void
}
export const Sidebar = ({ isMobileOpen, onCloseMobile }: SidebarProps) => {
const { activeOrg } = useAuth()
const { theme, toggleTheme } = useTheme()
const navItems = [
{
group: 'Principal',
links: [
{ to: '/dashboard', label: 'Meu Dashboard', icon: <LayoutDashboard className="w-4 h-4" /> },
{ to: '/tasks', label: 'Tarefas & Board', icon: <ListTodo className="w-4 h-4" /> },
],
},
{
group: 'Estrutura',
links: [
{ to: '/projects', label: 'Projetos', icon: <FolderKanban className="w-4 h-4" /> },
{ to: '/categories', label: 'Categorias', icon: <Tags className="w-4 h-4" /> },
],
},
{
group: 'Gestão & Equipe',
links: [
{ to: '/analytics', label: 'Analytics da Org', icon: <BarChart3 className="w-4 h-4" /> },
{ to: '/members', label: 'Membros & Squads', icon: <Users className="w-4 h-4" /> },
{ to: '/organization/settings', label: 'Configurações', icon: <Settings className="w-4 h-4" /> },
],
},
]
const navContent = (
<div className="flex flex-col h-full bg-surface border-r border-border-soft select-none">
{/* Brand & Logo */}
<div className="h-18 px-6 flex items-center justify-between border-b border-border-soft">
<NavLink to="/dashboard" className="flex items-center gap-3">
<div className="w-9 h-9 rounded-xl bg-gradient-to-br from-accent to-brand flex items-center justify-center shadow-md shadow-accent/20">
<span className="text-xl">🐝</span>
</div>
<div>
<div className="flex items-center gap-1.5">
<span className="font-extrabold text-lg tracking-tight text-text-main">
Bee<span className="text-accent">Task</span>
</span>
<Chip className="bg-brand-soft text-brand text-[10px] font-bold px-1.5 py-0.2">
<ChipLabel>v3.0</ChipLabel>
</Chip>
</div>
<p className="text-[10px] font-semibold text-text-muted leading-tight">
Workspace Ágil
</p>
</div>
</NavLink>
{/* Mobile close button */}
<button
type="button"
onClick={onCloseMobile}
className="lg:hidden p-1.5 rounded-lg text-text-muted hover:text-text-main hover:bg-surface-muted"
>
<X className="w-5 h-5" />
</button>
</div>
{/* Nav List */}
<div className="flex-1 overflow-y-auto px-4 py-6 space-y-6">
{navItems.map((group, idx) => (
<div key={idx} className="space-y-1.5">
<p className="px-3 text-[10px] font-extrabold uppercase tracking-widest text-text-muted">
{group.group}
</p>
<div className="space-y-1">
{group.links.map((link) => (
<NavLink
key={link.to}
to={link.to}
onClick={onCloseMobile}
className={({ isActive }) =>
`flex items-center gap-3 px-3 py-2.5 rounded-xl text-xs font-semibold transition-all ${
isActive
? 'bg-brand text-white shadow-md shadow-brand/20 font-bold'
: 'text-text-muted hover:text-text-main hover:bg-surface-muted'
}`
}
>
{link.icon}
<span>{link.label}</span>
</NavLink>
))}
</div>
</div>
))}
</div>
{/* Bottom Workspace Card Info */}
<div className="p-4 border-t border-border-soft">
<div className="p-3 rounded-2xl bg-surface-muted/70 border border-border-soft flex items-center justify-between gap-2">
<div className="flex items-center gap-2.5 truncate flex-1 min-w-0">
<div className="w-8 h-8 rounded-xl bg-brand-soft text-brand flex items-center justify-center font-bold text-xs shrink-0">
<Building2 className="w-4 h-4 text-brand" />
</div>
<div className="truncate flex-1 min-w-0">
<p className="text-xs font-bold text-text-main truncate">
{activeOrg?.name || 'Workspace Padrão'}
</p>
<span className="text-[10px] font-semibold text-text-muted uppercase tracking-wider">
{activeOrg?.roles[0] || 'Ativo'}
</span>
</div>
</div>
<button
type="button"
onClick={toggleTheme}
title={theme === 'dark' ? 'Mudar para tema claro' : 'Mudar para tema escuro'}
className="p-1.5 rounded-lg border border-border-soft bg-surface text-muted hover:text-foreground hover:bg-surface-raised transition-colors shrink-0"
aria-label="Alternar tema"
>
{theme === 'dark' ? (
<Sun className="w-3.5 h-3.5 text-amber-400" />
) : (
<Moon className="w-3.5 h-3.5 text-brand" />
)}
</button>
</div>
</div>
</div>
)
return (
<>
{/* Desktop Sidebar (Permanent) */}
<aside className="hidden lg:block w-64 h-screen sticky top-0 shrink-0 z-30">
{navContent}
</aside>
{/* Mobile Sidebar (Drawer Overlay) */}
{isMobileOpen && (
<div className="lg:hidden fixed inset-0 z-50 flex">
<div
className="fixed inset-0 bg-black/40 backdrop-blur-xs transition-opacity"
onClick={onCloseMobile}
/>
<div className="relative w-64 max-w-xs h-full z-50 animate-in slide-in-from-left duration-200">
{navContent}
</div>
</div>
)}
</>
)
}