AIEXTRACT1 / frontend /src /Layout.jsx
Seth0330's picture
Update frontend/src/Layout.jsx
53fd305 verified
raw
history blame
4.71 kB
// 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 &amp; 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>
);
}