"use client" import { useEffect, useState } from "react" import { getRepositoryStructure, type RepoStructureEntry } from "@/lib/api/github" import { ChevronDown, ChevronRight, FileText, Folder } from "lucide-react" type Node = { name: string path: string type: 'file' | 'directory' } export default function RepoTree({ repositoryId, rootPath = "", onSelectFile, onSelectDirectory }: { repositoryId: string, rootPath?: string, onSelectFile: (path: string) => void, onSelectDirectory?: (path: string) => void }) { const [expanded, setExpanded] = useState>({}) const [loading, setLoading] = useState>({}) const [children, setChildren] = useState>({}) const toggle = async (nodePath: string) => { const next = !expanded[nodePath] setExpanded(prev => ({ ...prev, [nodePath]: next })) if (next && !children[nodePath]) { setLoading(prev => ({ ...prev, [nodePath]: true })) try { const res = await getRepositoryStructure(repositoryId, nodePath) const list = (res?.structure || []) as RepoStructureEntry[] const mapped: Node[] = list.map(e => ({ name: (e as any).name || (e as any).filename || (((e as any).path || (e as any).relative_path || '').split('/').slice(-1)[0]) || 'unknown', path: (e as any).path || (e as any).relative_path || '', type: (e as any).type === 'directory' || (e as any).type === 'dir' ? 'directory' : 'file' })) setChildren(prev => ({ ...prev, [nodePath]: mapped })) onSelectDirectory && onSelectDirectory(nodePath) } finally { setLoading(prev => ({ ...prev, [nodePath]: false })) } } } // initial load for root useEffect(() => { toggle(rootPath) onSelectDirectory && onSelectDirectory(rootPath) // eslint-disable-next-line react-hooks/exhaustive-deps }, [repositoryId, rootPath]) const renderNode = (node: Node) => { const isDir = node.type === 'directory' const isOpen = !!expanded[node.path] return (
isDir ? toggle(node.path) : onSelectFile(node.path)}> {isDir ? ( isOpen ? : ) : ( )} {isDir ? : } {node.name}
{isDir && isOpen && (
{loading[node.path] &&
Loading…
} {(children[node.path] || []).map(ch => renderNode(ch))}
)}
) } return (
{(children[rootPath] || []).map(n => renderNode(n))}
) }