diff options
| author | soryu <soryu@soryu.co> | 2026-02-06 01:02:32 +0000 |
|---|---|---|
| committer | soryu <soryu@soryu.co> | 2026-02-06 01:02:32 +0000 |
| commit | 8f725a7c64fbeb85ebeb59b54d2f774e9a0a59d6 (patch) | |
| tree | f66a7dd9190deb1a85b83da7302c85f7c171b69b /makima/frontend/src/components/chains/ChainList.tsx | |
| parent | 0fb5083e1f453b6b8dab402014f333e13df75733 (diff) | |
| download | soryu-8f725a7c64fbeb85ebeb59b54d2f774e9a0a59d6.tar.gz soryu-8f725a7c64fbeb85ebeb59b54d2f774e9a0a59d6.zip | |
Fix: Directive page and remove chain page
Diffstat (limited to 'makima/frontend/src/components/chains/ChainList.tsx')
| -rw-r--r-- | makima/frontend/src/components/chains/ChainList.tsx | 191 |
1 files changed, 0 insertions, 191 deletions
diff --git a/makima/frontend/src/components/chains/ChainList.tsx b/makima/frontend/src/components/chains/ChainList.tsx deleted file mode 100644 index e185efc..0000000 --- a/makima/frontend/src/components/chains/ChainList.tsx +++ /dev/null @@ -1,191 +0,0 @@ -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> - ); -} |
