189 lines
7.9 KiB
JavaScript
189 lines
7.9 KiB
JavaScript
import React from 'react';
|
|
import { Link, useLocation, useNavigate } from 'react-router-dom';
|
|
import { Home, Store, BarChart3, HeartPulse, Wrench, ShoppingBag, AlertTriangle, UserCheck, ShieldCheck, LogOut, LayoutGrid } from 'lucide-react';
|
|
import { useAuth } from '../context/useAuth';
|
|
|
|
export function NavigationHeader({
|
|
title,
|
|
subtitle,
|
|
icon: TitleIcon,
|
|
health,
|
|
onResetHome,
|
|
children,
|
|
}) {
|
|
const location = useLocation();
|
|
const path = location.pathname;
|
|
const search = location.search;
|
|
const navigate = useNavigate();
|
|
const { user, role, logout } = useAuth();
|
|
|
|
const handleLogout = () => {
|
|
logout();
|
|
navigate('/login');
|
|
};
|
|
|
|
const getRoleBadge = () => {
|
|
if (role === 'admin') {
|
|
return (
|
|
<span className="inline-flex items-center gap-1 rounded-full bg-amber-500/15 border border-amber-500/30 px-2.5 py-0.5 text-[11px] font-bold text-amber-600">
|
|
<ShieldCheck className="h-3 w-3" /> Admin
|
|
</span>
|
|
);
|
|
}
|
|
return (
|
|
<span className="inline-flex items-center gap-1 rounded-full bg-blue-500/15 border border-blue-500/30 px-2.5 py-0.5 text-[11px] font-bold text-blue-600">
|
|
<UserCheck className="h-3 w-3" /> User
|
|
</span>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<header className="sticky top-0 z-30 flex flex-col gap-3 border-b border-ink-900/10 bg-paper-50/95 px-6 py-3.5 backdrop-blur-md transition-all shadow-xs">
|
|
<div className="flex items-center justify-between gap-4 flex-wrap">
|
|
{/* Left Section: Home/Back Button + Page Title */}
|
|
<div className="flex items-center gap-3">
|
|
<Link
|
|
to={role === 'admin' ? '/' : '/user'}
|
|
onClick={() => {
|
|
if (onResetHome) onResetHome();
|
|
}}
|
|
title={role === 'admin' ? 'Navigate to Catalog' : 'Navigate to User Workspace'}
|
|
className="group flex items-center gap-2 rounded-full bg-gradient-to-r from-amber-500 to-amber-600 hover:from-amber-600 hover:to-amber-700 text-white px-4 py-2 text-xs font-semibold shadow-sm transition-all duration-200 active:scale-95 hover:shadow-md"
|
|
>
|
|
<Home className="h-4 w-4 transition-transform group-hover:-translate-x-0.5" />
|
|
<span>{role === 'admin' ? 'Home / Catalog' : 'Home / Workspace'}</span>
|
|
</Link>
|
|
|
|
{title && (
|
|
<div className="flex items-center gap-2.5 border-l border-ink-900/15 pl-4 py-0.5">
|
|
{TitleIcon && (
|
|
<div className="flex h-7 w-7 items-center justify-center rounded-lg bg-ink-900/5 text-ink-900">
|
|
<TitleIcon className="h-4 w-4" />
|
|
</div>
|
|
)}
|
|
<div>
|
|
<h1 className="font-display text-sm font-bold text-ink-950 flex items-center gap-1.5">
|
|
{title}
|
|
</h1>
|
|
{subtitle && <p className="text-[11px] text-slate-400 font-normal leading-tight">{subtitle}</p>}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Right Section: System Health + Role-Based Nav Tabs + Logout Button */}
|
|
<div className="flex items-center gap-3">
|
|
{health && health.status !== 'ok' && (
|
|
<span className="flex items-center gap-1.5 rounded-full bg-maroon-100 px-3 py-1 text-xs font-medium text-maroon-600">
|
|
<AlertTriangle className="h-3.5 w-3.5" />
|
|
{!health.database && !health.ollama
|
|
? 'DB & Ollama offline'
|
|
: !health.database
|
|
? 'Database offline'
|
|
: 'Ollama offline'}
|
|
</span>
|
|
)}
|
|
|
|
{/* User Role Profile Badge */}
|
|
<div className="flex items-center gap-2 rounded-full border border-slate-200 bg-white px-3 py-1.5 text-xs shadow-2xs">
|
|
<span className="font-bold text-slate-800">{user?.display_name || user?.username || 'Guest'}</span>
|
|
{getRoleBadge()}
|
|
</div>
|
|
|
|
{/* Role-tailored Navigation Tabs */}
|
|
<nav className="flex items-center gap-1 rounded-full bg-ink-100/90 p-1 text-xs font-medium backdrop-blur">
|
|
{/* Catalog tab ONLY visible to Admin role */}
|
|
{role === 'admin' && (
|
|
<Link
|
|
to="/"
|
|
onClick={() => {
|
|
if (onResetHome) onResetHome();
|
|
}}
|
|
className={`flex items-center gap-1.5 rounded-full px-3.5 py-1.5 transition-all ${
|
|
path === '/' ? 'bg-ink-950 text-paper-100 shadow-sm font-semibold' : 'text-slate-600 hover:text-ink-950 hover:bg-white/60'
|
|
}`}
|
|
>
|
|
<ShoppingBag className="h-3.5 w-3.5" /> Catalog
|
|
</Link>
|
|
)}
|
|
|
|
{/* User Upload tab */}
|
|
<Link
|
|
to="/user"
|
|
className={`flex items-center gap-1.5 rounded-full px-3.5 py-1.5 transition-all ${
|
|
path === '/user' && !search.includes('tab=cards') ? 'bg-ink-950 text-paper-100 shadow-sm font-semibold' : 'text-slate-600 hover:text-ink-950 hover:bg-white/60'
|
|
}`}
|
|
>
|
|
<UserCheck className="h-3.5 w-3.5 text-blue-400" /> User Upload
|
|
</Link>
|
|
|
|
{/* Product Cards tab for User role */}
|
|
<Link
|
|
to="/user?tab=cards"
|
|
className={`flex items-center gap-1.5 rounded-full px-3.5 py-1.5 transition-all ${
|
|
path === '/user' && search.includes('tab=cards') ? 'bg-amber-500 text-slate-950 font-bold shadow-sm' : 'text-slate-600 hover:text-ink-950 hover:bg-white/60'
|
|
}`}
|
|
>
|
|
<LayoutGrid className="h-3.5 w-3.5 text-amber-600" /> Product Cards
|
|
</Link>
|
|
|
|
{/* Stores tab */}
|
|
<Link
|
|
to="/stores"
|
|
className={`flex items-center gap-1.5 rounded-full px-3.5 py-1.5 transition-all ${
|
|
path === '/stores' ? 'bg-ink-950 text-paper-100 shadow-sm font-semibold' : 'text-slate-600 hover:text-ink-950 hover:bg-white/60'
|
|
}`}
|
|
>
|
|
<Store className="h-3.5 w-3.5 text-emerald-400" /> Stores
|
|
</Link>
|
|
|
|
{/* Analytics tab */}
|
|
<Link
|
|
to="/analytics"
|
|
className={`flex items-center gap-1.5 rounded-full px-3.5 py-1.5 transition-all ${
|
|
path === '/analytics' ? 'bg-ink-950 text-paper-100 shadow-sm font-semibold' : 'text-slate-600 hover:text-ink-950 hover:bg-white/60'
|
|
}`}
|
|
>
|
|
<BarChart3 className="h-3.5 w-3.5" /> Analytics
|
|
</Link>
|
|
|
|
{/* Nutrition tab */}
|
|
<Link
|
|
to="/nutrition-analytics"
|
|
className={`flex items-center gap-1.5 rounded-full px-3.5 py-1.5 transition-all ${
|
|
path === '/nutrition-analytics' ? 'bg-ink-950 text-paper-100 shadow-sm font-semibold' : 'text-slate-600 hover:text-ink-950 hover:bg-white/60'
|
|
}`}
|
|
>
|
|
<HeartPulse className="h-3.5 w-3.5" /> Nutrition
|
|
</Link>
|
|
|
|
{/* Admin Panel tab ONLY visible to Admin role */}
|
|
{role === 'admin' && (
|
|
<Link
|
|
to="/admin"
|
|
className={`flex items-center gap-1.5 rounded-full px-3.5 py-1.5 transition-all ${
|
|
path === '/admin' ? 'bg-ink-950 text-paper-100 shadow-sm font-semibold' : 'text-slate-600 hover:text-ink-950 hover:bg-white/60'
|
|
}`}
|
|
>
|
|
<Wrench className="h-3.5 w-3.5 text-amber-400" /> Admin
|
|
</Link>
|
|
)}
|
|
</nav>
|
|
|
|
{/* Top Right Logout Button */}
|
|
<button
|
|
onClick={handleLogout}
|
|
title="Logout to Login Page"
|
|
className="flex items-center gap-1.5 rounded-full bg-rose-600 hover:bg-rose-700 text-white px-3.5 py-1.5 text-xs font-semibold shadow-xs transition-all active:scale-95 cursor-pointer"
|
|
>
|
|
<LogOut className="h-3.5 w-3.5" />
|
|
<span>Logout</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{children}
|
|
</header>
|
|
);
|
|
}
|