import { useState, useCallback } from "react";
import type { ChainSummary, ChainStatus } from "../../lib/api";
interface ChainListProps {
chains: ChainSummary[];
loading: boolean;
onSelect: (chainId: string) => void;
onCreate: () => void;
selectedId?: string;
onArchive: (chain: ChainSummary) => void;
}
const statusColors: Record<ChainStatus, string> = {
pending: "text-yellow-400",
active: "text-green-400",
completed: "text-blue-400",
archived: "text-[#555]",
};
export function ChainList({
chains,
loading,
onSelect,
onCreate,
selectedId,
onArchive,
}: ChainListProps) {
const [filter, setFilter] = useState<ChainStatus | "all">("all");
const [contextMenuPosition, setContextMenuPosition] = useState<{ x: number; y: number } | null>(null);
const [contextMenuChain, setContextMenuChain] = useState<ChainSummary | null>(null);
const filteredChains =
filter === "all"
? chains
: chains.filter((c) => c.status === filter);
const handleContextMenu = useCallback(
(e: React.MouseEvent, chain: ChainSummary) => {
e.preventDefault();
setContextMenuPosition({ x: e.clientX, y: e.clientY });
setContextMenuChain(chain);
},
[]
);
const closeContextMenu = useCallback(() => {
setContextMenuPosition(null);
setContextMenuChain(null);
}, []);
const handleArchive = useCallback(() => {
if (contextMenuChain) {
onArchive(contextMenuChain);
closeContextMenu();
}
}, [contextMenuChain, onArchive, closeContextMenu]);
if (loading) {
return (
<div className="panel h-full flex items-center justify-center">
<div className="font-mono text-[#9bc3ff] text-sm">Loading...</div>
</div>
);
}
return (
<div className="panel h-full flex flex-col" onClick={closeContextMenu}>
{/* Header */}
<div className="p-4 border-b border-dashed border-[rgba(117,170,252,0.35)]">
<div className="flex items-center justify-between mb-3">
<h2 className="font-mono text-sm text-[#75aafc] uppercase tracking-wider">
Chains
</h2>
<button
onClick={onCreate}
className="px-3 py-1.5 font-mono text-xs text-[#dbe7ff] bg-[#0f3c78] border border-[#3f6fb3] hover:bg-[#153667] transition-colors uppercase"
>
+ New
</button>
</div>
{/* Filter tabs */}
<div className="flex gap-1">
{(["all", "active", "completed", "archived"] as const).map((status) => (
<button
key={status}
onClick={() => setFilter(status)}
className={`
px-2 py-1 font-mono text-[10px] uppercase tracking-wider transition-colors
${
filter === status
? "bg-[rgba(117,170,252,0.1)] text-[#9bc3ff] border border-[rgba(117,170,252,0.3)]"
: "text-[#555] hover:text-[#75aafc]"
}
`}
>
{status}
</button>
))}
</div>
</div>
{/* Chain list */}
<div className="flex-1 overflow-y-auto">
{filteredChains.length === 0 ? (
<div className="p-4 text-center">
<p className="font-mono text-sm text-[#555]">
{filter === "all"
? "No chains yet"
: `No ${filter} chains`}
</p>
</div>
) : (
<div className="divide-y divide-[rgba(117,170,252,0.15)]">
{filteredChains.map((chain) => (
<button
key={chain.id}
onClick={() => onSelect(chain.id)}
onContextMenu={(e) => handleContextMenu(e, chain)}
className={`
w-full text-left p-4 transition-colors
${
selectedId === chain.id
? "bg-[rgba(117,170,252,0.1)]"
: "hover:bg-[rgba(117,170,252,0.05)]"
}
`}
>
<div className="flex items-start justify-between gap-2 mb-2">
<h3 className="font-mono text-sm text-[#dbe7ff] truncate">
{chain.name}
</h3>
<span
className={`text-[10px] font-mono uppercase shrink-0 ${
statusColors[chain.status]
}`}
>
{chain.status}
</span>
</div>
{chain.description && (
<p className="font-mono text-xs text-[#555] mb-2 line-clamp-2">
{chain.description}
</p>
)}
<div className="flex items-center gap-4 text-[10px] font-mono text-[#555]">
<span>{chain.contractCount} contracts</span>
<span>{chain.completedContractCount} completed</span>
{chain.loopEnabled && (
<span className="text-amber-400">
loop {chain.loopCurrentIteration || 0}/{chain.loopMaxIterations || "∞"}
</span>
)}
</div>
</button>
))}
</div>
)}
</div>
{/* Context Menu */}
{contextMenuPosition && contextMenuChain && (
<div
className="fixed z-50 bg-[#0a1628] border border-[rgba(117,170,252,0.3)] shadow-lg py-1 min-w-[150px]"
style={{ top: contextMenuPosition.y, left: contextMenuPosition.x }}
onClick={(e) => e.stopPropagation()}
>
<button
onClick={() => {
onSelect(contextMenuChain.id);
closeContextMenu();
}}
className="w-full px-4 py-2 text-left font-mono text-xs text-[#dbe7ff] hover:bg-[rgba(117,170,252,0.1)] transition-colors"
>
View Details
</button>
{contextMenuChain.status !== "archived" && (
<button
onClick={handleArchive}
className="w-full px-4 py-2 text-left font-mono text-xs text-red-400 hover:bg-red-400/10 transition-colors"
>
Archive
</button>
)}
</div>
)}
</div>
);
}