137 lines
6.1 KiB
TypeScript
137 lines
6.1 KiB
TypeScript
'use client';
|
|
|
|
import Link from 'next/link';
|
|
import { usePathname } from 'next/navigation';
|
|
import { useAuth } from '@/contexts/AuthContext';
|
|
import { useState } from 'react';
|
|
import {
|
|
UsersIcon,
|
|
CubeIcon,
|
|
TagIcon,
|
|
BellIcon,
|
|
GiftIcon,
|
|
PowerIcon,
|
|
ShoppingBagIcon,
|
|
HomeIcon,
|
|
CalculatorIcon,
|
|
ChartBarIcon,
|
|
Bars3Icon,
|
|
XMarkIcon,
|
|
} from '@heroicons/react/24/outline';
|
|
import { MegaphoneIcon } from 'lucide-react';
|
|
import ThemeToggle from '@/components/ThemeToggle';
|
|
|
|
const navItems = [
|
|
{ href: '/admin/dashboard', label: 'داشبورد', Icon: HomeIcon },
|
|
{ href: '/admin/users', label: 'کاربران', Icon: UsersIcon },
|
|
{ href: '/admin/purchases', label: 'خریدها', Icon: ShoppingBagIcon },
|
|
{ href: '/admin/accounting', label: 'حسابداری', Icon: CalculatorIcon },
|
|
{ href: '/admin/auth-analytics', label: 'ورود و پیامک', Icon: ChartBarIcon },
|
|
{ href: '/admin/packages', label: 'پکیجها', Icon: CubeIcon },
|
|
{ href: '/admin/products', label: 'محصولات', Icon: TagIcon },
|
|
{ href: '/admin/reminders', label: 'یادآوریها', Icon: BellIcon },
|
|
{ href: '/admin/promotions', label: 'تبلیغات', Icon: MegaphoneIcon },
|
|
{ href: '/admin/referral-rewards', label: 'پاداش معرفی', Icon: GiftIcon },
|
|
];
|
|
|
|
export default function Sidebar() {
|
|
const pathname = usePathname();
|
|
const { logout, user } = useAuth();
|
|
const [mobileOpen, setMobileOpen] = useState(false);
|
|
|
|
const isActive = (href: string) => {
|
|
if (href === '/admin/dashboard') return pathname === href;
|
|
return pathname.startsWith(href);
|
|
};
|
|
|
|
const navContent = (
|
|
<div className="flex flex-col h-full">
|
|
{/* Logo / Brand */}
|
|
<div className="flex items-center gap-3 px-5 py-5 border-b border-gray-200 dark:border-gray-800">
|
|
<div className="flex-shrink-0 h-9 w-9 rounded-xl bg-indigo-600 flex items-center justify-center shadow-sm shadow-indigo-500/20">
|
|
<span className="text-white font-bold text-sm">A</span>
|
|
</div>
|
|
<div className="min-w-0">
|
|
<p className="text-sm font-bold text-gray-900 dark:text-gray-100 truncate">اپروایجنسی</p>
|
|
<p className="text-xs text-gray-500 dark:text-gray-400 truncate">پنل مدیریت</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Navigation */}
|
|
<nav className="flex-1 px-3 py-4 space-y-1 overflow-y-auto">
|
|
{navItems.map(({ href, label, Icon }) => {
|
|
const active = isActive(href);
|
|
return (
|
|
<Link
|
|
key={href}
|
|
href={href}
|
|
onClick={() => setMobileOpen(false)}
|
|
className={`flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm font-medium transition-all duration-150 ${
|
|
active
|
|
? 'bg-indigo-50 text-indigo-700 dark:bg-indigo-500/10 dark:text-indigo-400 shadow-sm'
|
|
: 'text-gray-600 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-gray-200'
|
|
}`}
|
|
>
|
|
<Icon className={`h-5 w-5 flex-shrink-0 ${active ? 'text-indigo-600 dark:text-indigo-400' : ''}`} />
|
|
{label}
|
|
</Link>
|
|
);
|
|
})}
|
|
</nav>
|
|
|
|
{/* User, Theme & Logout */}
|
|
<div className="border-t border-gray-200 dark:border-gray-800 px-3 py-4 space-y-1">
|
|
<ThemeToggle withLabel className="w-full justify-start px-3 py-2.5 rounded-xl text-sm font-medium" />
|
|
{user && (
|
|
<div className="px-3 py-2">
|
|
<p className="text-xs text-gray-500 dark:text-gray-400 truncate" dir="ltr">{user.email}</p>
|
|
</div>
|
|
)}
|
|
<button
|
|
onClick={logout}
|
|
className="flex items-center gap-3 w-full px-3 py-2.5 rounded-xl text-sm font-medium text-red-600 hover:bg-red-50 dark:text-red-400 dark:hover:bg-red-500/10 transition-colors"
|
|
>
|
|
<PowerIcon className="h-5 w-5" />
|
|
خروج
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
|
|
return (
|
|
<>
|
|
{/* Mobile hamburger */}
|
|
<button
|
|
onClick={() => setMobileOpen(true)}
|
|
className="lg:hidden fixed top-4 right-4 z-50 p-2 rounded-xl bg-white dark:bg-gray-900 shadow-lg ring-1 ring-gray-200 dark:ring-gray-800 text-gray-600 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors"
|
|
>
|
|
<Bars3Icon className="h-6 w-6" />
|
|
</button>
|
|
|
|
{/* Mobile overlay */}
|
|
{mobileOpen && (
|
|
<div className="lg:hidden fixed inset-0 z-40">
|
|
<div
|
|
className="absolute inset-0 bg-black/40 dark:bg-black/60 backdrop-blur-sm"
|
|
onClick={() => setMobileOpen(false)}
|
|
/>
|
|
<div className="absolute inset-y-0 right-0 w-72 bg-white dark:bg-gray-950 shadow-2xl">
|
|
<button
|
|
onClick={() => setMobileOpen(false)}
|
|
className="absolute top-4 left-4 p-1 rounded-lg text-gray-400 hover:text-gray-600 dark:hover:text-gray-200"
|
|
>
|
|
<XMarkIcon className="h-5 w-5" />
|
|
</button>
|
|
{navContent}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Desktop sidebar */}
|
|
<aside className="hidden lg:flex lg:fixed lg:inset-y-0 lg:right-0 lg:z-30 lg:w-64 lg:flex-col bg-white dark:bg-gray-950 border-l border-gray-200 dark:border-gray-800">
|
|
{navContent}
|
|
</aside>
|
|
</>
|
|
);
|
|
}
|