| "use client"; |
|
|
| import { Sidebar } from "./Sidebar"; |
| import { TopBar } from "./TopBar"; |
| import { Aurora } from "./Aurora"; |
| import { useChatStore } from "@/lib/chatStore"; |
| import { useBackendSync } from "@/lib/useBackendSync"; |
| import clsx from "clsx"; |
| import { usePathname } from "next/navigation"; |
| import { useEffect } from "react"; |
|
|
| export function AppShell({ children }: { children: React.ReactNode }) { |
| const sidebarOpen = useChatStore((s) => s.sidebarOpen); |
| const hydrated = useChatStore((s) => s.hydrated); |
| const pathname = usePathname(); |
| const conversations = useChatStore((s) => s.conversations); |
| const activeId = useChatStore((s) => s.activeId); |
| const newConversation = useChatStore((s) => s.newConversation); |
|
|
| |
| useBackendSync(); |
|
|
| |
| |
| |
| useEffect(() => { |
| if (pathname !== "/") return; |
| if (!hydrated) return; |
| const hasAny = Object.keys(conversations).length > 0; |
| const hasActive = activeId && conversations[activeId]; |
| if (!hasAny || !hasActive) newConversation(); |
| }, [pathname, hydrated, conversations, activeId, newConversation]); |
|
|
| return ( |
| <div className="relative h-screen flex flex-col overflow-hidden"> |
| {/* Atmospheric background — fixed, behind everything */} |
| <Aurora /> |
| |
| <TopBar /> |
| |
| <div className="relative z-10 flex-1 flex overflow-hidden min-h-0"> |
| <Sidebar /> |
| <main |
| className={clsx( |
| "flex-1 flex flex-col min-w-0 min-h-0 transition-[margin] duration-300 ease-atelier", |
| sidebarOpen ? "md:ml-0" : "md:ml-0" |
| )} |
| > |
| {children} |
| </main> |
| </div> |
| </div> |
| ); |
| } |
|
|