arbritage/layouts/TopBar.tsx
2026-01-26 11:20:25 -03:00

175 lines
8 KiB
TypeScript

import React, { useState } from 'react';
import { NavLink, useNavigate } from 'react-router-dom';
import {
LayoutDashboard, Search, History, Boxes, Store, Users, TrendingUp, LogOut, Wallet,
ChevronDown, Package, FileText, Factory, Menu, ShoppingCart, Settings, BarChart3
} from 'lucide-react';
import { useCRM } from '../context/CRMContext';
import clsx from 'clsx';
import Logo from '../components/Logo';
const TopBar: React.FC = () => {
const { users, signOut } = useCRM();
const currentUser = users[0];
const navigate = useNavigate();
// Dropdown States
const [openMenu, setOpenMenu] = useState<string | null>(null);
const handleSignOut = async () => {
await signOut();
navigate('/login');
};
const navStructure = [
{
label: 'Dashboard',
to: '/',
icon: LayoutDashboard,
type: 'link'
},
{
label: 'Vendas',
to: '/sales',
icon: ShoppingCart,
type: 'link'
},
{
label: 'Arbitragem',
icon: Search,
type: 'dropdown',
items: [
{ label: 'Sourcing Intel', to: '/sourcing', icon: Search },
{ label: 'Minhas Ordens', to: '/orders', icon: History },
]
},
{
label: 'Cadastros',
icon: FileText,
type: 'dropdown',
items: [
{ label: 'Clientes', to: '/customers', icon: Users },
{ label: 'Fornecedores', to: '/suppliers', icon: Store },
{ label: 'Produtos', to: '/products', icon: Package },
{ label: 'Estoque', to: '/inventory', icon: Boxes },
{ label: 'Usuários', to: '/users', icon: Users },
]
},
{
label: 'Produção',
icon: Factory,
type: 'nav-link', // Future placeholder
to: '#', // Placeholder
items: [], // Empty for now or future items
disabled: true
},
{
label: 'Relatórios',
to: '/reports',
icon: BarChart3,
type: 'link'
},
{
label: 'Financeiro',
to: '/financial',
icon: Wallet,
type: 'link'
}
];
return (
<header className="h-[72px] bg-background/80 backdrop-blur-xl border-b border-border flex items-center px-8 justify-between sticky top-0 z-50">
{/* LOGO */}
<div onClick={() => navigate('/')} className="cursor-pointer">
<Logo />
</div>
{/* NAV MENU CASCATA */}
<nav className="flex-1 flex justify-center items-center gap-2">
{navStructure.map((item, idx) => (
<div
key={idx}
className="relative group"
onMouseEnter={() => item.type === 'dropdown' && setOpenMenu(item.label)}
onMouseLeave={() => setOpenMenu(null)}
>
{item.type === 'link' ? (
<NavLink
to={item.to!}
className={({ isActive }) => clsx(
"px-5 py-2.5 rounded-xl text-sm font-bold flex items-center gap-2 transition-all duration-200 hover:bg-accent/50",
isActive ? "text-foreground bg-accent shadow-sm border border-border" : "text-muted-foreground"
)}
>
<item.icon size={16} />
{item.label}
</NavLink>
) : (
<button className={clsx(
"px-5 py-2.5 rounded-xl text-sm font-bold flex items-center gap-2 transition-all duration-200 hover:bg-accent/50 group-hover:text-foreground",
openMenu === item.label ? "text-foreground bg-accent" : "text-muted-foreground"
)}>
<item.icon size={16} />
{item.label}
<ChevronDown size={12} className={clsx("transition-transform duration-200", openMenu === item.label && "rotate-180")} />
</button>
)}
{/* DROPDOWN MENU */}
{item.type === 'dropdown' && (
<div className={clsx(
"absolute top-full left-1/2 -translate-x-1/2 pt-4 w-[240px] transition-all duration-200 origin-top z-50",
openMenu === item.label ? "opacity-100 scale-100 visible" : "opacity-0 scale-95 invisible"
)}>
<div className="bg-popover border border-border rounded-2xl shadow-xl p-2 flex flex-col gap-1 backdrop-blur-3xl">
<div className="absolute -top-1.5 left-1/2 -translate-x-1/2 w-3 h-3 bg-popover border-t border-l border-border rotate-45"></div>
{item.items?.map((subItem, subIdx) => (
<NavLink
key={subIdx}
to={subItem.to}
className={({ isActive }) => clsx(
"w-full text-left px-4 py-3 rounded-xl text-xs font-bold flex items-center gap-3 transition-colors hover:bg-accent",
isActive ? "text-foreground bg-accent" : "text-muted-foreground"
)}
>
{({ isActive }) => (
<>
<subItem.icon size={14} className={isActive ? "text-primary" : "text-slate-500"} />
{subItem.label}
</>
)}
</NavLink>
))}
</div>
</div>
)}
</div>
))}
</nav>
{/* USER ACTIONS */}
<div className="flex items-center gap-4 w-[200px] justify-end">
<button
onClick={() => navigate('/settings')}
className="w-10 h-10 rounded-2xl bg-secondary/50 border border-border flex items-center justify-center text-muted-foreground hover:text-foreground hover:bg-secondary transition-all"
title="Configurações"
>
<Settings size={20} />
</button>
<div onClick={handleSignOut} className="flex items-center gap-3 pl-4 pr-2 py-1.5 rounded-2xl bg-secondary/50 border border-border hover:bg-destructive/10 hover:border-destructive/20 transition-all cursor-pointer group">
<div className="text-right hidden xl:block">
<p className="text-xs font-bold text-foreground leading-none">{currentUser?.name || 'Admin'}</p>
<p className="text-[9px] text-muted-foreground font-bold uppercase mt-0.5">Online</p>
</div>
<div className="w-8 h-8 rounded-full bg-slate-800 border border-border flex items-center justify-center group-hover:scale-105 transition-transform overflow-hidden">
<img src={currentUser?.avatar || "https://api.dicebear.com/7.x/avataaars/svg?seed=Admin"} alt="Avatar" className="w-full h-full object-cover" />
</div>
</div>
</div>
</header>
);
};
export default TopBar;