129 lines
5.8 KiB
TypeScript
129 lines
5.8 KiB
TypeScript
'use client'
|
||
|
||
import { signOut } from 'next-auth/react'
|
||
import { Link, usePathname } from '@/i18n/routing'
|
||
import { LayoutDashboard, FileText, Inbox, ClipboardList, Map, LogOut, Menu, X, Globe, Calendar, Trash2 } from 'lucide-react'
|
||
import { useState } from 'react'
|
||
|
||
export default function AdminLayout({ children }: { children: React.ReactNode }) {
|
||
const pathname = usePathname()
|
||
const [sidebarOpen, setSidebarOpen] = useState(false)
|
||
|
||
const navigation = [
|
||
{ name: 'Dashboard', href: '/admin', icon: LayoutDashboard },
|
||
{ name: 'Mekanlar', href: '/admin/listings', icon: ClipboardList },
|
||
{ name: 'Etkinlikler', href: '/admin/events', icon: Calendar },
|
||
{ name: 'Yazılar (Blog)', href: '/admin/blog', icon: FileText },
|
||
{ name: 'Seçkiler (Kürasyon)', href: '/admin/collections', icon: ClipboardList },
|
||
{ name: 'Widget Ortakları', href: '/admin/widget-partners', icon: Globe },
|
||
{ name: 'Başvurular', href: '/admin/submissions', icon: FileText },
|
||
{ name: 'Mesajlar', href: '/admin/messages', icon: Inbox },
|
||
{ name: 'Kategoriler', href: '/admin/categories', icon: LayoutDashboard },
|
||
{ name: 'Mahalleler', href: '/admin/neighborhoods', icon: Map },
|
||
{ name: 'Çöp Kutusu', href: '/admin/trash', icon: Trash2 },
|
||
]
|
||
|
||
return (
|
||
<div className="min-h-screen bg-stone text-ink flex font-sans">
|
||
{/* Mobile sidebar backdrop */}
|
||
{sidebarOpen && (
|
||
<div
|
||
className="fixed inset-0 z-40 bg-pine/80 lg:hidden"
|
||
onClick={() => setSidebarOpen(false)}
|
||
/>
|
||
)}
|
||
|
||
{/* Sidebar */}
|
||
<div className={`
|
||
fixed inset-y-0 left-0 z-50 w-64 bg-pine border-r border-white/10
|
||
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>
|
||
{/* Sidebar Brand Header */}
|
||
<div className="h-20 flex items-center px-6 border-b border-white/10 gap-3">
|
||
<Link href="/" className="flex items-center gap-2.5">
|
||
<div className="w-9 h-9 rounded-full border border-stone/30 flex items-center justify-center relative bg-paper shrink-0">
|
||
<div className="absolute inset-[2px] rounded-full border border-dashed border-turquoise/50" />
|
||
<span className="font-heading font-extrabold text-pine text-xs tracking-tighter">ML</span>
|
||
</div>
|
||
<div>
|
||
<h1 className="font-heading font-extrabold text-sm text-stone tracking-tight leading-none lowercase">
|
||
marmaris <span className="text-turquoise">local</span>
|
||
</h1>
|
||
<span className="text-[8px] font-mono text-shutter tracking-wider uppercase">backoffice</span>
|
||
</div>
|
||
</Link>
|
||
<button
|
||
className="ml-auto lg:hidden text-stone/70 hover:text-stone"
|
||
onClick={() => setSidebarOpen(false)}
|
||
>
|
||
<X className="h-5 w-5" />
|
||
</button>
|
||
</div>
|
||
|
||
{/* Navigation links */}
|
||
<nav className="px-3 py-6 space-y-1.5 overflow-y-auto">
|
||
{navigation.map((item) => {
|
||
const isActive = pathname === item.href || (item.href !== '/admin' && pathname.startsWith(item.href))
|
||
return (
|
||
<Link
|
||
key={item.name}
|
||
href={item.href}
|
||
onClick={() => setSidebarOpen(false)}
|
||
className={`
|
||
flex items-center px-4 py-3 text-xs font-semibold rounded-xl transition-all duration-150
|
||
${isActive
|
||
? 'bg-white/5 border-l-4 border-turquoise text-stone pl-3'
|
||
: 'text-stone/75 hover:bg-white/5 hover:text-stone'}
|
||
`}
|
||
>
|
||
<item.icon className={`mr-3 flex-shrink-0 h-4.5 w-4.5 ${isActive ? 'text-turquoise' : 'text-stone/50'}`} />
|
||
{item.name}
|
||
</Link>
|
||
)
|
||
})}
|
||
</nav>
|
||
</div>
|
||
|
||
{/* Logout Action */}
|
||
<div className="p-4 border-t border-white/10">
|
||
<button
|
||
onClick={() => signOut({ callbackUrl: '/' })}
|
||
className="flex w-full items-center px-4 py-3 text-xs font-semibold text-red-400 hover:text-red-300 rounded-xl hover:bg-red-950/20 transition-colors"
|
||
>
|
||
<LogOut className="mr-3 h-4.5 w-4.5 text-red-400/70" />
|
||
Çıkış Yap
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Main content */}
|
||
<div className="flex-1 flex flex-col min-w-0 overflow-hidden">
|
||
{/* Mobile Header Bar */}
|
||
<header className="h-16 flex items-center lg:hidden bg-pine border-b border-white/10 px-4 shrink-0 text-stone">
|
||
<button
|
||
onClick={() => setSidebarOpen(true)}
|
||
className="text-stone hover:text-turquoise focus:outline-none"
|
||
>
|
||
<Menu className="h-6 w-6" />
|
||
</button>
|
||
<div className="ml-4 flex items-center gap-2">
|
||
<div className="w-8 h-8 rounded-full border border-stone/20 flex items-center justify-center relative bg-paper shrink-0">
|
||
<span className="font-heading font-extrabold text-pine text-[10px] tracking-tighter">ML</span>
|
||
</div>
|
||
<span className="text-sm font-heading font-bold lowercase">marmaris local <span className="text-turquoise">backoffice</span></span>
|
||
</div>
|
||
</header>
|
||
|
||
{/* Page Area */}
|
||
<main className="flex-1 overflow-y-auto p-4 sm:p-6 lg:p-8">
|
||
{children}
|
||
</main>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|