2026-01-08 19:10:40 +02:00
|
|
|
"use client";
|
|
|
|
|
|
|
|
|
|
import { useState } from "react";
|
|
|
|
|
import { TooltipProvider } from "@/components/ui/tooltip";
|
|
|
|
|
import { useIsMobile } from "@/hooks/use-mobile";
|
|
|
|
|
import { cn } from "@/lib/utils";
|
|
|
|
|
import { useSidebarState } from "../../hooks";
|
2026-01-13 00:17:12 -08:00
|
|
|
import type { ChatItem, NavItem, PageUsage, SearchSpace, User } from "../../types/layout.types";
|
2026-01-08 19:10:40 +02:00
|
|
|
import { Header } from "../header";
|
|
|
|
|
import { IconRail } from "../icon-rail";
|
|
|
|
|
import { MobileSidebar, MobileSidebarTrigger, Sidebar } from "../sidebar";
|
|
|
|
|
|
|
|
|
|
interface LayoutShellProps {
|
2026-01-12 15:47:56 +02:00
|
|
|
searchSpaces: SearchSpace[];
|
|
|
|
|
activeSearchSpaceId: number | null;
|
|
|
|
|
onSearchSpaceSelect: (id: number) => void;
|
2026-01-13 01:45:58 -08:00
|
|
|
onSearchSpaceDelete?: (searchSpace: SearchSpace) => void;
|
|
|
|
|
onSearchSpaceSettings?: (searchSpace: SearchSpace) => void;
|
2026-01-12 15:47:56 +02:00
|
|
|
onAddSearchSpace: () => void;
|
|
|
|
|
searchSpace: SearchSpace | null;
|
2026-01-08 19:10:40 +02:00
|
|
|
navItems: NavItem[];
|
|
|
|
|
onNavItemClick?: (item: NavItem) => void;
|
|
|
|
|
chats: ChatItem[];
|
2026-01-13 00:17:12 -08:00
|
|
|
sharedChats?: ChatItem[];
|
2026-01-08 19:10:40 +02:00
|
|
|
activeChatId?: number | null;
|
|
|
|
|
onNewChat: () => void;
|
|
|
|
|
onChatSelect: (chat: ChatItem) => void;
|
|
|
|
|
onChatDelete?: (chat: ChatItem) => void;
|
2026-01-13 00:17:12 -08:00
|
|
|
onViewAllSharedChats?: () => void;
|
|
|
|
|
onViewAllPrivateChats?: () => void;
|
2026-01-08 19:10:40 +02:00
|
|
|
user: User;
|
|
|
|
|
onSettings?: () => void;
|
2026-01-12 15:47:56 +02:00
|
|
|
onManageMembers?: () => void;
|
2026-01-12 17:06:05 +02:00
|
|
|
onUserSettings?: () => void;
|
2026-01-08 19:10:40 +02:00
|
|
|
onLogout?: () => void;
|
|
|
|
|
pageUsage?: PageUsage;
|
|
|
|
|
breadcrumb?: React.ReactNode;
|
|
|
|
|
theme?: string;
|
2026-01-20 16:04:56 +05:30
|
|
|
setTheme?: (theme: "light" | "dark" | "system") => void;
|
2026-01-08 19:10:40 +02:00
|
|
|
defaultCollapsed?: boolean;
|
|
|
|
|
isChatPage?: boolean;
|
|
|
|
|
children: React.ReactNode;
|
|
|
|
|
className?: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function LayoutShell({
|
2026-01-12 15:47:56 +02:00
|
|
|
searchSpaces,
|
|
|
|
|
activeSearchSpaceId,
|
|
|
|
|
onSearchSpaceSelect,
|
2026-01-13 01:45:58 -08:00
|
|
|
onSearchSpaceDelete,
|
|
|
|
|
onSearchSpaceSettings,
|
2026-01-12 15:47:56 +02:00
|
|
|
onAddSearchSpace,
|
|
|
|
|
searchSpace,
|
2026-01-08 19:10:40 +02:00
|
|
|
navItems,
|
|
|
|
|
onNavItemClick,
|
|
|
|
|
chats,
|
2026-01-13 00:17:12 -08:00
|
|
|
sharedChats,
|
2026-01-08 19:10:40 +02:00
|
|
|
activeChatId,
|
|
|
|
|
onNewChat,
|
|
|
|
|
onChatSelect,
|
|
|
|
|
onChatDelete,
|
2026-01-13 00:17:12 -08:00
|
|
|
onViewAllSharedChats,
|
|
|
|
|
onViewAllPrivateChats,
|
2026-01-08 19:10:40 +02:00
|
|
|
user,
|
|
|
|
|
onSettings,
|
2026-01-12 15:47:56 +02:00
|
|
|
onManageMembers,
|
2026-01-12 17:06:05 +02:00
|
|
|
onUserSettings,
|
2026-01-08 19:10:40 +02:00
|
|
|
onLogout,
|
|
|
|
|
pageUsage,
|
|
|
|
|
breadcrumb,
|
|
|
|
|
theme,
|
2026-01-20 16:04:56 +05:30
|
|
|
setTheme,
|
2026-01-08 19:10:40 +02:00
|
|
|
defaultCollapsed = false,
|
|
|
|
|
isChatPage = false,
|
|
|
|
|
children,
|
|
|
|
|
className,
|
|
|
|
|
}: LayoutShellProps) {
|
|
|
|
|
const isMobile = useIsMobile();
|
|
|
|
|
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
|
|
|
|
const { isCollapsed, toggleCollapsed } = useSidebarState(defaultCollapsed);
|
|
|
|
|
|
|
|
|
|
// Mobile layout
|
|
|
|
|
if (isMobile) {
|
|
|
|
|
return (
|
|
|
|
|
<TooltipProvider delayDuration={0}>
|
|
|
|
|
<div className={cn("flex h-screen w-full flex-col bg-background", className)}>
|
|
|
|
|
<Header
|
|
|
|
|
breadcrumb={breadcrumb}
|
|
|
|
|
mobileMenuTrigger={<MobileSidebarTrigger onClick={() => setMobileMenuOpen(true)} />}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<MobileSidebar
|
|
|
|
|
isOpen={mobileMenuOpen}
|
|
|
|
|
onOpenChange={setMobileMenuOpen}
|
2026-01-12 15:47:56 +02:00
|
|
|
searchSpaces={searchSpaces}
|
|
|
|
|
activeSearchSpaceId={activeSearchSpaceId}
|
|
|
|
|
onSearchSpaceSelect={onSearchSpaceSelect}
|
2026-01-13 01:45:58 -08:00
|
|
|
onSearchSpaceDelete={onSearchSpaceDelete}
|
|
|
|
|
onSearchSpaceSettings={onSearchSpaceSettings}
|
2026-01-12 15:47:56 +02:00
|
|
|
onAddSearchSpace={onAddSearchSpace}
|
|
|
|
|
searchSpace={searchSpace}
|
2026-01-08 19:10:40 +02:00
|
|
|
navItems={navItems}
|
|
|
|
|
onNavItemClick={onNavItemClick}
|
|
|
|
|
chats={chats}
|
2026-01-13 00:17:12 -08:00
|
|
|
sharedChats={sharedChats}
|
2026-01-08 19:10:40 +02:00
|
|
|
activeChatId={activeChatId}
|
|
|
|
|
onNewChat={onNewChat}
|
|
|
|
|
onChatSelect={onChatSelect}
|
|
|
|
|
onChatDelete={onChatDelete}
|
2026-01-13 00:17:12 -08:00
|
|
|
onViewAllSharedChats={onViewAllSharedChats}
|
|
|
|
|
onViewAllPrivateChats={onViewAllPrivateChats}
|
2026-01-08 19:10:40 +02:00
|
|
|
user={user}
|
|
|
|
|
onSettings={onSettings}
|
2026-01-12 15:47:56 +02:00
|
|
|
onManageMembers={onManageMembers}
|
2026-01-12 17:06:05 +02:00
|
|
|
onUserSettings={onUserSettings}
|
2026-01-08 19:10:40 +02:00
|
|
|
onLogout={onLogout}
|
|
|
|
|
pageUsage={pageUsage}
|
2026-01-20 16:04:56 +05:30
|
|
|
theme={theme}
|
|
|
|
|
setTheme={setTheme}
|
2026-01-08 19:10:40 +02:00
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<main className={cn("flex-1", isChatPage ? "overflow-hidden" : "overflow-auto")}>
|
|
|
|
|
{children}
|
|
|
|
|
</main>
|
|
|
|
|
</div>
|
|
|
|
|
</TooltipProvider>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Desktop layout
|
|
|
|
|
return (
|
|
|
|
|
<TooltipProvider delayDuration={0}>
|
|
|
|
|
<div className={cn("flex h-screen w-full gap-2 p-2 overflow-hidden bg-muted/40", className)}>
|
|
|
|
|
<div className="hidden md:flex overflow-hidden">
|
|
|
|
|
<IconRail
|
2026-01-12 15:47:56 +02:00
|
|
|
searchSpaces={searchSpaces}
|
|
|
|
|
activeSearchSpaceId={activeSearchSpaceId}
|
|
|
|
|
onSearchSpaceSelect={onSearchSpaceSelect}
|
2026-01-13 01:45:58 -08:00
|
|
|
onSearchSpaceDelete={onSearchSpaceDelete}
|
|
|
|
|
onSearchSpaceSettings={onSearchSpaceSettings}
|
2026-01-12 15:47:56 +02:00
|
|
|
onAddSearchSpace={onAddSearchSpace}
|
2026-01-08 19:10:40 +02:00
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="flex flex-1 rounded-xl border bg-background overflow-hidden">
|
|
|
|
|
<Sidebar
|
2026-01-12 15:47:56 +02:00
|
|
|
searchSpace={searchSpace}
|
2026-01-08 19:10:40 +02:00
|
|
|
isCollapsed={isCollapsed}
|
|
|
|
|
onToggleCollapse={toggleCollapsed}
|
|
|
|
|
navItems={navItems}
|
|
|
|
|
onNavItemClick={onNavItemClick}
|
|
|
|
|
chats={chats}
|
2026-01-13 00:17:12 -08:00
|
|
|
sharedChats={sharedChats}
|
2026-01-08 19:10:40 +02:00
|
|
|
activeChatId={activeChatId}
|
|
|
|
|
onNewChat={onNewChat}
|
|
|
|
|
onChatSelect={onChatSelect}
|
|
|
|
|
onChatDelete={onChatDelete}
|
2026-01-13 00:17:12 -08:00
|
|
|
onViewAllSharedChats={onViewAllSharedChats}
|
|
|
|
|
onViewAllPrivateChats={onViewAllPrivateChats}
|
2026-01-08 19:10:40 +02:00
|
|
|
user={user}
|
|
|
|
|
onSettings={onSettings}
|
2026-01-12 15:47:56 +02:00
|
|
|
onManageMembers={onManageMembers}
|
2026-01-12 17:06:05 +02:00
|
|
|
onUserSettings={onUserSettings}
|
2026-01-08 19:10:40 +02:00
|
|
|
onLogout={onLogout}
|
|
|
|
|
pageUsage={pageUsage}
|
2026-01-20 16:04:56 +05:30
|
|
|
theme={theme}
|
|
|
|
|
setTheme={setTheme}
|
2026-01-08 19:10:40 +02:00
|
|
|
className="hidden md:flex border-r shrink-0"
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<main className="flex-1 flex flex-col min-w-0">
|
2026-01-20 20:47:31 +05:30
|
|
|
<Header breadcrumb={breadcrumb} />
|
2026-01-08 19:10:40 +02:00
|
|
|
|
|
|
|
|
<div className={cn("flex-1", isChatPage ? "overflow-hidden" : "overflow-auto")}>
|
|
|
|
|
{children}
|
|
|
|
|
</div>
|
|
|
|
|
</main>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</TooltipProvider>
|
|
|
|
|
);
|
|
|
|
|
}
|