import { useQuery } from "@tanstack/react-query";
import { Link, useParams, useSearch } from "@tanstack/react-router";
import { api } from "../api/client";
import { Card, CardBody, CardHeader } from "../components/ui/Card";
interface RepoPageSearch {
channel?: string;
path?: string;
}
export function RepoPage() {
const { owner, name } = useParams({ from: "/$owner/$name" });
const { channel: channelParam, path: pathParam } = useSearch({ from: "/$owner/$name" }) as RepoPageSearch;
const { data: repo, isLoading: repoLoading } = useQuery({
queryKey: ["repo", owner, name],
queryFn: () => api.repos.get(owner, name),
});
const { data: channels = [] } = useQuery({
queryKey: ["repo", owner, name, "channels"],
queryFn: () => api.repos.channels(owner, name),
enabled: !!repo,
});
const channel = channelParam ?? repo?.defaultChannel ?? "main";
const { data: tree = [], isLoading: treeLoading } = useQuery({
queryKey: ["repo", owner, name, "tree", channel, pathParam ?? ""],
queryFn: () => api.repos.tree(owner, name, channel, pathParam),
enabled: !!repo,
});
if (repoLoading) {
return <div className="flex items-center justify-center py-32 text-[#6e6e73]">Loading…</div>;
}
if (!repo) {
return (
<div className="max-w-2xl mx-auto px-6 py-20 text-center">
<p className="text-[17px] text-[#6e6e73]">Repository not found</p>
</div>
);
}
const breadcrumbs = pathParam?.split("/").filter(Boolean) ?? [];
return (
<div className="max-w-5xl mx-auto px-6 py-8">
{/* Header */}
<div className="flex items-start justify-between mb-6">
<div>
<div className="flex items-center gap-1.5 text-[15px] mb-1">
<Link to="/$owner/$name" params={{ owner, name: "" }} className="text-[#0071e3] hover:underline">
{owner}
</Link>
<span className="text-[#6e6e73]">/</span>
<span className="font-semibold text-[#1d1d1f]">{name}</span>
<span className="text-[11px] text-[#6e6e73] border border-black/[0.08] rounded-full px-2 py-0.5">
{repo.visibility}
</span>
</div>
{repo.description && (
<p className="text-[14px] text-[#6e6e73]">{repo.description}</p>
)}
</div>
<div className="flex items-center gap-2">
<Link
to="/$owner/$name/changes"
params={{ owner, name }}
className="text-[13px] text-[#0071e3] hover:underline"
>
Changes
</Link>
</div>
</div>
{/* Channel selector */}
{channels.length > 1 && (
<div className="flex items-center gap-2 mb-4">
<span className="text-[12px] text-[#6e6e73]">Channel:</span>
<div className="flex gap-1">
{channels.map((ch) => (
<Link
key={ch}
to="/$owner/$name"
params={{ owner, name }}
search={{ channel: ch }}
className={`text-[12px] px-3 py-1 rounded-full border transition-colors ${
ch === channel
? "bg-[#0071e3] text-white border-[#0071e3]"
: "border-black/[0.08] text-[#6e6e73] hover:border-[#0071e3]/40"
}`}
>
{ch}
</Link>
))}
</div>
</div>
)}
{/* File tree */}
<Card>
<CardHeader>
{/* Breadcrumb */}
<div className="flex items-center gap-1 text-[13px]">
<Link
to="/$owner/$name"
params={{ owner, name }}
search={{ channel }}
className="text-[#0071e3] hover:underline"
>
{name}
</Link>
{breadcrumbs.map((crumb, i) => (
<span key={crumb}>
<span className="text-[#6e6e73] mx-1">/</span>
<Link
to="/$owner/$name"
params={{ owner, name }}
search={{ channel, path: breadcrumbs.slice(0, i + 1).join("/") }}
className="text-[#0071e3] hover:underline"
>
{crumb}
</Link>
</span>
))}
</div>
</CardHeader>
{treeLoading ? (
<CardBody>
<div className="text-[13px] text-[#6e6e73]">Loading…</div>
</CardBody>
) : tree.length === 0 ? (
<CardBody>
<p className="text-[14px] text-[#6e6e73] text-center py-8">
This repository is empty. Push some changes to get started.
</p>
</CardBody>
) : (
<div className="divide-y divide-black/[0.04]">
{pathParam && (
<Link
to="/$owner/$name"
params={{ owner, name }}
search={{ channel, path: breadcrumbs.slice(0, -1).join("/") || undefined }}
className="flex items-center gap-3 px-5 py-3 hover:bg-black/[0.02] transition-colors"
>
<span className="text-[#6e6e73]">📁</span>
<span className="text-[14px] text-[#6e6e73]">..</span>
</Link>
)}
{tree.map((entry) => (
entry.kind === "dir" ? (
<Link
key={entry.path}
to="/$owner/$name"
params={{ owner, name }}
search={{ channel, path: entry.path }}
className="flex items-center gap-3 px-5 py-3 hover:bg-black/[0.02] transition-colors"
>
<span>📁</span>
<span className="text-[14px] text-[#0071e3]">{entry.name}</span>
</Link>
) : (
<Link
key={entry.path}
to="/$owner/$name/file"
params={{ owner, name }}
search={{ channel, path: entry.path }}
className="flex items-center gap-3 px-5 py-3 hover:bg-black/[0.02] transition-colors"
>
<span>📄</span>
<span className="text-[14px] text-[#1d1d1f]">{entry.name}</span>
</Link>
)
))}
</div>
)}
</Card>
</div>
);
}