pratikfrontend / components /Layout.tsx
Antaram's picture
Upload 61 files
24c454f verified
Raw
History Blame Contribute Delete
5.86 kB
import React, { useState } from 'react';
import { Link, useLocation } from 'react-router-dom';
import {
Home,
FileInput,
FileOutput,
Users,
Package,
Settings,
Menu,
X,
TrendingUp
} from 'lucide-react';
interface LayoutProps {
children: React.ReactNode;
}
const Layout: React.FC<LayoutProps> = ({ children }) => {
const [isSidebarOpen, setSidebarOpen] = useState(false);
const location = useLocation();
const navItems = [
{ path: '/', label: 'डॅशबोर्ड (Home)', icon: Home },
{ path: '/jawaak', label: 'जावक बिल (Sales)', icon: FileOutput },
{ path: '/awaak', label: 'आवक बिल (Purchase)', icon: FileInput },
{ path: '/ledger', label: 'पार्टी लेजर (Ledger)', icon: Users },
// { path: '/patti-ledger', label: 'पट्टी लेजर (Patti Ledger)', icon: Users },
{ path: '/stock', label: 'स्टॉक रिपोर्ट (Stock)', icon: Package },
{ path: '/patti-stock', label: 'पट्टी स्टॉक (Patti Stock)', icon: Package },
{ path: '/analysis', label: 'अ‍ॅनालिसीस (Analysis)', icon: TrendingUp },
{ path: '/patti-analysis', label: 'पट्टी अ‍ॅनालिसीस (Patti Analysis)', icon: TrendingUp },
{ path: '/settings', label: 'सेटिंग्स (Settings)', icon: Settings },
];
const isActive = (path: string) => {
if (path === '/') {
return location.pathname === '/';
}
return location.pathname.startsWith(path);
};
return (
<div className="flex h-screen bg-gray-50 overflow-hidden">
{/* Mobile Sidebar Overlay */}
{isSidebarOpen && (
<div
className="fixed inset-0 bg-black bg-opacity-50 z-20 lg:hidden"
onClick={() => setSidebarOpen(false)}
/>
)}
{/* Sidebar */}
<aside
className={`fixed lg:static inset-y-0 left-0 w-64 bg-teal-800 text-white transform transition-transform duration-200 ease-in-out z-30 ${isSidebarOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'
}`}
>
<div className="flex items-center justify-between p-4 border-b border-teal-700 h-16">
<div className="flex items-center gap-2">
<TrendingUp className="w-6 h-6 text-teal-300" />
<span className="font-bold text-xl">Mirchi Vyapar</span>
</div>
<button
className="lg:hidden p-1 hover:bg-teal-700 rounded"
onClick={() => setSidebarOpen(false)}
>
<X size={24} />
</button>
</div>
<nav className="p-4 space-y-1">
{navItems.map((item) => (
<Link
key={item.path}
to={item.path}
onClick={() => setSidebarOpen(false)}
className={`flex items-center gap-3 px-4 py-3 rounded-lg transition-colors ${isActive(item.path)
? 'bg-teal-900 text-teal-100 shadow-sm'
: 'text-teal-100 hover:bg-teal-700'
}`}
>
<item.icon size={20} />
<span className="font-medium">{item.label}</span>
</Link>
))}
</nav>
<div className="absolute bottom-0 w-full p-4 border-t border-teal-700 bg-teal-800">
<div className="flex items-center gap-3">
<div className="w-8 h-8 rounded-full bg-teal-600 flex items-center justify-center font-bold">
A
</div>
<div>
<p className="text-sm font-medium">Admin User</p>
<p className="text-xs text-teal-300">Mirchi Mandi</p>
</div>
</div>
</div>
</aside>
{/* Main Content */}
<main className="flex-1 flex flex-col overflow-hidden">
{/* Top Header */}
<header className="h-16 bg-white border-b flex items-center justify-between px-4 lg:px-8">
<button
className="lg:hidden p-2 -ml-2 text-gray-600 hover:bg-gray-100 rounded-lg"
onClick={() => setSidebarOpen(true)}
>
<Menu size={24} />
</button>
<h1 className="text-xl font-semibold text-gray-800 ml-2 lg:ml-0">
{navItems.find(i => isActive(i.path))?.label.split(' (')[0] || 'Mirchi Vyapar'}
</h1>
<div className="flex items-center gap-4">
<span className="text-sm text-gray-500 hidden md:block">
{new Date().toLocaleDateString('mr-IN', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })}
</span>
</div>
</header>
{/* Page Content */}
<div className="flex-1 overflow-auto p-4 lg:p-6 pb-20 lg:pb-6">
{children}
</div>
</main>
</div>
);
};
export default Layout;