1
0
Fork 0
mirror of https://gitbruv.vercel.app/api/git/bruv/gitbruv.git synced 2025-12-20 23:24:09 +01:00
gitbruv/components/file-tree.tsx
2025-12-20 04:23:17 +00:00

62 lines
2.1 KiB
TypeScript

"use client";
import Link from "next/link";
import { Folder, FileCode, FileText, FileJson, File } from "lucide-react";
import { formatDistanceToNow } from "date-fns";
type FileEntry = {
name: string;
type: "blob" | "tree";
oid: string;
path: string;
lastCommit?: { message: string; timestamp: number } | null;
};
const FILE_ICONS: Record<string, React.ElementType> = {
ts: FileCode,
tsx: FileCode,
js: FileCode,
jsx: FileCode,
py: FileCode,
rb: FileCode,
go: FileCode,
rs: FileCode,
java: FileCode,
md: FileText,
txt: FileText,
json: FileJson,
yaml: FileJson,
yml: FileJson,
};
function getFileIcon(name: string, type: "blob" | "tree") {
if (type === "tree") return Folder;
const ext = name.split(".").pop()?.toLowerCase() || "";
return FILE_ICONS[ext] || File;
}
export function FileTree({ files, username, repoName, branch }: { files: FileEntry[]; username: string; repoName: string; branch: string; basePath?: string }) {
return (
<div className="divide-y divide-border">
{files.map((file) => {
const Icon = getFileIcon(file.name, file.type);
const href = file.type === "tree" ? `/${username}/${repoName}/tree/${branch}/${file.path}` : `/${username}/${repoName}/blob/${branch}/${file.path}`;
return (
<Link key={file.oid + file.name} href={href} className="flex items-center gap-3 px-4 py-2.5 hover:bg-muted/50 transition-colors group">
<Icon className={`h-4 w-4 shrink-0 ${file.type === "tree" ? "text-accent" : "text-muted-foreground"}`} />
<span className="text-sm group-hover:text-accent truncate min-w-0 shrink">{file.name}</span>
{file.lastCommit && (
<>
<span className="text-sm text-muted-foreground truncate hidden sm:block flex-1 min-w-0">{file.lastCommit.message}</span>
<span className="text-sm text-muted-foreground whitespace-nowrap ml-auto">
{formatDistanceToNow(file.lastCommit.timestamp, { addSuffix: true })}
</span>
</>
)}
</Link>
);
})}
</div>
);
}