| import React, { useState, useEffect } from 'react'; | |
| import { Link, useLocation } from 'react-router-dom'; | |
| import { createPageUrl } from '@/utils'; | |
| import { motion, AnimatePresence } from 'framer-motion'; | |
| import { Brain, Home, BookOpen, Cpu, Target, Menu, X, Sparkles } from 'lucide-react'; | |
| import { Button } from '@/components/ui/button'; | |
| const navItems = [ | |
| { name: 'Home', icon: Home, page: 'Home' }, | |
| { name: 'Lessons', icon: BookOpen, page: 'Lessons' }, | |
| { name: 'Quiz', icon: Target, page: 'Quiz' } | |
| ]; | |
| export default function Layout({ children, currentPageName }) { | |
| const [mobileMenuOpen, setMobileMenuOpen] = useState(false); | |
| const location = useLocation(); | |
| useEffect(() => { | |
| window.scrollTo(0, 0); | |
| }, [location.pathname]); | |
| return ( | |
| <div className="min-h-screen bg-slate-900"> | |
| {/* Navigation */} | |
| <nav className="fixed top-0 left-0 right-0 z-50 bg-slate-900/80 backdrop-blur-xl border-b border-white/10"> | |
| <div className="max-w-6xl mx-auto px-6"> | |
| <div className="flex items-center justify-between h-16"> | |
| {/* Logo */} | |
| <Link to={createPageUrl('Home')} className="flex items-center gap-3"> | |
| <div className="w-10 h-10 rounded-xl bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center"> | |
| <Brain className="w-6 h-6 text-white" /> | |
| </div> | |
| <span className="font-bold text-white text-lg hidden sm:block">Computer Vision Lab</span> | |
| </Link> | |
| {/* Desktop Navigation */} | |
| <div className="hidden md:flex items-center gap-1"> | |
| {navItems.map((item) => { | |
| const isActive = currentPageName === item.page; | |
| return ( | |
| <Link key={item.page} to={createPageUrl(item.page)}> | |
| <Button | |
| variant="ghost" | |
| className={`relative rounded-xl px-4 ${ | |
| isActive | |
| ? 'text-white bg-white/10' | |
| : 'text-white/70 hover:text-white hover:bg-white/5' | |
| }`} | |
| > | |
| <item.icon className="w-4 h-4 mr-2" /> | |
| {item.name} | |
| {isActive && ( | |
| <motion.div | |
| layoutId="activeTab" | |
| className="absolute bottom-0 left-0 right-0 h-0.5 bg-gradient-to-r from-blue-500 to-purple-500" | |
| /> | |
| )} | |
| </Button> | |
| </Link> | |
| ); | |
| })} | |
| </div> | |
| {/* Mobile Menu Button */} | |
| <Button | |
| size="icon" | |
| className="md:hidden text-white bg-transparent hover:bg-white/10 border-0" | |
| onClick={() => setMobileMenuOpen(!mobileMenuOpen)} | |
| > | |
| {mobileMenuOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />} | |
| </Button> | |
| </div> | |
| </div> | |
| {/* Mobile Menu */} | |
| <AnimatePresence> | |
| {mobileMenuOpen && ( | |
| <motion.div | |
| initial={{ opacity: 0, height: 0 }} | |
| animate={{ opacity: 1, height: 'auto' }} | |
| exit={{ opacity: 0, height: 0 }} | |
| className="md:hidden bg-slate-900/95 backdrop-blur-xl border-b border-white/10" | |
| > | |
| <div className="px-6 py-4 space-y-2"> | |
| {navItems.map((item) => { | |
| const isActive = currentPageName === item.page; | |
| return ( | |
| <Link | |
| key={item.page} | |
| to={createPageUrl(item.page)} | |
| onClick={() => setMobileMenuOpen(false)} | |
| > | |
| <div className={`flex items-center gap-3 p-3 rounded-xl ${ | |
| isActive | |
| ? 'bg-white/10 text-white' | |
| : 'text-white/70 hover:bg-white/5 hover:text-white' | |
| }`}> | |
| <item.icon className="w-5 h-5" /> | |
| <span className="font-medium">{item.name}</span> | |
| </div> | |
| </Link> | |
| ); | |
| })} | |
| </div> | |
| </motion.div> | |
| )} | |
| </AnimatePresence> | |
| </nav> | |
| {/* Main Content */} | |
| <main> | |
| {children} | |
| </main> | |
| {/* Footer */} | |
| <footer className="bg-slate-900 border-t border-white/10 py-9 px-6"> | |
| <div className="max-w-6xl mx-auto"> | |
| <div className="pt-3 text-center text-white/40 text-sm"> | |
| <p>© 2026 Computer Vision Lab</p> | |
| </div> | |
| </div> | |
| </footer> | |
| </div> | |
| ); | |
| } |