Add src/app/admin/layout.tsx
This commit is contained in:
69
src/app/admin/layout.tsx
Normal file
69
src/app/admin/layout.tsx
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import Link from 'next/link';
|
||||||
|
import { usePathname } from 'next/navigation';
|
||||||
|
import { Home, Package, LayoutGrid, ShoppingCart, Users, ReceiptText, Settings, Menu } from 'lucide-react';
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
|
const adminNavItems = [
|
||||||
|
{ href: '/admin', label: 'Overview', icon: Home },
|
||||||
|
{ href: '/admin/services', label: 'Services', icon: Package },
|
||||||
|
{ href: '/admin/categories', label: 'Categories', icon: LayoutGrid },
|
||||||
|
{ href: '/admin/orders', label: 'Orders', icon: ShoppingCart },
|
||||||
|
{ href: '/admin/users', label: 'Users', icon: Users },
|
||||||
|
{ href: '/admin/transactions', label: 'Transactions', icon: ReceiptText },
|
||||||
|
{ href: '/admin/settings', label: 'Settings', icon: Settings },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function AdminLayout({ children }: { children: React.ReactNode }) {
|
||||||
|
const pathname = usePathname();
|
||||||
|
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex min-h-screen bg-neutral-950 text-white">
|
||||||
|
{/* Mobile Menu Button */}
|
||||||
|
<button
|
||||||
|
className="fixed top-4 left-4 z-50 p-2 rounded-md bg-neutral-800 lg:hidden focus:outline-none focus:ring-2 focus:ring-primary-cta"
|
||||||
|
onClick={() => setIsSidebarOpen(!isSidebarOpen)}
|
||||||
|
aria-label="Toggle sidebar"
|
||||||
|
>
|
||||||
|
<Menu className="h-6 w-6" />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{/* Sidebar */}
|
||||||
|
<aside
|
||||||
|
className={`fixed inset-y-0 left-0 z-40 w-64 bg-neutral-900 shadow-lg transform ${isSidebarOpen ? 'translate-x-0' : '-translate-x-full'} lg:translate-x-0 transition-transform duration-300 ease-in-out`}
|
||||||
|
>
|
||||||
|
<div className="p-6 border-b border-neutral-800">
|
||||||
|
<h1 className="text-2xl font-bold text-primary-cta">Admin Panel</h1>
|
||||||
|
</div>
|
||||||
|
<nav className="mt-6">
|
||||||
|
<ul>
|
||||||
|
{adminNavItems.map((item) => {
|
||||||
|
const isActive = pathname === item.href || (item.href !== '/admin' && pathname.startsWith(item.href));
|
||||||
|
return (
|
||||||
|
<li key={item.href}>
|
||||||
|
<Link
|
||||||
|
href={item.href}
|
||||||
|
className={`flex items-center gap-3 px-6 py-3 text-lg font-medium transition-colors duration-200 ${isActive ? 'bg-primary-cta text-white' : 'text-neutral-300 hover:bg-neutral-800 hover:text-white'}`}
|
||||||
|
onClick={() => setIsSidebarOpen(false)} // Close sidebar on nav item click
|
||||||
|
>
|
||||||
|
<item.icon className="h-5 w-5" />
|
||||||
|
{item.label}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
{/* Main Content */}
|
||||||
|
<main className={`flex-1 transition-all duration-300 ease-in-out ${isSidebarOpen ? 'lg:ml-64 ml-0' : 'lg:ml-64 ml-0'} p-8 pt-16 lg:pt-8`}>
|
||||||
|
<div className="max-w-7xl mx-auto">
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user