import React, { useState, useRef, useEffect } from "react"; // @ts-ignore import FolderIcon from "@/assets/fontawesome/svg/folder.svg?react"; // @ts-ignore import TagsIcon from "@/assets/fontawesome/svg/tags.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 { useUIStore } from "@/stores/uiStore.ts"; import { TagSelector } from "../../Home.tsx"; import { useCreateFolder, useFolderTree, useUpdateFolder, useUpdateNote, } from "@/hooks/useFolders.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 { data: folderTree, isLoading, error } = useFolderTree(); const createFolder = useCreateFolder(); const { encryptionKey } = useAuthStore(); const { setSideBarResize, sideBarResize, sideBarView, setSideBarView } = useUIStore(); useEffect(() => { if (newFolder && newFolderRef.current) { newFolderRef.current.focus(); } }, [newFolder]); useEffect(() => { if (!encryptionKey) return; }, [encryptionKey]); const handleCreateFolder = async () => { if (!newFolderText.trim()) return; createFolder.mutate({ name: newFolderText, parentId: null }); }; 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 updateNote = useUpdateNote(); const updateFolder = useUpdateFolder(); 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); updateNote.mutate({ noteId: active.id as number, note: { folderId: 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 { updateFolder.mutate({ folderId: active.data.current.folder.id, folder: { parentId: 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 (
{sideBarView == "folders" ? ( <>
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); } }} />
)} {/* Loading state */} {isLoading && (
Loading folders...
)} {/* Error state */} {error && (
Failed to load folders
)} {/* Folder tree */} {!isLoading && !error && ( <>
{folderTree?.folders.map((folder) => ( ))}
{/* Orphaned notes */} {folderTree?.orphanedNotes && folderTree.orphanedNotes.length > 0 && (
{folderTree.orphanedNotes.map((note) => ( ))}
)} )}
{activeItem?.type === "note" && (
{activeItem.data.title}
)} {activeItem?.type === "folder" && (
{activeItem.data.name}
)}
) : (
)}
); };