import { useEffect, useState } from "react"; import { Box, Chip, Divider, Paper, Stack, Typography } from "@mui/material"; import { fetchWorkflowGraph } from "../../lib/api"; import { WorkflowGraph } from "../../lib/types"; type WorkflowGraphPanelProps = { t: (key: string, fallback?: string) => string; }; export default function WorkflowGraphPanel({ t }: WorkflowGraphPanelProps) { const [graph, setGraph] = useState(null); const [error, setError] = useState(""); useEffect(() => { let alive = true; void fetchWorkflowGraph() .then((payload) => { if (alive) { setGraph(payload); } }) .catch((err) => { if (alive) { setError(String(err)); } }); return () => { alive = false; }; }, []); return ( {t("ui.workflow.graph.title", "Workflow Graph")} {graph ? t("ui.workflow.graph.summary", "Nodes: {nodes}, Edges: {edges}") .replace("{nodes}", String(graph.count.nodes)) .replace("{edges}", String(graph.count.edges)) : t("ui.workflow.graph.loading", "Loading graph…")} {error ? ( {error} ) : ( <> }> {graph?.nodes.map((node) => ( {node.label_key ? t(node.label_key, node.type) : node.type} {node.parent ? `${t("ui.workflow.graph.child_of", "child of")} ${node.parent}` : t("ui.workflow.graph.top_level", "top level")} ))} {graph?.edges.map((edge, index) => ( {t("ui.workflow.graph.edge", "{from} → {to} ({var})") .replace("{from}", edge.from) .replace("{to}", edge.to) .replace("{var}", edge.var)} ))} )} ); }