'use client' import { useState, useCallback } from 'react' import Link from 'next/link' import { usePathname, useRouter, useSearchParams } from 'next/navigation' import { cn } from '@/lib/utils' import { StickyNote, Plus, Tag, Folder, Briefcase, FileText, Zap, BarChart3, Globe, Sparkles, Book, Heart, Crown, Music, Building2, LucideIcon, Plane, ChevronDown, ChevronRight } from 'lucide-react' import { useNotebooks } from '@/context/notebooks-context' import { useNotebookDrag } from '@/context/notebook-drag-context' import { Button } from '@/components/ui/button' import { CreateNotebookDialog } from './create-notebook-dialog' import { NotebookActions } from './notebook-actions' import { DeleteNotebookDialog } from './delete-notebook-dialog' import { EditNotebookDialog } from './edit-notebook-dialog' import { NotebookSummaryDialog } from './notebook-summary-dialog' import { useLanguage } from '@/lib/i18n' import { useLabels } from '@/context/LabelContext' // Map icon names to lucide-react components const ICON_MAP: Record = { 'folder': Folder, 'briefcase': Briefcase, 'document': FileText, 'lightning': Zap, 'chart': BarChart3, 'globe': Globe, 'sparkle': Sparkles, 'book': Book, 'heart': Heart, 'crown': Crown, 'music': Music, 'building': Building2, 'flight_takeoff': Plane, } // Function to get icon component by name const getNotebookIcon = (iconName: string) => { const IconComponent = ICON_MAP[iconName] || Folder return IconComponent } export function NotebooksList() { const pathname = usePathname() const searchParams = useSearchParams() const router = useRouter() const { t } = useLanguage() const { notebooks, currentNotebook, deleteNotebook, moveNoteToNotebookOptimistic, isLoading } = useNotebooks() const { draggedNoteId, dragOverNotebookId, dragOver } = useNotebookDrag() const { labels } = useLabels() const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false) const [editingNotebook, setEditingNotebook] = useState(null) const [deletingNotebook, setDeletingNotebook] = useState(null) const [summaryNotebook, setSummaryNotebook] = useState(null) const [expandedNotebook, setExpandedNotebook] = useState(null) const currentNotebookId = searchParams.get('notebook') // Handle drop on a notebook const handleDrop = useCallback(async (e: React.DragEvent, notebookId: string | null) => { e.preventDefault() e.stopPropagation() const noteId = e.dataTransfer.getData('text/plain') if (noteId) { await moveNoteToNotebookOptimistic(noteId, notebookId) } dragOver(null) }, [moveNoteToNotebookOptimistic, dragOver]) // Handle drag over a notebook const handleDragOver = useCallback((e: React.DragEvent, notebookId: string | null) => { e.preventDefault() dragOver(notebookId) }, [dragOver]) // Handle drag leave const handleDragLeave = useCallback(() => { dragOver(null) }, [dragOver]) const handleSelectNotebook = (notebookId: string | null) => { const params = new URLSearchParams(searchParams) if (notebookId) { params.set('notebook', notebookId) } else { params.delete('notebook') } // Clear other filters params.delete('labels') params.delete('search') router.push(`/?${params.toString()}`) } const handleToggleExpand = (notebookId: string) => { setExpandedNotebook(expandedNotebook === notebookId ? null : notebookId) } const handleLabelFilter = (labelName: string, notebookId: string) => { const params = new URLSearchParams(searchParams) const currentLabels = params.get('labels')?.split(',').filter(Boolean) || [] if (currentLabels.includes(labelName)) { params.set('labels', currentLabels.filter((l: string) => l !== labelName).join(',')) } else { params.set('labels', [...currentLabels, labelName].join(',')) } params.set('notebook', notebookId) router.push(`/?${params.toString()}`) } if (isLoading) { return (
{t('common.loading')}
) } return ( <>
{/* Header with Add Button */}
{t('nav.notebooks') || 'NOTEBOOKS'}
{/* Notebooks Loop */} {notebooks.map((notebook: any) => { const isActive = currentNotebookId === notebook.id const isExpanded = expandedNotebook === notebook.id const isDragOver = dragOverNotebookId === notebook.id // Get icon component const NotebookIcon = getNotebookIcon(notebook.icon || 'folder') return (
{isActive ? ( // Active notebook with expanded labels - STYLE MATCH Sidebar
handleDrop(e, notebook.id)} onDragOver={(e) => handleDragOver(e, notebook.id)} onDragLeave={handleDragLeave} className={cn( "flex flex-col mr-2 rounded-r-full overflow-hidden transition-all", !notebook.color && "bg-primary/10 dark:bg-primary/20", isDragOver && "ring-2 ring-primary ring-dashed" )} style={notebook.color ? { backgroundColor: `${notebook.color}20` } : undefined} > {/* Header - allow pointer events for expand button */}
{notebook.name}
{/* Contextual Labels Tree */} {isExpanded && labels.length > 0 && (
{labels.map((label: any) => ( ))}
)}
) : ( // Inactive notebook
handleDrop(e, notebook.id)} onDragOver={(e) => handleDragOver(e, notebook.id)} onDragLeave={handleDragLeave} className={cn( "flex items-center group relative", isDragOver && "ring-2 ring-blue-500 ring-dashed rounded-r-full mr-2" )} >
{/* Expand button separate from main click */}
{/* Actions (visible on hover) */}
setEditingNotebook(notebook)} onDelete={() => setDeletingNotebook(notebook)} onSummary={() => setSummaryNotebook(notebook)} />
)}
) })}
{/* Create Notebook Dialog */} {/* Edit Notebook Dialog */} {editingNotebook && ( { if (!open) setEditingNotebook(null) }} /> )} {/* Delete Confirmation Dialog */} {deletingNotebook && ( { if (!open) setDeletingNotebook(null) }} /> )} {/* Notebook Summary Dialog */} { if (!open) setSummaryNotebook(null) }} notebookId={summaryNotebook?.id} notebookName={summaryNotebook?.name} /> ) }