78 lines
2.8 KiB
TypeScript
78 lines
2.8 KiB
TypeScript
import React from 'react';
|
|
import { Sidebar } from './components/Sidebar';
|
|
import { Topbar } from './components/Topbar';
|
|
import { usePage } from '@inertiajs/react';
|
|
|
|
interface Props {
|
|
children: React.ReactNode;
|
|
}
|
|
|
|
export default function AuthenticatedLayout({ children }: Props) {
|
|
const { system_settings } = usePage().props as any;
|
|
const primaryColor = system_settings?.primary_color;
|
|
|
|
const [theme, setTheme] = React.useState(() => {
|
|
if (typeof window !== 'undefined') {
|
|
return localStorage.getItem('theme') || 'light';
|
|
}
|
|
return 'light';
|
|
});
|
|
|
|
const [sidebarOpen, setSidebarOpen] = React.useState(false);
|
|
|
|
React.useEffect(() => {
|
|
if (theme === 'dark') {
|
|
document.documentElement.classList.add('dark');
|
|
} else {
|
|
document.documentElement.classList.remove('dark');
|
|
}
|
|
localStorage.setItem('theme', theme);
|
|
}, [theme]);
|
|
|
|
// Close sidebar on route change (mobile)
|
|
const url = usePage().url;
|
|
React.useEffect(() => {
|
|
setSidebarOpen(false);
|
|
}, [url]);
|
|
|
|
return (
|
|
<div className="flex h-screen overflow-hidden transition-colors duration-300 bg-[#E3EBE8] dark:bg-[#1A2120]"
|
|
style={primaryColor ? {
|
|
'--color-primary-500': primaryColor,
|
|
'--color-accent-gold': primaryColor
|
|
} as React.CSSProperties : {}}>
|
|
|
|
{/* Mobile overlay */}
|
|
<div
|
|
onClick={() => setSidebarOpen(false)}
|
|
className={`fixed inset-0 z-10 bg-black/40 backdrop-blur-sm lg:hidden transition-opacity duration-300
|
|
${sidebarOpen ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'}`}
|
|
/>
|
|
|
|
{/* Sidebar — desktop: always visible in flow; mobile: fixed slide-in */}
|
|
<div className="hidden lg:block shrink-0">
|
|
<Sidebar theme={theme} />
|
|
</div>
|
|
<div className={`fixed inset-y-0 left-0 z-20 lg:hidden transition-transform duration-300 ease-in-out
|
|
${sidebarOpen ? 'translate-x-0' : '-translate-x-full'}`}>
|
|
<Sidebar theme={theme} />
|
|
</div>
|
|
|
|
<div className="flex-1 flex flex-col min-w-0 h-full relative">
|
|
<Topbar
|
|
theme={theme}
|
|
onThemeToggle={() => setTheme(t => t === 'dark' ? 'light' : 'dark')}
|
|
onMenuToggle={() => setSidebarOpen(o => !o)}
|
|
sidebarOpen={sidebarOpen}
|
|
/>
|
|
|
|
<main className="flex-1 overflow-y-auto px-6 pt-6 pb-6 custom-scrollbar">
|
|
<div key={url} className="max-w-[1600px] mx-auto anim-page">
|
|
{children}
|
|
</div>
|
|
</main>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|