177 lines
9.3 KiB
TypeScript
177 lines
9.3 KiB
TypeScript
'use client'
|
|
|
|
import { useState } from "react"
|
|
import { usePathname, useRouter } from 'next/navigation'
|
|
import SidebarFooter from "./SidebarFooter"
|
|
import Button from "./Button"
|
|
|
|
export default function Sidebar({ children }: { children?: React.ReactNode }) {
|
|
const router = useRouter()
|
|
const pathname = usePathname()
|
|
|
|
const [isOpen, setIsOpen] = useState(false)
|
|
const [openSubmenu, setOpenSubmenu] = useState<'teams' | 'players' | null>(null)
|
|
|
|
const toggleSidebar = () => setIsOpen(prev => !prev)
|
|
|
|
const handleSubmenuToggle = (menu: 'teams' | 'players') => {
|
|
setOpenSubmenu(prev => (prev === menu ? null : menu))
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<Button
|
|
onClick={toggleSidebar}
|
|
className="absolute items-center p-2 mt-2 ms-3 text-sm text-gray-500 rounded-lg sm:hidden focus:bg-gray-100 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:bg-neutral-700 dark:hover:text-neutral-200 dark:focus:text-neutral-200"
|
|
>
|
|
<span className="sr-only">Open sidebar</span>
|
|
<svg className="w-6 h-6" fill="currentColor" viewBox="0 0 20 20">
|
|
<path clipRule="evenodd" fillRule="evenodd" d="M2 4.75A.75.75 0 012.75 4h14.5a.75.75 0 010 1.5H2.75A.75.75 0 012 4.75zm0 10.5a.75.75 0 01.75-.75h7.5a.75.75 0 010 1.5h-7.5a.75.75 0 01-.75-.75zM2 10a.75.75 0 01.75-.75h14.5a.75.75 0 010 1.5H2.75A.75.75 0 012 10z" />
|
|
</svg>
|
|
</Button>
|
|
|
|
<div className="flex">
|
|
<aside className={`fixed top-0 left-0 z-40 h-screen w-64 bg-white dark:bg-neutral-800 border-e border-gray-200 dark:border-neutral-700 transition-transform sm:translate-x-0 ${isOpen ? 'translate-x-0' : '-translate-x-full'}`} aria-label="Sidebar">
|
|
<div className="flex flex-col h-full">
|
|
<header className="p-4 flex justify-between items-center">
|
|
<a href="#" className="font-semibold text-xl text-black dark:text-white">Iron:e</a>
|
|
<button onClick={toggleSidebar} className="lg:hidden">
|
|
<svg className="size-4" viewBox="0 0 24 24" stroke="currentColor" fill="none">
|
|
<path d="M18 6L6 18M6 6l12 12" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
|
|
</svg>
|
|
</button>
|
|
</header>
|
|
|
|
<nav className="flex-1 overflow-y-auto px-2">
|
|
<ul className="space-y-1">
|
|
|
|
{/* Dashboard */}
|
|
<li>
|
|
<Button
|
|
onClick={() => router.push('/dashboard')}
|
|
size="sm"
|
|
variant="link"
|
|
className={`w-full flex items-center gap-x-3.5 py-2 px-2.5 text-sm rounded-lg transition-colors ${
|
|
pathname === '/dashboard'
|
|
? 'bg-gray-100 dark:bg-neutral-700 text-gray-900 dark:text-white'
|
|
: 'text-gray-800 hover:bg-gray-100 dark:text-neutral-300 dark:hover:bg-neutral-700'
|
|
}`}
|
|
>
|
|
<svg className="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><path d="M9 22V12h6v10"/></svg>
|
|
Dashboard
|
|
</Button>
|
|
</li>
|
|
|
|
{/* Teams */}
|
|
<li>
|
|
<Button
|
|
onClick={() => handleSubmenuToggle('teams')}
|
|
size="sm"
|
|
variant="link"
|
|
className="w-full flex items-center justify-between gap-x-3.5 py-2 px-2.5 text-sm text-gray-800 rounded-lg hover:bg-gray-100 dark:text-neutral-200 dark:hover:bg-neutral-700"
|
|
>
|
|
<span className="flex items-center gap-x-3.5">
|
|
<svg className="size-5" viewBox="0 0 640 640" fill="currentColor" stroke="currentColor" strokeWidth="2">
|
|
<path d="M320 64C355.3 64 384 92.7 384 128C384 163.3 355.3 192 320 192C284.7 192 256 163.3 256 128C256 92.7 284.7 64 320 64zM416 376C416 401 403.3 423 384 435.9L384 528C384 554.5 362.5 576 336 576L304 576C277.5 576 256 554.5 256 528L256 435.9C236.7 423 224 401 224 376L224 336C224 283 267 240 320 240C373 240 416 283 416 336L416 376zM160 96C190.9 96 216 121.1 216 152C216 182.9 190.9 208 160 208C129.1 208 104 182.9 104 152C104 121.1 129.1 96 160 96zM176 336L176 368C176 400.5 188.1 430.1 208 452.7L208 528C208 529.2 208 530.5 208.1 531.7C199.6 539.3 188.4 544 176 544L144 544C117.5 544 96 522.5 96 496L96 439.4C76.9 428.4 64 407.7 64 384L64 352C64 299 107 256 160 256C172.7 256 184.8 258.5 195.9 262.9C183.3 284.3 176 309.3 176 336zM432 528L432 452.7C451.9 430.2 464 400.5 464 368L464 336C464 309.3 456.7 284.4 444.1 262.9C455.2 258.4 467.3 256 480 256C533 256 576 299 576 352L576 384C576 407.7 563.1 428.4 544 439.4L544 496C544 522.5 522.5 544 496 544L464 544C451.7 544 440.4 539.4 431.9 531.7C431.9 530.5 432 529.2 432 528zM480 96C510.9 96 536 121.1 536 152C536 182.9 510.9 208 480 208C449.1 208 424 182.9 424 152C424 121.1 449.1 96 480 96z" />
|
|
</svg>
|
|
Teams
|
|
</span>
|
|
<svg
|
|
className={`size-4 transition-transform ${openSubmenu === 'teams' ? 'rotate-180' : ''}`}
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
>
|
|
<path d="M6 9l6 6 6-6" />
|
|
</svg>
|
|
</Button>
|
|
|
|
{openSubmenu === 'teams' && (
|
|
<ul className="pl-6 space-y-1 mt-1">
|
|
<li>
|
|
<Button onClick={() => router.push('/teams')} size="sm" variant="link" className="w-full text-start">
|
|
Übersicht
|
|
</Button>
|
|
</li>
|
|
<li>
|
|
<Button onClick={() => router.push('/teams/manage')} size="sm" variant="link" className="w-full text-start">
|
|
Teamverwaltung
|
|
</Button>
|
|
</li>
|
|
</ul>
|
|
)}
|
|
</li>
|
|
|
|
{/* Spieler */}
|
|
<li>
|
|
<Button
|
|
onClick={() => handleSubmenuToggle('players')}
|
|
size="sm"
|
|
variant="link"
|
|
className="w-full flex items-center justify-between gap-x-3.5 py-2 px-2.5 text-sm text-gray-800 rounded-lg hover:bg-gray-100 dark:text-neutral-200 dark:hover:bg-neutral-700"
|
|
>
|
|
<span className="flex items-center gap-x-3.5">
|
|
<svg className="size-4" fill="currentColor" viewBox="0 0 24 24">
|
|
<path fillRule="evenodd" d="M12 4a4 4 0 1 0 0 8 4 4 0 0 0 0-8Zm-2 9a4 4 0 0 0-4 4v1a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2v-1a4 4 0 0 0-4-4h-4Z" clipRule="evenodd"/>
|
|
</svg>
|
|
Spieler
|
|
</span>
|
|
<svg className={`size-4 transition-transform ${openSubmenu === 'players' ? 'rotate-180' : ''}`} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M6 9l6 6 6-6" /></svg>
|
|
</Button>
|
|
|
|
{openSubmenu === 'players' && (
|
|
<ul className="pl-6 space-y-1 mt-1">
|
|
<li>
|
|
<Button onClick={() => router.push('/players')} size="sm" variant="link" className="w-full text-start">
|
|
Übersicht
|
|
</Button>
|
|
</li>
|
|
<li>
|
|
<Button onClick={() => router.push('/players/stats')} size="sm" variant="link" className="w-full text-start">
|
|
Statistiken
|
|
</Button>
|
|
</li>
|
|
</ul>
|
|
)}
|
|
</li>
|
|
|
|
{/* Spielplan */}
|
|
<li>
|
|
<Button
|
|
onClick={() => router.push('/schedule')}
|
|
size="sm"
|
|
variant="link"
|
|
className={`w-full flex items-center gap-x-3.5 py-2 px-2.5 text-sm rounded-lg transition-colors ${
|
|
pathname === '/schedule'
|
|
? 'bg-gray-100 dark:bg-neutral-700 text-gray-900 dark:text-white'
|
|
: 'text-gray-800 hover:bg-gray-100 dark:text-neutral-300 dark:hover:bg-neutral-700'
|
|
}`}
|
|
>
|
|
<svg className="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
|
<rect width="18" height="18" x="3" y="4" rx="2" ry="2"/>
|
|
<line x1="16" x2="16" y1="2" y2="6"/>
|
|
<line x1="8" x2="8" y1="2" y2="6"/>
|
|
<line x1="3" x2="21" y1="10" y2="10"/>
|
|
<path d="M8 14h.01M12 14h.01M16 14h.01M8 18h.01M12 18h.01M16 18h.01"/>
|
|
</svg>
|
|
Spielplan
|
|
</Button>
|
|
</li>
|
|
</ul>
|
|
</nav>
|
|
|
|
<footer className="mt-auto border-t border-gray-200 dark:border-neutral-700">
|
|
<SidebarFooter />
|
|
</footer>
|
|
</div>
|
|
</aside>
|
|
|
|
<main className="sm:ml-64 flex-1 p-6 bg-white dark:bg-black overflow-y-auto">
|
|
{children}
|
|
</main>
|
|
</div>
|
|
</>
|
|
)
|
|
}
|