SurfSense/surfsense_web/components/sidebar/app-sidebar.tsx

263 lines
5.2 KiB
TypeScript
Raw Normal View History

2025-07-27 10:05:37 -07:00
"use client";
2025-04-07 23:47:06 -07:00
import {
2025-07-27 10:41:15 -07:00
AlertCircle,
2025-07-27 10:05:37 -07:00
BookOpen,
Cable,
2025-07-27 10:41:15 -07:00
ExternalLink,
2025-07-27 10:05:37 -07:00
FileStack,
2025-07-27 10:41:15 -07:00
FileText,
Info,
type LucideIcon,
2025-07-27 10:05:37 -07:00
MessageCircleMore,
2025-07-27 10:41:15 -07:00
Podcast,
2025-07-27 10:05:37 -07:00
Settings2,
SquareLibrary,
SquareTerminal,
Trash2,
2025-07-27 10:41:15 -07:00
Undo2,
2025-07-27 10:05:37 -07:00
} from "lucide-react";
2025-11-03 16:00:58 -08:00
import Image from "next/image";
import Link from "next/link";
2025-08-02 21:20:36 -07:00
import { memo, useMemo } from "react";
2025-04-07 23:47:06 -07:00
import { Logo } from "@/components/Logo";
2025-07-27 10:05:37 -07:00
import { NavMain } from "@/components/sidebar/nav-main";
import { NavProjects } from "@/components/sidebar/nav-projects";
import { NavSecondary } from "@/components/sidebar/nav-secondary";
import { PageUsageDisplay } from "@/components/sidebar/page-usage-display";
2025-04-07 23:47:06 -07:00
import {
2025-07-27 10:05:37 -07:00
Sidebar,
SidebarContent,
2025-08-02 21:20:36 -07:00
SidebarFooter,
2025-07-27 10:05:37 -07:00
SidebarHeader,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
} from "@/components/ui/sidebar";
2025-04-07 23:47:06 -07:00
// Map of icon names to their components
export const iconMap: Record<string, LucideIcon> = {
2025-07-27 10:05:37 -07:00
BookOpen,
Cable,
FileStack,
Undo2,
MessageCircleMore,
Settings2,
SquareLibrary,
SquareTerminal,
AlertCircle,
Info,
ExternalLink,
Trash2,
Podcast,
FileText,
};
2025-04-07 23:47:06 -07:00
const defaultData = {
2025-07-27 10:05:37 -07:00
user: {
name: "Surf",
email: "m@example.com",
avatar: "/icon-128.png",
},
navMain: [
{
title: "Researcher",
url: "#",
icon: "SquareTerminal",
isActive: true,
items: [],
},
{
title: "Documents",
url: "#",
icon: "FileStack",
items: [
{
title: "Upload Documents",
url: "#",
},
{
title: "Manage Documents",
url: "#",
},
],
},
{
title: "Connectors",
url: "#",
icon: "Cable",
items: [
{
title: "Add Connector",
url: "#",
},
{
title: "Manage Connectors",
url: "#",
},
],
},
{
title: "Research Synthesizer's",
url: "#",
icon: "SquareLibrary",
items: [
{
title: "Podcast Creator",
url: "#",
},
{
title: "Presentation Creator",
url: "#",
},
],
},
],
navSecondary: [
{
title: "SEARCH SPACE",
url: "#",
icon: "LifeBuoy",
},
],
RecentChats: [
{
name: "Design Engineering",
url: "#",
icon: "MessageCircleMore",
id: 1001,
},
{
name: "Sales & Marketing",
url: "#",
icon: "MessageCircleMore",
id: 1002,
},
{
name: "Travel",
url: "#",
icon: "MessageCircleMore",
id: 1003,
},
],
};
2025-04-07 23:47:06 -07:00
interface AppSidebarProps extends React.ComponentProps<typeof Sidebar> {
2025-07-27 10:05:37 -07:00
navMain?: {
title: string;
url: string;
icon: string;
isActive?: boolean;
items?: {
title: string;
url: string;
}[];
}[];
navSecondary?: {
title: string;
url: string;
2025-08-02 21:20:36 -07:00
icon: string;
2025-07-27 10:05:37 -07:00
}[];
RecentChats?: {
name: string;
url: string;
2025-08-02 21:20:36 -07:00
icon: string;
2025-07-27 10:05:37 -07:00
id?: number;
search_space_id?: number;
actions?: {
name: string;
icon: string;
onClick: () => void;
}[];
}[];
2025-08-02 21:20:36 -07:00
user?: {
name: string;
email: string;
avatar: string;
};
pageUsage?: {
pagesUsed: number;
pagesLimit: number;
};
2025-04-07 23:47:06 -07:00
}
2025-08-02 21:20:36 -07:00
// Memoized AppSidebar component for better performance
export const AppSidebar = memo(function AppSidebar({
2025-07-27 10:05:37 -07:00
navMain = defaultData.navMain,
navSecondary = defaultData.navSecondary,
RecentChats = defaultData.RecentChats,
pageUsage,
2025-07-27 10:05:37 -07:00
...props
2025-04-07 23:47:06 -07:00
}: AppSidebarProps) {
2025-07-27 10:05:37 -07:00
// Process navMain to resolve icon names to components
2025-07-27 10:41:15 -07:00
const processedNavMain = useMemo(() => {
2025-07-27 10:05:37 -07:00
return navMain.map((item) => ({
...item,
2025-08-02 21:20:36 -07:00
icon: iconMap[item.icon] || SquareTerminal,
2025-07-27 10:05:37 -07:00
}));
}, [navMain]);
2025-04-07 23:47:06 -07:00
2025-07-27 10:05:37 -07:00
// Process navSecondary to resolve icon names to components
2025-07-27 10:41:15 -07:00
const processedNavSecondary = useMemo(() => {
2025-07-27 10:05:37 -07:00
return navSecondary.map((item) => ({
...item,
2025-08-02 21:20:36 -07:00
icon: iconMap[item.icon] || Undo2,
2025-07-27 10:05:37 -07:00
}));
}, [navSecondary]);
2025-04-07 23:47:06 -07:00
2025-07-27 10:05:37 -07:00
// Process RecentChats to resolve icon names to components
2025-07-27 10:41:15 -07:00
const processedRecentChats = useMemo(() => {
2025-07-27 10:05:37 -07:00
return (
RecentChats?.map((item) => ({
...item,
2025-08-02 21:20:36 -07:00
icon: iconMap[item.icon] || MessageCircleMore,
2025-07-27 10:05:37 -07:00
})) || []
);
}, [RecentChats]);
2025-04-07 23:47:06 -07:00
2025-07-27 10:05:37 -07:00
return (
2025-08-02 21:20:36 -07:00
<Sidebar variant="inset" collapsible="icon" aria-label="Main navigation" {...props}>
2025-07-27 10:05:37 -07:00
<SidebarHeader>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton asChild size="lg">
2025-11-03 16:00:58 -08:00
<Link href="/" className="flex items-center gap-2 w-full">
<div className="bg-sidebar-primary text-sidebar-primary-foreground flex aspect-square size-8 items-center justify-center rounded-lg">
<Image
src="/icon-128.png"
alt="SurfSense logo"
width={32}
height={32}
className="rounded-lg"
/>
</div>
<div className="grid flex-1 text-left text-sm leading-tight">
<span className="truncate font-medium">SurfSense</span>
<span className="truncate text-xs">beta v0.0.8</span>
</div>
</Link>
2025-07-27 10:05:37 -07:00
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarHeader>
2025-08-02 21:20:36 -07:00
<SidebarContent className="space-y-6">
2025-07-27 10:05:37 -07:00
<NavMain items={processedNavMain} />
2025-08-02 21:20:36 -07:00
{processedRecentChats.length > 0 && (
<div className="space-y-2">
<NavProjects chats={processedRecentChats} />
</div>
)}
2025-07-27 10:05:37 -07:00
</SidebarContent>
2025-08-02 21:20:36 -07:00
<SidebarFooter>
{pageUsage && (
<PageUsageDisplay pagesUsed={pageUsage.pagesUsed} pagesLimit={pageUsage.pagesLimit} />
)}
2025-08-02 21:20:36 -07:00
<NavSecondary items={processedNavSecondary} className="mt-auto" />
</SidebarFooter>
2025-07-27 10:05:37 -07:00
</Sidebar>
);
2025-08-02 21:20:36 -07:00
});