tahamajs/IE / Projects /front /src /components /data-hub /CodeRepoPanel.tsx
tahamajs's picture
download
raw
3.68 kB
// src/components/data-hub/CodeRepoPanel.tsx
import { useState } from "react";
import { useCodeRepositoryIntegration } from "@/hooks/useCodeRepositoryIntegration";
import { GitBranch, Github, Plus, ExternalLink, Trash2, Star, Loader2 } from "lucide-react";
export function CodeRepoPanel() {
const { repos, loading, connecting, linkRepo, unlinkRepo } = useCodeRepositoryIntegration();
const [showLink, setShowLink] = useState(false);
const [provider, setProvider] = useState<"github" | "gitlab">("github");
const [owner, setOwner] = useState("");
const [name, setName] = useState("");
const handleLink = () => {
if (!owner.trim() || !name.trim()) return;
linkRepo(provider, owner.trim(), name.trim());
setOwner(""); setName(""); setShowLink(false);
};
return (
<div className="space-y-4">
<div className="flex items-center justify-between">
<h2 className="text-xl font-bold flex items-center gap-2"><GitBranch className="w-5 h-5 text-primary"/> Linked Repositories</h2>
<button onClick={() => setShowLink(true)} className="btn btn-primary btn-sm gap-1.5"><Plus className="w-4 h-4"/> Link Repo</button>
</div>
{showLink && (
<div className="glass rounded-xl p-4 space-y-3">
<div className="flex gap-2">
<button onClick={() => setProvider("github")} className={`px-4 py-2 rounded-lg text-sm ${provider === "github" ? "bg-primary/20 text-primary" : "bg-white/10"}`}>GitHub</button>
<button onClick={() => setProvider("gitlab")} className={`px-4 py-2 rounded-lg text-sm ${provider === "gitlab" ? "bg-primary/20 text-primary" : "bg-white/10"}`}>GitLab</button>
</div>
<div className="flex gap-2">
<input type="text" value={owner} onChange={e => setOwner(e.target.value)} placeholder="Owner/Org" className="flex-1 input text-sm" />
<input type="text" value={name} onChange={e => setName(e.target.value)} placeholder="Repo name" className="flex-1 input text-sm" />
</div>
<button onClick={handleLink} disabled={connecting} className="btn btn-primary btn-sm w-full">{connecting ? <Loader2 className="w-4 h-4 animate-spin"/> : "Link"}</button>
</div>
)}
{loading ? (
<div className="flex justify-center py-8"><Loader2 className="w-6 h-6 animate-spin text-gray-400"/></div>
) : repos.length === 0 ? (
<div className="text-center py-8 text-gray-400"><Github className="w-8 h-8 mx-auto mb-2 opacity-30"/><p>No linked repositories</p></div>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
{repos.map(repo => (
<div key={repo.id} className="glass rounded-xl p-4 flex items-start justify-between">
<div>
<div className="flex items-center gap-2">
{repo.provider === "github" ? <Github className="w-4 h-4"/> : <GitBranch className="w-4 h-4"/>}
<a href={repo.url} target="_blank" className="font-semibold text-sm hover:text-primary">{repo.owner}/{repo.name}</a>
</div>
<p className="text-xs text-gray-500 mt-1">{repo.description}</p>
<div className="flex items-center gap-3 mt-2 text-xs text-gray-400">
<span>{repo.language}</span>
<span className="flex items-center gap-1"><Star className="w-3 h-3"/> {repo.stars}</span>
</div>
</div>
<button onClick={() => unlinkRepo(repo.id)} className="text-gray-400 hover:text-red-500"><Trash2 className="w-4 h-4"/></button>
</div>
))}
</div>
)}
</div>
);
}

Xet Storage Details

Size:
3.68 kB
·
Xet hash:
2274e13392d7f863330c43ae7a2d97112282e5d0e4fc7711cb8f0fd848b43a8a

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.