'use client'; import { useState } from 'react'; import { ChevronRight, Folder, FolderOpen, FolderTree, Inbox, Lock } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from '@/components/ui/sheet'; import { cn } from '@/lib/utils'; import { useDocumentFolders, type FolderNode } from '@/hooks/use-document-folders'; interface FolderTreeSidebarProps { /** Currently-selected folder id, or `null` for root, or `undefined` * for "All documents" (no folder filter). */ selectedFolderId: string | null | undefined; onSelect: (folderId: string | null | undefined) => void; /** Slot below the tree for a "New folder" affordance from the parent. */ footer?: React.ReactNode; } /** * Collapsed-by-default tree. Each row shows a chevron that toggles its * children; clicking the row label selects the folder. The "All * documents" + "Root" pseudo-rows at the top let reps filter to the * full set or to docs without a folder. * * Designed for unlimited depth — only the top level renders by default * so deep trees don't blow out the page; reps drill in by expanding. * * On mobile (< sm) the sidebar collapses into a Sheet drawer triggered by * a "Show folders" button so the main listing isn't pushed below a * full-width folder stack. */ export function FolderTreeSidebar({ selectedFolderId, onSelect, footer }: FolderTreeSidebarProps) { const [mobileOpen, setMobileOpen] = useState(false); const handleMobileSelect = (id: string | null | undefined) => { onSelect(id); setMobileOpen(false); }; return ( <> {/* Mobile-only trigger that opens the drawer; hidden at sm+. */}
Folders
{/* Desktop sidebar: hidden on mobile (the Sheet trigger replaces it). */} ); } function TreeBody({ selectedFolderId, onSelect, footer, }: { selectedFolderId: string | null | undefined; onSelect: (folderId: string | null | undefined) => void; footer?: React.ReactNode; }) { const { data: tree = [], isLoading, isError } = useDocumentFolders(); return ( <>
onSelect(undefined)} /> onSelect(null)} />
{isLoading ? (

Loading...

) : isError ? (

Failed to load folders.

) : tree.length === 0 ? (

No folders yet.

) : ( tree.map((node) => ( )) )}
{footer ?
{footer}
: null} ); } function PseudoRow({ label, icon: Icon, active, onClick, }: { label: string; icon: typeof Inbox; active: boolean; onClick: () => void; }) { return ( ); } function FolderRow({ node, depth, selectedFolderId, onSelect, }: { node: FolderNode; depth: number; selectedFolderId: string | null | undefined; onSelect: (folderId: string | null) => void; }) { const [open, setOpen] = useState(false); const hasChildren = node.children.length > 0; const isActive = selectedFolderId === node.id; return ( <>
{open ? node.children.map((child) => ( )) : null} ); }