import React, { useState, useRef, useEffect, SetStateAction } from "react"; import { FolderCreate, FolderTreeNode, FolderTreeResponse, NoteRead, folderApi, } from "../../api/folders"; import { DraggableNote } from "./DraggableNote"; import { DroppableFolder } from "./DroppableFolder"; import { useNoteStore } from "../../stores/notesStore"; import { DndContext, DragEndEvent, PointerSensor, useSensor, useSensors, } from "@dnd-kit/core"; import { notesApi } from "../../api/notes"; import { RecursiveFolder } from "./RecursiveFolder"; export const Sidebar = ({ clearSelection }: { clearSelection: () => void }) => { // const [folderTree, setFolderTree] = useState(null); const [newFolder, setNewFolder] = useState(false); const [newFolderText, setNewFolderText] = useState(""); const newFolderRef = useRef(null); const { setSelectedFolder, selectedFolder, folderTree, loadFolderTree, selectedNote, setSelectedNote, } = useNoteStore(); useEffect(() => { if (newFolder && newFolderRef.current) { newFolderRef.current.focus(); } }, [newFolder]); useEffect(() => { loadFolderTree(); }, []); const handleCreateFolder = async () => { if (!newFolderText.trim()) return; const newFolderData: FolderCreate = { name: newFolderText, parent_id: null, }; await folderApi.create(newFolderData); setNewFolderText(""); loadFolderTree(); setNewFolder(false); }; const pointer = useSensor(PointerSensor, { activationConstraint: { distance: 30, }, }); const sensors = useSensors(pointer); const handleDragEnd = async (event: DragEndEvent) => { 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 notesApi.update(active.id as number, { folder_id: 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 { const response = await folderApi.update(active.data.current.folder.id, { parent_id: over.id as number, }); console.log("Folder update response:", response); } catch (error) { console.error("Failed to update folder:", error); return; } } loadFolderTree(); }; 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="border border-ctp-mauve rounded-md px-3 py-2 w-full focus:outline-none focus:ring-2 focus:ring-ctp-mauve bg-ctp-base text-ctp-text placeholder:text-ctp-overlay0" 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 && (
{/*
Unsorted
*/} {folderTree.orphaned_notes.map((note) => ( ))}
)}
); }; export const SidebarHeader = ({ clearSelection, setNewFolder, }: { clearSelection: () => void; setNewFolder: React.Dispatch>; }) => { return (

FastNotes

); };