tia/src/app/admin/layout.tsx

120 lines
No EOL
4 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
import { useRouter, usePathname } from "next/navigation";
import Link from "next/link";
interface NavItem {
name: string;
href: string;
icon: string;
}
const navItems: NavItem[] = [
{ name: "Dashboard", href: "/admin", icon: "📊" },
{ name: "Families", href: "/admin/families", icon: "🏠" },
{ name: "Users", href: "/admin/users", icon: "👥" },
{ name: "Children", href: "/admin/children", icon: "👶" },
{ name: "Revenue", href: "/admin/revenue", icon: "💰" },
{ name: "Analytics", href: "/admin/analytics", icon: "📈" },
{ name: "Support", href: "/admin/support", icon: "🎫" },
{ name: "Settings", href: "/admin/settings", icon: "⚙️" },
];
export default function AdminLayout({ children }: { children: React.ReactNode }) {
const router = useRouter();
const pathname = usePathname();
const [sidebarOpen, setSidebarOpen] = useState(true);
const [admin, setAdmin] = useState<{ username: string; role: string } | null>(null);
// Check if this is the login page - don't show sidebar
const isLoginPage = pathname === "/admin-login";
useEffect(() => {
// Only check auth if not on login page
if (isLoginPage) return;
const token = localStorage.getItem("admin_token");
if (!token) {
router.push("/admin/login");
return;
}
const stored = localStorage.getItem("admin_user");
if (stored) {
setAdmin(JSON.parse(stored));
}
}, [router, isLoginPage]);
const handleLogout = () => {
localStorage.removeItem("admin_token");
localStorage.removeItem("admin_user");
router.push("/admin/login");
};
// Login page - render without sidebar
if (isLoginPage) {
return (
<div className="min-h-screen bg-gray-900 text-white">
{children}
</div>
);
}
// Main layout with sidebar
return (
<div className="min-h-screen bg-gray-900 text-white flex">
{/* Sidebar */}
<aside className={`${sidebarOpen ? "w-64" : "w-16"} bg-gray-800 flex-shrink-0 transition-all duration-300 flex flex-col`}>
{/* Header */}
<div className="p-4 flex items-center justify-between border-b border-gray-700">
{sidebarOpen && (
<Link href="/admin" className="text-lg font-bold text-rose-400">
Tia Admin
</Link>
)}
<button onClick={() => setSidebarOpen(!sidebarOpen)} className="text-gray-400 hover:text-white">
{sidebarOpen ? "◀" : "▶"}
</button>
</div>
{/* Navigation */}
<nav className="flex-1 p-2 space-y-1 overflow-y-auto">
{navItems.map((item) => {
const isActive = pathname === item.href || (item.href !== "/admin" && pathname.startsWith(item.href));
return (
<Link
key={item.name}
href={item.href}
className={`flex items-center gap-3 px-3 py-2.5 rounded-lg transition-colors ${
isActive ? "bg-rose-500/20 text-rose-400" : "text-gray-400 hover:bg-gray-700 hover:text-white"
}`}
>
<span className="text-lg">{item.icon}</span>
{sidebarOpen && <span className="font-medium">{item.name}</span>}
</Link>
);
})}
</nav>
{/* Footer */}
<div className="mt-auto p-4 border-t border-gray-700">
{sidebarOpen && admin && (
<div className="mb-3">
<div className="text-sm font-medium">{admin.username}</div>
<div className="text-xs text-gray-400">{admin.role}</div>
</div>
)}
<button
onClick={handleLogout}
className="w-full px-3 py-2 bg-gray-700 text-gray-400 hover:text-white rounded-lg text-sm"
>
{sidebarOpen ? "Logout" : "🚪"}
</button>
</div>
</aside>
{/* Main Content */}
<main className="flex-1 overflow-auto">{children}</main>
</div>
);
}