import { useState } from "react"; import { Check, HelpCircle, X } from "lucide-react"; import type { GatedResult } from "../types"; const BUTTONS = [ { label: "Approve", human: "APPROVE", cls: "bg-emerald-600 hover:bg-emerald-700", Icon: Check }, { label: "Reject", human: "REJECT", cls: "bg-rose-600 hover:bg-rose-700", Icon: X }, { label: "Request info", human: "ESCALATE", cls: "bg-amber-500 hover:bg-amber-600", Icon: HelpCircle }, ]; const MOD_KEY = "amana.moderator"; export function HumanControls({ result, onDecide, }: { result: GatedResult; onDecide: (human: string, moderator: string, reason: string) => Promise; }) { const [moderator, setModerator] = useState(() => localStorage.getItem(MOD_KEY) ?? ""); const [reason, setReason] = useState(""); const [msg, setMsg] = useState<{ kind: "ok" | "warn"; text: string } | null>(null); const [busy, setBusy] = useState(false); const aiRec = result.decision.recommendation; const click = async (human: string) => { const name = moderator.trim(); if (!name) { setMsg({ kind: "warn", text: "Add your name first — a human owns every decision." }); return; } const isOverride = human !== aiRec; if (isOverride && !reason.trim()) { setMsg({ kind: "warn", text: `Overriding the AI's ${aiRec} with ${human} needs a written reason.` }); return; } setBusy(true); setMsg(null); try { await onDecide(human, name, reason.trim()); localStorage.setItem(MOD_KEY, name); setMsg({ kind: "ok", text: isOverride ? `Recorded — ${name} overrode the AI's ${aiRec} (reason logged).` : `Recorded: ${human} by ${name} (agreed with the AI).`, }); setReason(""); } catch (e) { setMsg({ kind: "warn", text: (e as Error).message }); } finally { setBusy(false); } }; return (
Your decision — final; the AI does not decide
setModerator(e.target.value)} placeholder="Your name (recorded with the decision)" className="w-full text-sm border border-line rounded-lg px-3 py-2 bg-surface text-body focus:outline-none focus:ring-2 focus:ring-accent/40 focus:border-accent" />