"use client"; import { useMemo, useState } from "react"; import { useDiagramStore } from "@/store/diagramStore"; import { buildDofCoach, type CoachSeverity } from "@/lib/dofCoach"; import type { DofBalance } from "@/lib/dofLedger"; import type { EntropykNodeData } from "@/lib/configBuilder"; import type { Node } from "@xyflow/react"; import ApiHealthIndicator from "@/components/shell/ApiHealthIndicator"; import { AlertTriangle, CheckCircle2, ChevronUp, Equal, Lightbulb, MinusCircle, Sparkles, } from "lucide-react"; function balanceStyle(balance: DofBalance): { bg: string; fg: string; border: string; Icon: typeof CheckCircle2; } { switch (balance) { case "balanced": return { bg: "bg-emerald-50", fg: "text-emerald-800", border: "border-emerald-200", Icon: CheckCircle2, }; case "over-constrained": return { bg: "bg-red-50", fg: "text-red-800", border: "border-red-200", Icon: AlertTriangle, }; case "under-constrained": return { bg: "bg-amber-50", fg: "text-amber-900", border: "border-amber-200", Icon: MinusCircle, }; default: return { bg: "bg-[var(--chrome-2)]", fg: "text-[var(--ink-dim)]", border: "border-[var(--line)]", Icon: Equal, }; } } function tipIcon(sev: CoachSeverity) { switch (sev) { case "ok": return ; case "block": return ; case "warn": return ; default: return ; } } export default function DofStatusBar() { const nodes = useDiagramStore((s) => s.nodes) as Node[]; const edges = useDiagramStore((s) => s.edges); const [open, setOpen] = useState(false); const [tab, setTab] = useState<"guide" | "ledger">("guide"); const coach = useMemo(() => buildDofCoach(nodes, edges), [nodes, edges]); const { ledger } = coach; const style = balanceStyle(ledger.balance); const Icon = style.Icon; return (
{open && (
Estimation UI — le CLI valide le ledger Rust exact
{tab === "guide" ? ( <>

Chaque Fixed doit libérer une inconnue ailleurs (Free P, actionneur, pression émergente…). Suit les étapes dans l’ordre.

    {coach.tips.map((tip, i) => (
  1. {String(i + 1).padStart(2, "0")} {tipIcon(tip.severity)}
    {tip.title}
    {tip.action}
    {tip.focus && (
    → {tip.focus}
    )}
  2. ))}
) : ( <> {ledger.diagnostics.length > 0 && (
    {ledger.diagnostics.slice(0, 12).map((d, i) => (
  • ! {d}
  • ))}
)}
{ledger.components.map((c) => (
{c.name} {c.nEquations} eq
{c.type}
{c.roles.join(" · ")}
))}
)}
)}
); }