Spaces:
Sleeping
Sleeping
| // frontend/src/Layout.jsx | |
| import React, { useState } from "react"; | |
| import { Link } from "react-router-dom"; | |
| import { createPageUrl } from "./utils"; | |
| import { | |
| ScanText, | |
| LayoutDashboard, | |
| History as HistoryIcon, | |
| ChevronLeft, | |
| Sparkles, | |
| } from "lucide-react"; | |
| import { cn } from "@/lib/utils"; | |
| export default function Layout({ children, currentPageName }) { | |
| const [collapsed, setCollapsed] = useState(false); | |
| const navItems = [ | |
| { name: "Dashboard", icon: LayoutDashboard, page: "Dashboard" }, | |
| { name: "History", icon: HistoryIcon, page: "History" }, | |
| ]; | |
| return ( | |
| <div className="min-h-screen bg-[#FAFAFA] flex"> | |
| {/* Sidebar */} | |
| <aside | |
| className={cn( | |
| "fixed left-0 top-0 h-screen bg-white border-r border-slate-200/80 z-50 transition-all duration-300 ease-out flex flex-col", | |
| collapsed ? "w-[72px]" : "w-[260px]" | |
| )} | |
| > | |
| {/* Logo */} | |
| <div | |
| className={cn( | |
| "h-16 flex items-center border-b border-slate-100 px-4", | |
| collapsed ? "justify-center" : "justify-between" | |
| )} | |
| > | |
| <Link to={createPageUrl("Dashboard")} className="flex items-center gap-3"> | |
| <div className="h-9 w-9 rounded-xl bg-gradient-to-br from-indigo-500 to-violet-600 flex items-center justify-center shadow-lg shadow-indigo-500/25"> | |
| <ScanText className="h-5 w-5 text-white" /> | |
| </div> | |
| {!collapsed && ( | |
| <div className="flex flex-col"> | |
| <span className="font-semibold text-slate-900 tracking-tight">EZOFIS AI</span> | |
| <span className="text-[10px] text-slate-400 font-medium tracking-wide uppercase"> | |
| Agentic Extract | |
| </span> | |
| </div> | |
| )} | |
| </Link> | |
| {!collapsed && ( | |
| <button | |
| onClick={() => setCollapsed(true)} | |
| className="h-7 w-7 rounded-lg hover:bg-slate-100 flex items-center justify-center text-slate-400 hover:text-slate-600 transition-colors" | |
| > | |
| <ChevronLeft className="h-4 w-4" /> | |
| </button> | |
| )} | |
| </div> | |
| {/* Navigation */} | |
| <nav className="flex-1 p-3 space-y-1"> | |
| {navItems.map((item) => { | |
| const isActive = currentPageName === item.page; | |
| return ( | |
| <Link | |
| key={item.name} | |
| to={createPageUrl(item.page)} | |
| className={cn( | |
| "flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-200 group", | |
| isActive | |
| ? "bg-gradient-to-r from-indigo-50 to-violet-50 text-indigo-600" | |
| : "text-slate-500 hover:bg-slate-50 hover:text-slate-700" | |
| )} | |
| > | |
| <item.icon | |
| className={cn( | |
| "h-5 w-5 flex-shrink-0", | |
| isActive ? "text-indigo-600" : "text-slate-400 group-hover:text-slate-600" | |
| )} | |
| /> | |
| {!collapsed && ( | |
| <span className="font-medium text-sm">{item.name}</span> | |
| )} | |
| </Link> | |
| ); | |
| })} | |
| </nav> | |
| {/* Collapse Toggle (when collapsed) */} | |
| {collapsed && ( | |
| <button | |
| onClick={() => setCollapsed(false)} | |
| className="m-3 h-10 rounded-xl bg-slate-50 hover:bg-slate-100 flex items-center justify-center text-slate-400 hover:text-slate-600 transition-colors" | |
| > | |
| <ChevronLeft className="h-4 w-4 rotate-180" /> | |
| </button> | |
| )} | |
| {/* Pro Badge */} | |
| {!collapsed && ( | |
| <div className="p-3"> | |
| <div className="p-4 rounded-2xl bg-gradient-to-br from-slate-900 to-slate-800 text-white"> | |
| <div className="flex items-center gap-2 mb-2"> | |
| <Sparkles className="h-4 w-4 text-amber-400" /> | |
| <span className="text-xs font-semibold tracking-wide">DEPLOY THIS AGENT</span> | |
| </div> | |
| <p className="text-xs text-slate-400 mb-3"> | |
| Unlock batch extractions & API access | |
| </p> | |
| <button className="w-full py-2 px-3 rounded-lg bg-white text-slate-900 text-sm font-semibold hover:bg-slate-100 transition-colors"> | |
| Talk to us | |
| </button> | |
| </div> | |
| </div> | |
| )} | |
| </aside> | |
| {/* Main Content */} | |
| <main | |
| className={cn( | |
| "flex-1 transition-all duration-300", | |
| collapsed ? "ml-[72px]" : "ml-[260px]" | |
| )} | |
| > | |
| {children} | |
| </main> | |
| </div> | |
| ); | |
| } | |