import { useState, useEffect } from "react"; import type { ContractRepository, RepositorySourceType, RepositoryStatus, DaemonDirectory, } from "../../lib/api"; import { getDaemonDirectories } from "../../lib/api"; import { DirectoryInput } from "../mesh/DirectoryInput"; interface RepositoryPanelProps { repositories: ContractRepository[]; onAddRemote: (name: string, url: string, isPrimary: boolean) => void; onAddLocal: (name: string, path: string, isPrimary: boolean) => void; onCreateManaged: (name: string, isPrimary: boolean) => void; onDelete: (repoId: string) => void; onSetPrimary: (repoId: string) => void; } type AddMode = "remote" | "local" | "managed" | null; const sourceTypeLabels: Record = { remote: "Remote", local: "Local", managed: "Managed", }; const sourceTypeIcons: Record = { remote: "GH", local: "FS", managed: "MK", }; const statusColors: Record = { ready: "text-green-400", pending: "text-yellow-400", creating: "text-cyan-400", failed: "text-red-400", }; export function RepositoryPanel({ repositories, onAddRemote, onAddLocal, onCreateManaged, onDelete, onSetPrimary, }: RepositoryPanelProps) { const [addMode, setAddMode] = useState(null); const [name, setName] = useState(""); const [url, setUrl] = useState(""); const [path, setPath] = useState(""); const [isPrimary, setIsPrimary] = useState(false); // Daemon directory suggestions for local repositories const [suggestedDirectories, setSuggestedDirectories] = useState([]); // Fetch daemon directories when "local" mode is selected useEffect(() => { if (addMode === "local") { getDaemonDirectories() .then((res) => setSuggestedDirectories(res.directories)) .catch(() => setSuggestedDirectories([])); } }, [addMode]); const handleAdd = () => { if (!name.trim()) return; if (addMode === "remote" && url.trim()) { onAddRemote(name.trim(), url.trim(), isPrimary); } else if (addMode === "local" && path.trim()) { onAddLocal(name.trim(), path.trim(), isPrimary); } else if (addMode === "managed") { onCreateManaged(name.trim(), isPrimary); } // Reset form setAddMode(null); setName(""); setUrl(""); setPath(""); setIsPrimary(false); }; const handleCancel = () => { setAddMode(null); setName(""); setUrl(""); setPath(""); setIsPrimary(false); }; return (
{/* Repository list */} {repositories.length === 0 ? (

No repositories configured

) : (
{repositories.map((repo) => (
{/* Type icon */} {sourceTypeIcons[repo.sourceType]} {/* Name and details */}
{repo.name} {repo.isPrimary && ( Primary )}
{repo.repositoryUrl || repo.localPath || "(pending creation)"}
{/* Status */} {repo.status} {/* Actions */}
{!repo.isPrimary && repo.status === "ready" && ( )}
))}
)} {/* Add repository form */} {addMode ? (
Add {sourceTypeLabels[addMode]} Repository
setName(e.target.value)} placeholder="Repository name" className="w-full px-3 py-2 bg-[#0d1b2d] border border-[#3f6fb3] text-[#dbe7ff] font-mono text-xs focus:outline-none focus:border-[#75aafc]" /> {addMode === "remote" && ( setUrl(e.target.value)} placeholder="https://github.com/owner/repo" className="w-full px-3 py-2 bg-[#0d1b2d] border border-[#3f6fb3] text-[#dbe7ff] font-mono text-xs focus:outline-none focus:border-[#75aafc]" /> )} {addMode === "local" && ( )} {addMode === "managed" && (

Makima will create this repository via the daemon.

)}
) : (
)}
); }