import React from 'react'; import { Plus, Archive, Settings, ChevronRight, BookOpen, Bot, Microscope, Activity, Pin, Moon, Sun, Bell, Lock, Edit3, Trash2, Users, Clock, GripVertical, Wind, Network } from 'lucide-react'; import { motion, AnimatePresence } from 'motion/react'; import { NavigationView, Carnet, Note } from '../types'; interface NoteLinkProps { note: Note; isActive: boolean; onClick: () => void; } const NoteLink: React.FC = ({ note, isActive, onClick }) => (
{note.title}
{note.isPinned && } ); interface SidebarItemProps { carnet: Carnet; isActive: boolean; notes: Note[]; activeNoteId: string | null; onCarnetClick: () => void; onNoteClick: (noteId: string) => void; onAddSubCarnet: () => void; onRename: () => void; onDelete: () => void; children?: React.ReactNode; level: number; isExpanded: boolean; toggleExpand: () => void; onMove?: (draggedId: string, targetId?: string) => void; } const SidebarItem: React.FC = ({ carnet, isActive, notes, activeNoteId, onCarnetClick, onNoteClick, onAddSubCarnet, onRename, onDelete, children, level, isExpanded, toggleExpand, onMove }) => { const hasChildren = React.Children.count(children) > 0; return (
{/* Subtle Drag Handle */}
{/* Hierarchy Guide Line */} {level > 0 && (
)} {level > 0 && (
)}
{hasChildren ? ( ) : (
// Spacer for alignment )} { e.preventDefault(); e.dataTransfer.dropEffect = 'move'; e.currentTarget.classList.add('bg-blueprint/5', 'ring-1', 'ring-blueprint/20'); }} onDragLeave={(e) => { e.currentTarget.classList.remove('bg-blueprint/5', 'ring-1', 'ring-blueprint/20'); }} onDrop={(e) => { e.preventDefault(); e.currentTarget.classList.remove('bg-blueprint/5', 'ring-1', 'ring-blueprint/20'); const draggedId = e.dataTransfer.getData('carnetId'); console.log('Dropped carnet:', draggedId, 'on target:', carnet.id); if (draggedId && draggedId !== carnet.id) { onMove?.(draggedId, carnet.id); } }} draggable onDragStart={(e) => { console.log('Starting drag for carnet:', carnet.id); e.dataTransfer.setData('carnetId', carnet.id); e.dataTransfer.effectAllowed = 'move'; const ghost = e.currentTarget.cloneNode(true) as HTMLElement; ghost.style.position = 'absolute'; ghost.style.top = '-1000px'; ghost.style.opacity = '0.5'; document.body.appendChild(ghost); e.dataTransfer.setDragImage(ghost, 0, 0); setTimeout(() => document.body.removeChild(ghost), 0); }} > {/* active indicator dot */} {isActive && ( )}
{carnet.initial}
{carnet.name} {carnet.isPrivate && }
{notes.length > 0 && ( {notes.length} )}
{(isExpanded || (isActive && !hasChildren)) && (
{/* Vertical line for nested content */}
{children} {isActive && !hasChildren && notes.map(note => ( onNoteClick(note.id)} /> ))} {isActive && !hasChildren && notes.length === 0 && (

No notes found

)}
)}
); }; interface SidebarProps { activeView: NavigationView; isDarkMode: boolean; setIsDarkMode: (val: boolean) => void; setActiveView: (view: NavigationView) => void; carnets: Carnet[]; notes: Note[]; activeCarnetId: string; activeNoteId: string | null; setActiveCarnetId: (id: string) => void; setActiveNoteId: (id: string | null) => void; setShowNewCarnetModal: (show: boolean, parentId?: string, isRenaming?: boolean, carnetId?: string) => void; onDeleteCarnet: (id: string) => void; onMoveCarnet: (draggedId: string, targetId?: string) => void; } export const Sidebar: React.FC = ({ activeView, isDarkMode, setIsDarkMode, setActiveView, carnets, notes, activeCarnetId, activeNoteId, setActiveCarnetId, setActiveNoteId, setShowNewCarnetModal, onDeleteCarnet, onMoveCarnet }) => { const [expandedIds, setExpandedIds] = React.useState>(new Set(['4'])); // Default expand Research const toggleExpand = (id: string) => { const newSet = new Set(expandedIds); if (newSet.has(id)) newSet.delete(id); else newSet.add(id); setExpandedIds(newSet); }; const renderCarnetTree = (parentId: string | undefined = undefined, level: number = 0) => { return carnets .filter(c => c.parentId === parentId && !c.isDeleted) .map(carnet => ( n.carnetId === carnet.id && !n.isDeleted)} activeNoteId={activeNoteId} level={level} isExpanded={expandedIds.has(carnet.id)} toggleExpand={() => toggleExpand(carnet.id)} onAddSubCarnet={() => { if (!expandedIds.has(carnet.id)) toggleExpand(carnet.id); setShowNewCarnetModal(true, carnet.id); }} onRename={() => { setShowNewCarnetModal(true, undefined, true, carnet.id); }} onDelete={() => { onDeleteCarnet(carnet.id); }} onCarnetClick={() => { setActiveCarnetId(carnet.id); setActiveNoteId(null); // Auto expand when clicking if (!expandedIds.has(carnet.id)) toggleExpand(carnet.id); }} onNoteClick={(id) => { setActiveCarnetId(carnet.id); setActiveNoteId(id); }} onMove={onMoveCarnet} > {renderCarnetTree(carnet.id, level + 1)} )); }; return ( ); };