109 lines
3.9 KiB
JavaScript
109 lines
3.9 KiB
JavaScript
import React, { useState } from 'react'
|
|
import { Link, usePage } from '@inertiajs/react'
|
|
|
|
const navItems = [
|
|
{ label: 'Overview', href: '/studio', icon: 'fa-solid fa-chart-line' },
|
|
{ label: 'Artworks', href: '/studio/artworks', icon: 'fa-solid fa-images' },
|
|
{ label: 'Cards', href: '/studio/cards', icon: 'fa-solid fa-rectangle-history-circle-user' },
|
|
{ label: 'Drafts', href: '/studio/artworks/drafts', icon: 'fa-solid fa-file-pen' },
|
|
{ label: 'Archived', href: '/studio/artworks/archived', icon: 'fa-solid fa-box-archive' },
|
|
{ label: 'Analytics', href: '/studio/analytics', icon: 'fa-solid fa-chart-pie' },
|
|
]
|
|
|
|
function NavLink({ item, active }) {
|
|
return (
|
|
<Link
|
|
href={item.href}
|
|
className={`flex items-center gap-3 px-4 py-2.5 rounded-xl text-sm font-medium transition-all duration-200 ${
|
|
active
|
|
? 'bg-accent/20 text-accent shadow-sm shadow-accent/10'
|
|
: 'text-slate-400 hover:text-white hover:bg-white/5'
|
|
}`}
|
|
>
|
|
<i className={`${item.icon} w-5 text-center text-base`} />
|
|
<span>{item.label}</span>
|
|
</Link>
|
|
)
|
|
}
|
|
|
|
export default function StudioLayout({ children, title }) {
|
|
const { url, props } = usePage()
|
|
const user = props.auth?.user
|
|
const [mobileOpen, setMobileOpen] = useState(false)
|
|
|
|
const isActive = (href) => {
|
|
if (href === '/studio') return url === '/studio'
|
|
return url.startsWith(href)
|
|
}
|
|
|
|
return (
|
|
<div className="min-h-screen bg-nova-900">
|
|
{/* Mobile top bar */}
|
|
<div className="lg:hidden flex items-center justify-between px-4 py-3 border-b border-white/10 bg-nova-900/80 backdrop-blur-xl sticky top-16 z-30">
|
|
<h1 className="text-lg font-bold text-white">Studio</h1>
|
|
<button
|
|
onClick={() => setMobileOpen(!mobileOpen)}
|
|
className="text-slate-400 hover:text-white p-2"
|
|
aria-label="Toggle navigation"
|
|
>
|
|
<i className={`fa-solid ${mobileOpen ? 'fa-xmark' : 'fa-bars'} text-xl`} />
|
|
</button>
|
|
</div>
|
|
|
|
{/* Mobile nav overlay */}
|
|
{mobileOpen && (
|
|
<div className="lg:hidden fixed inset-0 z-40 bg-black/60 backdrop-blur-sm" onClick={() => setMobileOpen(false)}>
|
|
<nav
|
|
className="absolute left-0 top-0 bottom-0 w-72 bg-nova-900 border-r border-white/10 p-4 pt-20 space-y-1"
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
<StudioSidebarContent isActive={isActive} onNavigate={() => setMobileOpen(false)} />
|
|
</nav>
|
|
</div>
|
|
)}
|
|
|
|
<div className="flex">
|
|
{/* Desktop sidebar */}
|
|
<aside className="hidden lg:flex flex-col w-64 min-h-[calc(100vh-4rem)] border-r border-white/10 bg-nova-900/60 backdrop-blur-xl p-4 pt-6 sticky top-16 self-start">
|
|
<StudioSidebarContent isActive={isActive} />
|
|
</aside>
|
|
|
|
{/* Main content */}
|
|
<main className="flex-1 min-w-0 px-4 lg:px-8 pt-4 pb-8">
|
|
{title && (
|
|
<h1 className="text-2xl font-bold text-white mb-4">{title}</h1>
|
|
)}
|
|
{children}
|
|
</main>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function StudioSidebarContent({ isActive, onNavigate }) {
|
|
return (
|
|
<>
|
|
<div className="mb-6">
|
|
<h2 className="text-xs font-semibold uppercase tracking-wider text-slate-500 px-4 mb-2">Creator Studio</h2>
|
|
</div>
|
|
|
|
<nav className="space-y-1 flex-1" onClick={onNavigate}>
|
|
{navItems.map((item) => (
|
|
<NavLink key={item.href} item={item} active={isActive(item.href)} />
|
|
))}
|
|
</nav>
|
|
|
|
<div className="mt-auto pt-6">
|
|
<Link
|
|
href="/upload"
|
|
className="flex items-center justify-center gap-2 w-full px-4 py-3 rounded-xl bg-sky-600 hover:bg-sky-500 text-white font-semibold text-sm transition-all duration-200 shadow-lg"
|
|
onClick={onNavigate}
|
|
>
|
|
<i className="fa-solid fa-cloud-arrow-up" />
|
|
Upload
|
|
</Link>
|
|
</div>
|
|
</>
|
|
)
|
|
}
|