import { useState, useCallback } from 'react' import { toast } from 'sonner' export interface FileNode { id: string name: string type: 'file' | 'folder' content?: string language?: string children?: FileNode[] expanded?: boolean } /** * Hook to manage file tree operations * Handles tree traversal, node creation, deletion, and updates */ export function useFileTree(initialFiles: FileNode[] = []) { const [files, setFiles] = useState(initialFiles) const findNodeById = useCallback((id: string, nodes = files): FileNode | null => { for (const node of nodes) { if (node.id === id) return node if (node.children) { const found = findNodeById(id, node.children) if (found) return found } } return null }, [files]) const updateNode = useCallback((id: string, updates: Partial) => { const update = (nodes: FileNode[]): FileNode[] => nodes.map(node => { if (node.id === id) { return { ...node, ...updates } } if (node.children) { return { ...node, children: update(node.children) } } return node }) setFiles(update) }, []) const deleteNode = useCallback((id: string) => { const remove = (nodes: FileNode[]): FileNode[] => nodes.filter(node => node.id !== id).map(node => ({ ...node, children: node.children ? remove(node.children) : undefined, })) setFiles(remove) toast.success('Deleted') }, []) const toggleFolder = useCallback((id: string) => { updateNode(id, { expanded: (node => !node.expanded)(findNodeById(id)!) }) }, [updateNode, findNodeById]) const addChild = useCallback((parentId: string, child: FileNode) => { const parent = findNodeById(parentId) if (!parent || parent.type !== 'folder') return setFiles(files => files.map(node => { if (node.id === parentId) { return { ...node, children: [...(node.children || []), child], } } if (node.children) { return { ...node, children: files.map(n => (n.id === parentId ? { ...n, children: [...(n.children || []), child] } : n))[0]?.children || node.children, } } return node }) ) toast.success('Created') }, [findNodeById, files]) return { files, setFiles, findNodeById, updateNode, deleteNode, toggleFolder, addChild, } }