"use client"; import * as React from "react"; import { Check, CircleOff, FolderKanban, Plus } from "lucide-react"; import { useRouter } from "next/navigation"; import { useApp } from "@/components/app/store"; import { useApi } from "@/lib/client/api"; import { useIsMobile } from "@/lib/client/hooks"; import { ActionSheet, type ActionSheetItem } from "@/components/ui/sheet"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"; import { toast } from "@/components/ui/toast"; import { ProjectIcon } from "./project-icon"; import type { PublicProject } from "@/lib/client/types"; /** * Active-project quick switcher. Phone: iOS-style ActionSheet; desktop: dropdown. * Wrap any trigger (`children`); selecting sets `activeProjectId` (new chats inherit the project). */ export function ProjectSwitcher({ children, onNavigate }: { children: React.ReactElement; onNavigate?: () => void }) { const { activeProjectId, setActiveProjectId } = useApp(); const isMobile = useIsMobile(); const router = useRouter(); const [open, setOpen] = React.useState(false); const { data } = useApi<{ projects: PublicProject[] }>(open || !isMobile ? "/api/projects" : null); const projects = React.useMemo(() => (data?.projects ?? []).filter((p) => !p.archived), [data]); const choose = (id: string | null) => { setActiveProjectId(id); const p = id ? projects.find((x) => x.id === id) : null; toast.info(p ? `Active project: ${p.name}` : "No active project", p ? "New chats will use its instructions and models." : "New chats start without project context."); }; if (isMobile) { const items: (ActionSheetItem | "separator")[] = [ { key: "none", label: "No project", icon: , selected: !activeProjectId, onSelect: () => choose(null) }, ...projects.map((p) => ({ key: p.id, label: p.name, icon: , selected: p.id === activeProjectId, hint: p.conversationCount ? `${p.conversationCount}` : undefined, onSelect: () => choose(p.id) })), "separator", { key: "new", label: "New project", icon: , onSelect: () => { onNavigate?.(); router.push("/app/projects?new=1"); }, }, ]; return ( <> {React.cloneElement(children as React.ReactElement<{ onClick?: () => void }>, { onClick: () => setOpen(true) })} ); } return ( {children} Active project choose(null)}> No project {!activeProjectId ? : null} {projects.length ? : null} {projects.map((p) => ( choose(p.id)}> {p.name} {p.id === activeProjectId ? : null} ))} { onNavigate?.(); router.push("/app/projects?new=1"); }} > New project ); }