import React, { useState } from "react"; import { useSelector, useDispatch } from 'react-redux'; import { toggleNodeExpansion } from '../../store/navigationSlice'; import { Link } from "react-router-dom"; import { ChevronRight, Folder, FolderOpen, Settings2, Pencil, Check, Trash2, ChevronUp, ChevronDown, } from "lucide-react"; import PermissionGuard from "../PermissionGuard"; import { useDeletePath, useMovePath, useUpdatePath } from "../../utils/queries/path-queries"; import { useIndexMarkdown, useMoveMarkdown } from "../../utils/queries/markdown-queries"; import MarkdownNode from "./MarkdownNode"; import PathSettingModal from "../Modals/PathSettingModal"; import { cn } from "../../lib/utils"; const iconBtn = "grid h-6 w-6 place-items-center rounded text-muted-foreground transition-colors hover:bg-accent hover:text-primary"; const PathNode = ({ path, isRoot = false }) => { const [isPathSettingModalOpen, setIsPathSettingModalOpen] = useState(false); const [isEditing, setIsEditing] = useState(false); const [newName, setNewName] = useState(path.name || ""); const expandedNodes = useSelector(state => state.navigation.expandedNodes); const dispatch = useDispatch(); const isExpanded = isRoot || expandedNodes[path.id]; const deletePath = useDeletePath(); const updatePath = useUpdatePath(); const { data: indexMarkdown } = useIndexMarkdown(path.id); const movePath = useMovePath(); const moveMarkdown = useMoveMarkdown(); const expand = () => { if (!isExpanded) dispatch(toggleNodeExpansion(path.id)); }; const toggleExpand = () => dispatch(toggleNodeExpansion(path.id)); const handleSave = () => { updatePath.mutate({ id: path.id, data: { name: newName } }, { onSuccess: () => setIsEditing(false), onError: () => alert("failed to update this path"), }); }; const handleDelete = () => { if (window.confirm("Are you sure?")) { deletePath.mutate(path.id, { onError: () => alert("failed to delete this path"), }); } }; const handleEdit = () => setIsEditing(true); const handleMovePath = (pth, direction) => { movePath.mutate({ path: pth, direction }, { onError: () => alert("failed to move this path"), }); }; const handleMoveMarkdown = (md, direction) => { moveMarkdown.mutate({ markdown: md, direction }, { onError: () => alert("failed to move this markdown"), }); }; const childPaths = path.children.filter(x => x.type === "path"); const sortedPaths = childPaths ? childPaths.slice().sort((a, b) => a.order.localeCompare(b.order)) : []; const markdowns = path.children.filter(x => x.type === "markdown"); const sortedMarkdowns = markdowns ? markdowns.filter(md => md.title !== "index").sort((a, b) => a.order.localeCompare(b.order)) : []; if (isRoot) return ( ); return (
  • {isEditing ? ( setNewName(e.target.value)} onKeyDown={(e) => e.key === "Enter" && handleSave()} /> ) : indexMarkdown ? ( // Clicking the name navigates to the folder's index page // AND expands the subtree (expanded state is global, so // the children stay visible after navigation). {path.name} ) : ( {path.name} )}
    {isEditing ? ( ) : ( )}
    setIsPathSettingModalOpen(false)} />
    {isExpanded && ( )}
  • ); }; export default PathNode;