185 lines
8.5 KiB
TypeScript
185 lines
8.5 KiB
TypeScript
'use client'
|
||
|
||
import { useState, useEffect } from 'react'
|
||
import Link from 'next/link'
|
||
import Image from 'next/image'
|
||
import { usePathname } from 'next/navigation'
|
||
import {
|
||
HomeIcon,
|
||
UsersIcon,
|
||
CalendarDaysIcon,
|
||
BuildingOfficeIcon,
|
||
Cog6ToothIcon,
|
||
ArrowRightOnRectangleIcon,
|
||
Bars3Icon,
|
||
XMarkIcon,
|
||
} from '@heroicons/react/24/outline'
|
||
|
||
const navigation = [
|
||
{ name: 'Dashboard', href: '/', icon: HomeIcon },
|
||
{ name: 'Personeller', href: '/employees', icon: UsersIcon },
|
||
{ name: 'İzinler', href: '/leave-requests', icon: CalendarDaysIcon },
|
||
{ name: 'Şirketler', href: '/companies', icon: BuildingOfficeIcon },
|
||
{ name: 'Ayarlar', href: '/settings', icon: Cog6ToothIcon },
|
||
]
|
||
|
||
interface SidebarProps {
|
||
isAdmin?: boolean
|
||
}
|
||
|
||
export function Sidebar({ isAdmin = false }: SidebarProps) {
|
||
const pathname = usePathname()
|
||
const [sidebarOpen, setSidebarOpen] = useState(false)
|
||
|
||
const filteredNavigation = navigation.filter(item => {
|
||
if (item.href === '/companies') return isAdmin
|
||
return true
|
||
})
|
||
|
||
// Listen for mobile menu open event from Header
|
||
useEffect(() => {
|
||
const handleOpen = () => setSidebarOpen(true);
|
||
window.addEventListener('open-mobile-menu', handleOpen);
|
||
return () => window.removeEventListener('open-mobile-menu', handleOpen);
|
||
}, []);
|
||
|
||
return (
|
||
<>
|
||
{/* Drawer logic is below, Mobile Header is now in Header.tsx */}
|
||
|
||
{/* Mobile Sidebar Overlay (Drawer) */}
|
||
{sidebarOpen && (
|
||
<div className="relative z-50 lg:hidden" aria-modal="true">
|
||
<div className="fixed inset-0 bg-slate-900/60 backdrop-blur-sm transition-opacity" onClick={() => setSidebarOpen(false)} />
|
||
<div className="fixed inset-0 flex">
|
||
<div className="relative flex w-full max-w-xs flex-1 transform transition duration-300 ease-in-out">
|
||
<div className="absolute right-0 top-0 -mr-12 pt-4">
|
||
<button
|
||
type="button"
|
||
className="ml-1 flex h-10 w-10 items-center justify-center rounded-full focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white"
|
||
onClick={() => setSidebarOpen(false)}
|
||
>
|
||
<span className="sr-only">Menüyü Kapat</span>
|
||
<XMarkIcon className="h-6 w-6 text-white" aria-hidden="true" />
|
||
</button>
|
||
</div>
|
||
|
||
{/* Mobile Sidebar Content - Reusing Desktop Style */}
|
||
<div className="flex grow flex-col gap-y-5 overflow-y-auto bg-[#173363] px-6 pb-4 shadow-2xl">
|
||
<div className="flex h-24 shrink-0 items-center mt-4 border-b border-white/10">
|
||
<div className="flex flex-col gap-1">
|
||
<Image src="/logo.png" alt="Abisena Logo" width={140} height={45} className="h-10 w-auto object-contain" />
|
||
<span className="text-[9px] font-black text-slate-400 tracking-[0.3em] uppercase ml-1">Personel Takip Sistemi</span>
|
||
</div>
|
||
</div>
|
||
<nav className="flex flex-1 flex-col">
|
||
<ul role="list" className="flex flex-1 flex-col gap-y-7">
|
||
<li>
|
||
<ul role="list" className="-mx-2 space-y-2">
|
||
{filteredNavigation.map((item) => (
|
||
<li key={item.name}>
|
||
<Link
|
||
href={item.href}
|
||
onClick={() => setSidebarOpen(false)}
|
||
className={`
|
||
group flex items-center gap-x-3 rounded-xl p-3 text-sm leading-6 font-semibold transition-all
|
||
${pathname === item.href
|
||
? 'bg-[#CE0515] text-white'
|
||
: 'text-slate-300 hover:text-white hover:bg-white/5'
|
||
}
|
||
`}
|
||
>
|
||
<item.icon
|
||
className={`h-5 w-5 shrink-0 ${pathname === item.href ? 'text-white' : 'text-slate-400 group-hover:text-white'}`}
|
||
aria-hidden="true"
|
||
/>
|
||
{item.name}
|
||
</Link>
|
||
</li>
|
||
))}
|
||
</ul>
|
||
</li>
|
||
<li className="mt-auto">
|
||
<form action="/auth/signout" method="post" className="-mx-2 pb-4">
|
||
<button type="submit" className="group flex w-full items-center gap-x-3 rounded-xl p-3 text-sm font-bold text-slate-400 hover:text-white transition-all">
|
||
<ArrowRightOnRectangleIcon className="h-5 w-5 shrink-0" />
|
||
Güvenli Çıkış
|
||
</button>
|
||
</form>
|
||
</li>
|
||
</ul>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{/* Desktop Sidebar */}
|
||
<div className="hidden lg:fixed lg:inset-y-0 lg:z-50 lg:flex lg:w-72 lg:flex-col">
|
||
<div className="flex grow flex-col gap-y-5 overflow-y-auto bg-[#173363] px-6 pb-4 shadow-xl">
|
||
<div className="flex h-24 shrink-0 items-center mt-6 mb-2 border-b border-gray-100/50 dark:border-zinc-900/50">
|
||
<div className="flex flex-col items-start gap-2 group cursor-pointer w-full">
|
||
<div className="p-2 transition-all duration-300 group-hover:brightness-110">
|
||
<Image src="/logo.png" alt="Abisena Logo" width={180} height={60} className="h-12 w-auto object-contain" priority />
|
||
</div>
|
||
<div className="px-2 w-full">
|
||
<div className="h-px w-full bg-gradient-to-r from-gray-200 via-gray-100 to-transparent dark:from-zinc-800 dark:via-zinc-900 dark:to-transparent mb-2" />
|
||
<span className="text-[10px] font-black text-gray-400 dark:text-zinc-500 tracking-[0.3em] uppercase ml-1 block">Personel Takip Sistemi</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<nav className="flex flex-1 flex-col">
|
||
<ul role="list" className="flex flex-1 flex-col gap-y-7">
|
||
<li>
|
||
<div className="text-[10px] font-bold tracking-widest leading-6 text-slate-400 mb-4 uppercase">YÖNETİM PANELİ</div>
|
||
<ul role="list" className="-mx-2 space-y-2">
|
||
{filteredNavigation.map((item) => (
|
||
<li key={item.name}>
|
||
<Link
|
||
href={item.href}
|
||
className={`
|
||
group flex items-center gap-x-3 rounded-xl p-3 text-sm leading-6 font-semibold transition-all duration-300 relative overflow-hidden
|
||
${pathname === item.href
|
||
? 'bg-[#CE0515] text-white shadow-lg shadow-red-900/20'
|
||
: 'text-slate-300 hover:text-white hover:bg-white/5'
|
||
}
|
||
`}
|
||
>
|
||
<item.icon
|
||
className={`h-5 w-5 shrink-0 transition-colors duration-200 ${pathname === item.href ? 'text-white' : 'text-slate-400 group-hover:text-white'}`}
|
||
aria-hidden="true"
|
||
/>
|
||
{item.name}
|
||
{pathname === item.href && (
|
||
<div className="ml-auto w-1.5 h-1.5 rounded-full bg-white animate-pulse" />
|
||
)}
|
||
</Link>
|
||
</li>
|
||
))}
|
||
</ul>
|
||
</li>
|
||
<li className="mt-auto">
|
||
<form action="/auth/signout" method="post" className="-mx-2 pb-4">
|
||
<button
|
||
type="submit"
|
||
className="group flex w-full items-center gap-x-3 rounded-2xl p-3 text-sm font-bold leading-6 text-slate-500 hover:text-rose-600 dark:text-zinc-400 dark:hover:text-rose-400 hover:bg-rose-50 dark:hover:bg-rose-500/5 transition-all duration-300 active:scale-95"
|
||
>
|
||
<ArrowRightOnRectangleIcon
|
||
className="h-5 w-5 shrink-0 text-slate-400 group-hover:text-rose-500 transition-colors duration-300"
|
||
aria-hidden="true"
|
||
/>
|
||
Güvenli Çıkış
|
||
</button>
|
||
</form>
|
||
</li>
|
||
</ul>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
</>
|
||
)
|
||
}
|