| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960 |
- "use client";
- import {
- BadgeCheck, Bot, Braces, Database, FileCheck2, FileLock2, Flag,
- GitCommitHorizontal, PackageCheck, RadioTower, RefreshCcw, Rocket,
- Send, ShieldCheck, Workflow,
- } from "lucide-react";
- import { Handle, Position, type Node, type NodeProps } from "@xyflow/react";
- import type { CardData } from "@/lib/flow";
- import type { NodeType } from "@/lib/types";
- const ICONS: Record<NodeType, typeof Database> = {
- input: Database,
- contract: FileLock2,
- operation: RadioTower,
- worker: Bot,
- attempt: Send,
- artifact: PackageCheck,
- validator: ShieldCheck,
- validation: FileCheck2,
- decision: BadgeCheck,
- checkpoint: Flag,
- publication: Rocket,
- transaction: GitCommitHorizontal,
- readback: RefreshCcw,
- };
- export function FlowCard({ data, selected }: NodeProps<Node<CardData>>) {
- const item = data.item;
- const Icon = ICONS[item.node_type] ?? Braces;
- return <article
- className={`flowCard type-${item.node_type} status-${item.status} ${selected ? "selected" : ""} ${data.dimmed ? "dimmed" : ""}`}
- data-node-id={item.id}
- >
- <Handle type="target" position={Position.Left} className="nodeHandle" />
- <header className="cardHeader">
- <span className="nodeIcon"><Icon size={17} strokeWidth={1.9} /></span>
- <span className="cardKind">{item.node_type}</span>
- <span className="sequence">{String(item.sequence).padStart(2, "0")}</span>
- </header>
- <div className="cardBody">
- <h3>{item.title}</h3>
- <p>{item.subtitle}</p>
- <div className="recordType"><Workflow size={12} /> {item.record.model_name}</div>
- {item.metrics.length ? <dl className="metricGrid">
- {item.metrics.slice(0, 3).map((metric) => <div key={`${metric.label}:${metric.value}`}>
- <dt>{metric.label}</dt><dd>{metric.value}</dd>
- </div>)}
- </dl> : null}
- </div>
- <footer className="cardFooter">
- <span className={`statusDot status-${item.status}`} />
- <strong>{item.status}</strong>
- {item.agent_role ? <span>{item.agent_role}</span> : null}
- {item.task_kind ? <span className="taskKind">{item.task_kind}</span> : null}
- </footer>
- <Handle type="source" position={Position.Right} className="nodeHandle" />
- </article>;
- }
|