import { useEffect } from "react"; import { useStore } from "../store"; import { FieldPlot } from "./FieldPlot"; export function FieldPanel() { const selectedId = useStore((s) => s.selectedId); const scenarioFields = useStore((s) => s.fields); const loading = useStore((s) => s.fieldsLoading); const error = useStore((s) => s.fieldsError); const loadFields = useStore((s) => s.loadFields); const agentFields = useStore((s) => s.agentFields); const agentBusy = useStore((s) => s.agentFieldsBusy); useEffect(() => { if (selectedId) loadFields(selectedId); }, [selectedId, loadFields]); // Agent output wins once the agent has produced at least one field. const fields = agentFields ?? scenarioFields; const source: "agent" | "scenario" = agentFields ? "agent" : "scenario"; if (!selectedId && !agentFields) return null; if (loading && !agentFields) { return (
Fields

Running solver and surrogate…

); } if (error && !agentFields) { return (
Fields

Could not load fields: {error}

); } if (!fields || (!fields.solver && !fields.surrogate)) return null; // Shared color range across whichever engines are present. const tmins = [fields.solver?.t_min, fields.surrogate?.t_min].filter( (v): v is number => typeof v === "number", ); const tmaxs = [fields.solver?.t_max, fields.surrogate?.t_max].filter( (v): v is number => typeof v === "number", ); const tMin = Math.min(...tmins); const tMax = Math.max(...tmaxs); const tDelta = fields.solver && fields.surrogate ? Math.abs(fields.solver.t_max - fields.surrogate.t_max) : null; return (
Temperature fields
{source === "agent" ? agentBusy ? "from agent · updating…" : "from agent" : "from scenario"} {tDelta !== null && ( Δ Tmax {tDelta.toFixed(1)}°C )}
{fields.solver && ( )} {fields.surrogate && ( )}
); }