import { useCallback, useEffect, useState } from "react"; import { useSearchParams } from "react-router-dom"; import { apiClient } from "../../../api/client"; import { EmptyState } from "../../data-states"; import { Icon } from "../../icon"; import type { GitStatus } from "../../../api/git-repositories"; interface FileTreeEntry { name: string; type: "file" | "directory"; path: string; size?: number; mode?: string; last_commit?: { hash: string; message: string; author: string; date: string; } | null; } interface Props { projectId: string; repoId: string; gitStatus: GitStatus | null; } export const FileBrowser = ({ projectId, repoId, gitStatus }: Props) => { const [searchParams, setSearchParams] = useSearchParams(); const [entries, setEntries] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const branch = searchParams.get("branch") || "main"; const path = searchParams.get("path") || ""; const loadFiles = useCallback(async () => { setLoading(true); setError(null); try { const response = await apiClient.get( `/projects/${projectId}/repositories/${repoId}/files`, { params: { branch, path } } ); setEntries(response.data.entries || []); } catch { setError("Failed to load files"); } finally { setLoading(false); } }, [projectId, repoId, branch, path]); useEffect(() => { void loadFiles(); }, [loadFiles]); useEffect(() => { const handleRefresh = () => void loadFiles(); window.addEventListener("refresh-file-tree", handleRefresh); return () => window.removeEventListener("refresh-file-tree", handleRefresh); }, [loadFiles]); const handleEntryClick = (entry: FileTreeEntry) => { if (entry.type === "directory") { const newParams = new URLSearchParams(searchParams); newParams.set("path", entry.path); setSearchParams(newParams); } else { const newParams = new URLSearchParams(searchParams); newParams.set("file", entry.path); setSearchParams(newParams); } }; const navigateUp = () => { if (!path) return; const parentPath = path.split("/").slice(0, -1).join("/"); const newParams = new URLSearchParams(searchParams); if (parentPath) { newParams.set("path", parentPath); } else { newParams.delete("path"); } setSearchParams(newParams); }; const getFileStatus = (filePath: string): string | null => { if (!gitStatus) return null; if (gitStatus.modified.includes(filePath)) return "modified"; if (gitStatus.added.includes(filePath)) return "added"; if (gitStatus.deleted.includes(filePath)) return "deleted"; if (gitStatus.untracked.includes(filePath)) return "untracked"; return null; }; if (loading) return

Loading files...

; if (error) return

{error}

; return (
{path && ( )} {entries.length === 0 && ( )} {entries.map((entry) => { const fileStatus = entry.type === "file" ? getFileStatus(entry.path) : null; return ( ); })}
); };