"use client"; import { useState, useEffect, useMemo } from "react"; import { PanelLeft, MessageSquare, FolderOpen, Table2, Library, User, ChevronsUpDown, ChevronDown, } from "lucide-react"; import { useAuth } from "@/contexts/AuthContext"; import { useUserProfile } from "@/contexts/UserProfileContext"; import { useChatHistoryContext } from "@/app/contexts/ChatHistoryContext"; import { useRouter, usePathname } from "next/navigation"; import Link from "next/link"; import { MikeIcon } from "@/components/chat/mike-icon"; import { SidebarChatItem } from "@/app/components/shared/SidebarChatItem"; import { listProjects } from "@/app/lib/mikeApi"; import type { Project } from "@/app/components/shared/types"; import { cn } from "@/lib/utils"; const NAV_ITEMS = [ { href: "/assistant", label: "Assistant", icon: MessageSquare }, { href: "/projects", label: "Projects", icon: FolderOpen }, { href: "/tabular-reviews", label: "Tabular Review", icon: Table2 }, { href: "/workflows", label: "Workflows", icon: Library }, ]; interface AppSidebarProps { isOpen: boolean; onToggle: () => void; } export function AppSidebar({ isOpen, onToggle }: AppSidebarProps) { const { user } = useAuth(); const { profile } = useUserProfile(); const { chats, hasMoreChats, loadMoreChats, setCurrentChatId } = useChatHistoryContext(); const router = useRouter(); const pathname = usePathname(); const routeChatId = useMemo(() => { if (pathname.startsWith("/assistant/chat/")) { return pathname.split("/").pop() ?? null; } const projectChatMatch = pathname.match( /^\/projects\/[^/]+\/assistant\/chat\/([^/]+)/, ); return projectChatMatch?.[1] ?? null; }, [pathname]); const [shouldAnimate, setShouldAnimate] = useState(false); const [isDropdownOpen, setIsDropdownOpen] = useState(false); const [projectsCollapsed, setProjectsCollapsed] = useState(false); const [historyCollapsed, setHistoryCollapsed] = useState(false); const [projectNames, setProjectNames] = useState>( {}, ); const [recentProjects, setRecentProjects] = useState( null, ); useEffect(() => { if (!user) return; listProjects() .then((projects) => { const map: Record = {}; for (const p of projects) map[p.id] = p.name; setProjectNames(map); setRecentProjects( [...projects] .sort( (a, b) => Date.parse(b.updated_at || b.created_at) - Date.parse(a.updated_at || a.created_at), ) .slice(0, 5), ); }) .catch(() => { setProjectNames({}); setRecentProjects([]); }); }, [user]); useEffect(() => { if (!isOpen) setShouldAnimate(true); }, [isOpen]); useEffect(() => { const handleClickOutside = () => setIsDropdownOpen(false); if (isDropdownOpen) { document.addEventListener("click", handleClickOutside); return () => document.removeEventListener("click", handleClickOutside); } }, [isDropdownOpen]); useEffect(() => { setCurrentChatId(routeChatId); }, [routeChatId, setCurrentChatId]); const getUserInitials = (email: string) => { if (profile?.displayName) return profile.displayName.charAt(0).toUpperCase(); return email.charAt(0).toUpperCase(); }; const getDisplayName = () => { if (!profile) return ""; return profile.displayName || user?.email?.split("@")[0] || ""; }; const getUserTier = () => { if (!profile) return ""; return profile.tier || "Free"; }; if (!user) return null; return (
{/* Toggle + Logo */}
{isOpen && (
Mike
)}
{/* Nav items */} {NAV_ITEMS.map(({ href, label, icon: Icon }) => { const isActive = href === "/assistant" ? pathname === href : href === "/projects" ? pathname === href : pathname === href || pathname.startsWith(href + "/"); return (
); })} {isOpen && (
{/* Recent Projects */}
{!projectsCollapsed && ( <> {!recentProjects ? (
{[50, 65, 45].map((w, i) => (
))}
) : recentProjects.length === 0 ? (
No projects yet
) : (
{recentProjects.map((project) => { const isActive = pathname === `/projects/${project.id}` || pathname.startsWith( `/projects/${project.id}/`, ); return ( ); })}
)} )}
{/* Assistant History */}
{!chats ? (
{[40, 60, 50, 70, 45].map((w, i) => (
))}
) : chats.length === 0 ? (
No chats yet
) : ( <>
{chats.map((chat) => ( { setCurrentChatId(chat.id); router.push( chat.project_id ? `/projects/${chat.project_id}/assistant/chat/${chat.id}` : `/assistant/chat/${chat.id}`, ); }} /> ))}
{hasMoreChats && (
)} )}
)} {/* User Profile */}
{user && (
{isDropdownOpen && (
)}
)}
); }