self-improving-agent / web /components /ResultCard.tsx
Zeetay
feat: Next.js frontend for hosted demo + README live-demo section
5456422
Raw
History Blame Contribute Delete
2.68 kB
import type { Output, Scores } from "@/lib/types";
const VARIANT_LABEL: Record<Output["variant_type"], string> = {
headline: "Headline",
body: "Body",
cta: "CTA",
};
// Badge / accent color by weighted average: green >=4.0, amber 2.5-4.0, red <2.5.
function band(weighted: number) {
if (weighted >= 4.0) {
return { text: "text-emerald-400", border: "border-emerald-500/40", bg: "bg-emerald-500/10", bar: "bg-emerald-400/70" };
}
if (weighted >= 2.5) {
return { text: "text-amber-400", border: "border-amber-500/40", bg: "bg-amber-500/10", bar: "bg-amber-400/70" };
}
return { text: "text-red-400", border: "border-red-500/40", bg: "bg-red-500/10", bar: "bg-red-400/70" };
}
const DIMS: { key: keyof Scores; label: string }[] = [
{ key: "hook_strength", label: "Hook" },
{ key: "brand_alignment", label: "Brand" },
{ key: "clarity", label: "Clarity" },
{ key: "conversion_intent", label: "Conv" },
];
function ScoreBar({ label, value, barClass }: { label: string; value: number; barClass: string }) {
const pct = Math.max(0, Math.min(100, (value / 5) * 100));
return (
<div className="flex items-center gap-2">
<span className="w-14 font-mono text-[10px] uppercase tracking-wider text-zinc-500">
{label}
</span>
<div className="h-1.5 flex-1 bg-ink-800">
<div className={`h-full ${barClass}`} style={{ width: `${pct}%` }} />
</div>
<span className="w-4 text-right font-mono text-[11px] tabular-nums text-zinc-400">
{value}
</span>
</div>
);
}
export function ResultCard({ output }: { output: Output }) {
const { scores } = output;
const c = band(scores.weighted_average);
return (
<div className="flex flex-col border border-ink-700 bg-ink-900">
<div className="flex items-center justify-between border-b border-ink-700 px-4 py-2.5">
<span className="font-mono text-xs uppercase tracking-wider text-zinc-400">
{VARIANT_LABEL[output.variant_type]}
</span>
<span
className={`border ${c.border} ${c.bg} ${c.text} px-2 py-0.5 font-mono text-xs tabular-nums`}
title="Weighted average score"
>
{scores.weighted_average.toFixed(2)}
</span>
</div>
<div className="flex-1 px-4 py-4">
<p className="text-sm leading-relaxed text-zinc-100">{output.content}</p>
</div>
<div className="space-y-2 border-t border-ink-700 px-4 py-3">
{DIMS.map((d) => (
<ScoreBar
key={d.key}
label={d.label}
value={Number(scores[d.key])}
barClass={c.bar}
/>
))}
</div>
</div>
);
}