AhmedSamir1598's picture
Add frontend source files and fix Dockerfile npm install fallback
15225f7
import { useState } from 'react'
import { Link, useLocation, useNavigate } from 'react-router-dom'
import { useAuth } from '../contexts/AuthContext'
import {
Zap,
Menu,
X,
LayoutDashboard,
Grid3X3,
Calculator,
FileText,
Users,
LogOut,
DollarSign
} from 'lucide-react'
export default function Navbar() {
const [isOpen, setIsOpen] = useState(false)
const { user, signOut } = useAuth()
const location = useLocation()
const navigate = useNavigate()
const handleSignOut = async () => {
await signOut()
navigate('/')
}
const isActive = (path) => location.pathname === path
const navLinks = user ? [
{ path: '/dashboard', label: 'Dashboard', icon: LayoutDashboard },
{ path: '/grid', label: 'Grid View', icon: Grid3X3 },
{ path: '/roi', label: 'ROI Calculator', icon: Calculator },
{ path: '/audit', label: 'Audit Logs', icon: FileText },
] : [
{ path: '/', label: 'Home', icon: null },
{ path: '/pricing', label: 'Pricing', icon: DollarSign },
{ path: '/about', label: 'About', icon: Users },
]
return (
<nav className="bg-white/95 backdrop-blur shadow-md sticky top-0 z-50">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between h-16">
{/* Logo */}
<Link to={user ? '/dashboard' : '/'} className="flex items-center gap-2 hover-lift">
<div className="w-9 h-9 rounded-full bg-gradient-to-br from-primary-500 to-accent-500 flex items-center justify-center glow-ring">
<Zap className="w-5 h-5 text-white" />
</div>
<span className="font-display font-bold text-xl text-dark-800">
Opti<span className="gradient-text">Q</span>
</span>
</Link>
{/* Desktop Navigation */}
<div className="hidden md:flex items-center gap-6">
{navLinks.map((link) => (
<Link
key={link.path}
to={link.path}
className={`flex items-center gap-2 px-3 py-2 rounded-lg transition-colors hover-lift ${
isActive(link.path)
? 'bg-primary-50 text-primary-600 font-medium'
: 'text-dark-600 hover:text-primary-600 hover:bg-dark-50'
}`}
>
{link.icon && <link.icon className="w-4 h-4" />}
{link.label}
</Link>
))}
{user ? (
<div className="flex items-center gap-4 ml-4 pl-4 border-l border-dark-200">
<span className="text-sm text-dark-500">
{user.displayName || user.email}
</span>
<button
onClick={handleSignOut}
className="flex items-center gap-2 px-3 py-2 text-dark-600 hover:text-red-600 rounded-lg hover:bg-red-50 transition-colors hover-lift"
>
<LogOut className="w-4 h-4" />
Sign Out
</button>
</div>
) : (
<div className="flex items-center gap-3 ml-4">
<Link to="/login" className="btn-outline btn text-sm py-2">
Log In
</Link>
<Link to="/signup" className="btn-primary btn text-sm py-2">
Get Started
</Link>
</div>
)}
</div>
{/* Mobile menu button */}
<div className="md:hidden flex items-center">
<button
onClick={() => setIsOpen(!isOpen)}
className="p-2 rounded-lg text-dark-600 hover:bg-dark-100"
>
{isOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
</button>
</div>
</div>
{/* Mobile Navigation */}
{isOpen && (
<div className="md:hidden pb-4">
<div className="flex flex-col gap-2">
{navLinks.map((link) => (
<Link
key={link.path}
to={link.path}
onClick={() => setIsOpen(false)}
className={`flex items-center gap-2 px-4 py-3 rounded-lg ${
isActive(link.path)
? 'bg-primary-50 text-primary-600 font-medium'
: 'text-dark-600 hover:bg-dark-50'
}`}
>
{link.icon && <link.icon className="w-5 h-5" />}
{link.label}
</Link>
))}
{user ? (
<button
onClick={handleSignOut}
className="flex items-center gap-2 px-4 py-3 text-red-600 hover:bg-red-50 rounded-lg mt-2"
>
<LogOut className="w-5 h-5" />
Sign Out
</button>
) : (
<div className="flex flex-col gap-2 mt-4 pt-4 border-t border-dark-200">
<Link to="/login" className="btn-outline btn text-center">
Log In
</Link>
<Link to="/signup" className="btn-primary btn text-center">
Get Started
</Link>
</div>
)}
</div>
</div>
)}
</div>
</nav>
)
}