40 lines
1.2 KiB
TypeScript
40 lines
1.2 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import { Outlet } from 'react-router-dom';
|
|
import { Sidebar } from './Sidebar';
|
|
import { Header } from './Header';
|
|
import { ToastProvider } from '@/components/ui';
|
|
import { LoginPage } from '@/components/auth/LoginPage';
|
|
import { isLocalMode } from '@/lib/api';
|
|
|
|
export function AppShell() {
|
|
const [authed, setAuthed] = useState(() => isLocalMode());
|
|
const [navOpen, setNavOpen] = useState(false);
|
|
|
|
useEffect(() => {
|
|
const h = () => setAuthed(false);
|
|
window.addEventListener('fp-auth-required', h);
|
|
return () => window.removeEventListener('fp-auth-required', h);
|
|
}, []);
|
|
|
|
if (!authed) {
|
|
return <LoginPage onAuthed={() => setAuthed(true)} />;
|
|
}
|
|
|
|
return (
|
|
<ToastProvider>
|
|
<div className="flex h-full">
|
|
{navOpen && (
|
|
<div className="fixed inset-0 z-30 bg-black/45 lg:hidden" onClick={() => setNavOpen(false)} aria-hidden />
|
|
)}
|
|
<Sidebar open={navOpen} onClose={() => setNavOpen(false)} />
|
|
<div className="flex min-w-0 flex-1 flex-col">
|
|
<Header onMenu={() => setNavOpen(true)} />
|
|
<main className="min-h-0 flex-1 overflow-y-auto">
|
|
<Outlet />
|
|
</main>
|
|
</div>
|
|
</div>
|
|
</ToastProvider>
|
|
);
|
|
}
|