Files
app/frontend/src/routes/_layout.tsx
T

68 lines
2.3 KiB
TypeScript

import {
createFileRoute,
Outlet,
redirect,
useRouterState,
} from "@tanstack/react-router"
import { ControlTrigger } from "@/components/Chat/ChatPanel"
import { ConnectionNotice } from "@/components/Common/ConnectionNotice"
import ErrorComponent from "@/components/Common/ErrorComponent"
import { Footer } from "@/components/Common/Footer"
import { useFlowSocket } from "@/components/Flow/useFlowSocket"
import AppSidebar from "@/components/Sidebar/AppSidebar"
import {
SidebarInset,
SidebarProvider,
SidebarTrigger,
} from "@/components/ui/sidebar"
import { isLoggedIn } from "@/hooks/useAuth"
export const Route = createFileRoute("/_layout")({
component: Layout,
// Inside the shell rather than at the root, so a screen that throws leaves
// the sidebar standing and somebody can navigate away from it. The root's
// own boundary replaces the whole app, navigation included.
errorComponent: () => <ErrorComponent />,
beforeLoad: async () => {
if (!isLoggedIn()) {
throw redirect({
to: "/login",
})
}
},
})
function Layout() {
// Dashboards live in this shell and read live values, so the socket belongs
// here rather than only inside the editor.
useFlowSocket()
const home = useRouterState({ select: (s) => s.location.pathname === "/" })
return (
<SidebarProvider className="bg-card">
<AppSidebar />
<SidebarInset className="bg-card">
{/* Draws nothing itself, and nothing at all unless this page is
served through a portal: it raises the offline notification. */}
<ConnectionNotice />
{/* The sidebar carries its own collapse control; a phone has no
sidebar on screen to carry it. Home's chat sits opposite, where
the brain view has it on a wider screen. */}
<header className="sticky top-0 z-10 flex h-16 shrink-0 items-center gap-2 px-4 md:hidden">
<SidebarTrigger className="-ml-1 text-muted-foreground" />
{home ? <ControlTrigger className="-mr-1 ml-auto" /> : null}
</header>
<main className="flex-1 p-4 sm:p-6 md:p-8">
<div className="mx-auto max-w-7xl">
<Outlet />
</div>
</main>
<Footer />
</SidebarInset>
</SidebarProvider>
)
}
export default Layout