108 lines
4.2 KiB
TypeScript
108 lines
4.2 KiB
TypeScript
'use client'
|
||
|
||
import { signOut } from 'next-auth/react'
|
||
import Link from 'next/link'
|
||
import Image from 'next/image'
|
||
import { usePathname, useParams } from 'next/navigation'
|
||
import { LayoutDashboard, Users, Settings, LogOut, Menu, X } from 'lucide-react'
|
||
import { useState } from 'react'
|
||
|
||
export default function AdminLayout({ children }: { children: React.ReactNode }) {
|
||
const pathname = usePathname()
|
||
const params = useParams()
|
||
const locale = (params?.locale as string) || 'tr'
|
||
const [sidebarOpen, setSidebarOpen] = useState(false)
|
||
|
||
const navigation = [
|
||
{ name: 'Dashboard', href: `/${locale}/admin`, icon: LayoutDashboard },
|
||
{ name: 'Kullanıcılar', href: `/${locale}/admin/users`, icon: Users },
|
||
{ name: 'Ayarlar', href: `/${locale}/admin/settings`, icon: Settings },
|
||
]
|
||
|
||
return (
|
||
<div className="min-h-screen bg-zinc-50 flex">
|
||
{/* Mobile sidebar backdrop */}
|
||
{sidebarOpen && (
|
||
<div
|
||
className="fixed inset-0 z-40 bg-zinc-950/60 lg:hidden"
|
||
onClick={() => setSidebarOpen(false)}
|
||
/>
|
||
)}
|
||
|
||
{/* Sidebar */}
|
||
<div className={`
|
||
fixed inset-y-0 left-0 z-50 w-64 bg-white border-r border-zinc-200
|
||
transform transition-transform duration-200 ease-in-out lg:translate-x-0 lg:static lg:inset-0
|
||
${sidebarOpen ? 'translate-x-0' : '-translate-x-full'}
|
||
`}>
|
||
<div className="h-full flex flex-col justify-between">
|
||
<div>
|
||
<div className="h-16 flex items-center justify-between px-6 border-b border-zinc-100">
|
||
<Link href={`/${locale}`} className="flex items-center gap-2">
|
||
<Image src="/logo.png" alt="AyrisLegal" width={110} height={22} className="h-5 w-auto object-contain" priority />
|
||
</Link>
|
||
<button
|
||
className="lg:hidden text-zinc-500 hover:text-zinc-900"
|
||
onClick={() => setSidebarOpen(false)}
|
||
aria-label="Menüyü Kapat"
|
||
>
|
||
<X className="h-5 w-5" />
|
||
</button>
|
||
</div>
|
||
|
||
<nav className="px-4 py-6 space-y-1 overflow-y-auto">
|
||
{navigation.map((item) => {
|
||
const isActive = pathname === item.href || (item.href !== `/${locale}/admin` && pathname.startsWith(item.href))
|
||
return (
|
||
<Link
|
||
key={item.name}
|
||
href={item.href}
|
||
className={`
|
||
flex items-center px-3.5 py-2.5 text-sm font-semibold rounded-xl transition-all
|
||
${isActive
|
||
? 'bg-[#FDEEEC] text-[#B8140F]'
|
||
: 'text-zinc-600 hover:bg-zinc-100/70 hover:text-zinc-900'}
|
||
`}
|
||
>
|
||
<item.icon className={`mr-3 flex-shrink-0 h-4 w-4 ${isActive ? 'text-[#B8140F]' : 'text-zinc-500'}`} />
|
||
{item.name}
|
||
</Link>
|
||
)
|
||
})}
|
||
</nav>
|
||
</div>
|
||
|
||
<div className="p-4 border-t border-zinc-100">
|
||
<button
|
||
onClick={() => signOut({ callbackUrl: `/${locale}` })}
|
||
className="flex w-full items-center px-3.5 py-2.5 text-sm font-semibold text-zinc-700 hover:text-[#B8140F] rounded-xl hover:bg-[#FDEEEC] transition-colors"
|
||
>
|
||
<LogOut className="mr-3 h-4 w-4" />
|
||
Çıkış Yap
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Main content */}
|
||
<div className="flex-1 flex flex-col min-w-0 overflow-hidden">
|
||
<header className="h-16 flex items-center justify-between lg:hidden bg-white border-b border-zinc-200 px-4">
|
||
<button
|
||
onClick={() => setSidebarOpen(true)}
|
||
className="text-zinc-600 hover:text-zinc-900 focus:outline-none"
|
||
aria-label="Menüyü Aç"
|
||
>
|
||
<Menu className="h-6 w-6" />
|
||
</button>
|
||
<span className="text-sm font-bold text-zinc-900">Admin Paneli</span>
|
||
<div className="w-6" />
|
||
</header>
|
||
|
||
<main className="flex-1 overflow-y-auto p-5 sm:p-8 max-w-[1400px]">
|
||
{children}
|
||
</main>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|