import React, { useState, useRef, useEffect, SetStateAction } from "react"; // @ts-ignore import FolderIcon from "@/assets/fontawesome/svg/folder.svg?react"; import { DraggableNote } from "./subcomponents/DraggableNote"; import { DndContext, DragEndEvent, DragOverlay, DragStartEvent, PointerSensor, useSensor, useSensors, } from "@dnd-kit/core"; import { FolderTree } from "./subcomponents/FolderTree.tsx"; import { SidebarHeader } from "./subcomponents/SideBarHeader.tsx"; import { useAuthStore } from "@/stores/authStore.ts"; import { useNoteStore } from "@/stores/notesStore.ts"; import { useUIStore } from "@/stores/uiStore.ts"; export const Sidebar = () => { const [newFolder, setNewFolder] = useState(false); const [newFolderText, setNewFolderText] = useState(""); const [activeItem, setActiveItem] = useState<{ type: "note" | "folder"; data: any; } | null>(null); const newFolderRef = useRef(null); const { folderTree, loadFolderTree, moveNoteToFolder, moveFolderToFolder, createFolder, } = useNoteStore(); const { encryptionKey } = useAuthStore(); const { setSideBarResize, sideBarResize } = useUIStore(); useEffect(() => { if (newFolder && newFolderRef.current) { newFolderRef.current.focus(); } }, [newFolder]); useEffect(() => { if (!encryptionKey) return; loadFolderTree(); }, [encryptionKey]); const handleCreateFolder = async () => { if (!newFolderText.trim()) return; await createFolder({ name: newFolderText, parent_id: null, }); setNewFolderText(""); setNewFolder(false); }; const pointer = useSensor(PointerSensor, { activationConstraint: { distance: 30, }, }); const sensors = useSensors(pointer); const handleDragStart = (event: DragStartEvent) => { const { active } = event; if (active.data.current?.type === "note") { setActiveItem({ type: "note", data: active.data.current.note }); } else if (active.data.current?.type === "folder") { setActiveItem({ type: "folder", data: active.data.current.folder }); } }; const handleDragEnd = async (event: DragEndEvent) => { setActiveItem(null); const { active, over } = event; if (!over) return; console.log("Drag ended:", { activeId: active.id, activeType: active.data.current?.type, activeFolder: active.data.current?.folder, overId: over.id, overType: over.data.current?.type, }); if (active.data.current?.type === "note") { console.log("Updating note", active.id, "to folder", over.id); await moveNoteToFolder(active.id as number, over.id as number); } else if (active.data.current?.type === "folder") { // Prevent dropping folder into itself if (active.data.current.folder.id === over.id) { console.log("Cannot drop folder into itself"); return; } console.log( "Updating folder", active.data.current.folder.id, "parent to", over.id, ); try { await moveFolderToFolder( active.data.current.folder.id, over.id as number, ); } catch (error) { console.error("Failed to update folder:", error); return; } } }; const [isResizing, setIsResizing] = useState(false); const handleMouseDown = (e: React.MouseEvent) => { setIsResizing(true); e.preventDefault(); }; useEffect(() => { const handleMouseMove = (e: MouseEvent) => { if (!isResizing) return; // Calculate new width based on mouse position from the left edge const newWidth = e.clientX; if (newWidth >= 200 && newWidth <= 500) { setSideBarResize(newWidth); } }; const handleMouseUp = () => { setIsResizing(false); }; if (isResizing) { document.addEventListener("mousemove", handleMouseMove); document.addEventListener("mouseup", handleMouseUp); } return () => { document.removeEventListener("mousemove", handleMouseMove); document.removeEventListener("mouseup", handleMouseUp); }; }, [isResizing]); return (
e.preventDefault()} onTouchMove={(e) => e.preventDefault()} > {/* New folder input */} {newFolder && (
setNewFolder(false)} onChange={(e) => setNewFolderText(e.target.value)} value={newFolderText} type="text" placeholder="Folder name..." className="standard-input" ref={newFolderRef} onKeyDown={(e) => { if (e.key === "Enter") { handleCreateFolder(); } if (e.key === "Escape") { setNewFolder(false); } }} />
)} {/* Folder tree */}
{folderTree?.folders.map((folder) => ( ))}
{/* Orphaned notes */} {folderTree?.orphaned_notes && folderTree.orphaned_notes.length > 0 && (
{folderTree.orphaned_notes.map((note) => ( ))}
)}
{activeItem?.type === "note" && (
{activeItem.data.title}
)} {activeItem?.type === "folder" && (
{activeItem.data.name}
)}
); };