216 lines
7.9 KiB
TypeScript
216 lines
7.9 KiB
TypeScript
|
|
import { useState } from 'react';
|
|
import { Link, useLocation, useNavigate } from 'react-router-dom';
|
|
import { Menu, X, LayoutDashboard, Users, MessageSquare, Home, LogIn, LogOut } from 'lucide-react';
|
|
import { cn } from '@/lib/utils';
|
|
import { useAuth } from '@/contexts/AuthContext';
|
|
|
|
export default function Navigation() {
|
|
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
|
const location = useLocation();
|
|
const navigate = useNavigate();
|
|
const { isAuthenticated, logout } = useAuth();
|
|
|
|
const navigationItems = [
|
|
{
|
|
name: 'Home',
|
|
href: '/',
|
|
icon: Home,
|
|
},
|
|
{
|
|
name: 'Synthetic Personas',
|
|
href: '/synthetic-users',
|
|
icon: Users,
|
|
},
|
|
{
|
|
name: 'Focus Groups',
|
|
href: '/focus-groups',
|
|
icon: MessageSquare,
|
|
},
|
|
{
|
|
name: 'Dashboard',
|
|
href: '/dashboard',
|
|
icon: LayoutDashboard,
|
|
},
|
|
];
|
|
|
|
const toggleMobileMenu = () => {
|
|
setMobileMenuOpen(!mobileMenuOpen);
|
|
};
|
|
|
|
const isActive = (path: string) => {
|
|
return location.pathname === path;
|
|
};
|
|
|
|
// Handle navigation with authentication
|
|
const handleAuthNavigation = (path: string) => {
|
|
// Dispatch a custom event when navigating to the synthetic users page
|
|
// This helps components know when they should refresh data
|
|
if (path === '/synthetic-users') {
|
|
// Create and dispatch a custom event that the SyntheticUsers component can listen for
|
|
const event = new CustomEvent('syntheticUsersNavigation');
|
|
window.dispatchEvent(event);
|
|
}
|
|
|
|
// Always navigate normally - ProtectedRoute will handle auth check
|
|
navigate(path);
|
|
};
|
|
|
|
return (
|
|
<header className="fixed top-0 left-0 right-0 z-50 bg-white/80 backdrop-blur-md border-b border-slate-200/80">
|
|
<div className="px-4 sm:px-6 lg:px-8">
|
|
<div className="flex h-16 items-center justify-between">
|
|
<div className="flex items-center">
|
|
<Link to="/" className="flex items-center">
|
|
<span className="font-sf text-2xl font-semibold text-gradient">Semblance</span>
|
|
</Link>
|
|
</div>
|
|
|
|
{/* Desktop Navigation */}
|
|
<nav className="hidden md:block">
|
|
<ul className="flex items-center space-x-8">
|
|
{navigationItems.map((item) => (
|
|
<li key={item.name}>
|
|
{item.href === '/' ? (
|
|
<Link
|
|
to={item.href}
|
|
className={cn(
|
|
"flex items-center px-1 py-2 text-sm font-medium hover-transition border-b-2",
|
|
isActive(item.href)
|
|
? "border-primary text-primary"
|
|
: "border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"
|
|
)}
|
|
>
|
|
<item.icon className="mr-1 h-4 w-4" />
|
|
{item.name}
|
|
</Link>
|
|
) : (
|
|
<button
|
|
onClick={() => handleAuthNavigation(item.href)}
|
|
className={cn(
|
|
"flex items-center px-1 py-2 text-sm font-medium hover-transition border-b-2",
|
|
isActive(item.href)
|
|
? "border-primary text-primary"
|
|
: "border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"
|
|
)}
|
|
>
|
|
<item.icon className="mr-1 h-4 w-4" />
|
|
{item.name}
|
|
</button>
|
|
)}
|
|
</li>
|
|
))}
|
|
|
|
{/* Authentication buttons */}
|
|
<li>
|
|
{isAuthenticated ? (
|
|
<button
|
|
onClick={() => {
|
|
logout();
|
|
navigate('/login');
|
|
}}
|
|
className="flex items-center px-3 py-2 text-sm font-medium text-slate-600 hover:text-slate-900 button-transition rounded-md hover:bg-slate-50"
|
|
>
|
|
<LogOut className="mr-1 h-4 w-4" />
|
|
Logout
|
|
</button>
|
|
) : (
|
|
<Link
|
|
to="/login"
|
|
className="flex items-center px-3 py-2 text-sm font-medium text-slate-600 hover:text-slate-900 button-transition rounded-md hover:bg-slate-50"
|
|
>
|
|
<LogIn className="mr-1 h-4 w-4" />
|
|
Login
|
|
</Link>
|
|
)}
|
|
</li>
|
|
</ul>
|
|
</nav>
|
|
|
|
{/* Mobile Menu Button */}
|
|
<div className="flex md:hidden">
|
|
<button
|
|
type="button"
|
|
className="inline-flex items-center justify-center rounded-md p-2 text-slate-700 hover:bg-slate-100 hover:text-slate-900 button-transition"
|
|
onClick={toggleMobileMenu}
|
|
>
|
|
<span className="sr-only">Open main menu</span>
|
|
{mobileMenuOpen ? (
|
|
<X className="block h-6 w-6" aria-hidden="true" />
|
|
) : (
|
|
<Menu className="block h-6 w-6" aria-hidden="true" />
|
|
)}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Mobile Menu */}
|
|
{mobileMenuOpen && (
|
|
<div className="md:hidden glass-panel animate-fade-in">
|
|
<div className="space-y-1 px-4 pb-3 pt-2">
|
|
{navigationItems.map((item) => (
|
|
<div key={item.name}>
|
|
{item.href === '/' ? (
|
|
<Link
|
|
to={item.href}
|
|
className={cn(
|
|
"flex items-center rounded-md px-3 py-2 text-base font-medium button-transition",
|
|
isActive(item.href)
|
|
? "bg-primary text-white"
|
|
: "text-slate-600 hover:bg-slate-50 hover:text-slate-900"
|
|
)}
|
|
onClick={() => setMobileMenuOpen(false)}
|
|
>
|
|
<item.icon className="mr-3 h-5 w-5" />
|
|
{item.name}
|
|
</Link>
|
|
) : (
|
|
<button
|
|
className={cn(
|
|
"flex items-center rounded-md px-3 py-2 text-base font-medium button-transition w-full text-left",
|
|
isActive(item.href)
|
|
? "bg-primary text-white"
|
|
: "text-slate-600 hover:bg-slate-50 hover:text-slate-900"
|
|
)}
|
|
onClick={() => {
|
|
setMobileMenuOpen(false);
|
|
handleAuthNavigation(item.href);
|
|
}}
|
|
>
|
|
<item.icon className="mr-3 h-5 w-5" />
|
|
{item.name}
|
|
</button>
|
|
)}
|
|
</div>
|
|
))}
|
|
|
|
{/* Mobile Authentication options */}
|
|
{isAuthenticated ? (
|
|
<button
|
|
onClick={() => {
|
|
logout();
|
|
setMobileMenuOpen(false);
|
|
navigate('/login');
|
|
}}
|
|
className="flex items-center rounded-md px-3 py-2 text-base font-medium button-transition text-slate-600 hover:bg-slate-50 hover:text-slate-900 w-full"
|
|
>
|
|
<LogOut className="mr-3 h-5 w-5" />
|
|
Logout
|
|
</button>
|
|
) : (
|
|
<Link
|
|
to="/login"
|
|
className="flex items-center rounded-md px-3 py-2 text-base font-medium button-transition text-slate-600 hover:bg-slate-50 hover:text-slate-900"
|
|
onClick={() => setMobileMenuOpen(false)}
|
|
>
|
|
<LogIn className="mr-3 h-5 w-5" />
|
|
Login
|
|
</Link>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</header>
|
|
);
|
|
}
|