gatepass / src /components /DharmaRadar.tsx
rb125
Initial frontend deploy
4c62137
Raw
History Blame Contribute Delete
2.61 kB
"use client";
import { motion } from "framer-motion";
import type { AGTScores } from "@/lib/types";
import { scoreColor } from "@/components/TrustGauge";
export function DharmaRadar({ scores }: { scores: AGTScores }) {
const dims = [
{ key: "truthfulness", label: "TRUTH", val: scores.truthfulness },
{ key: "non_harm", label: "SAFETY", val: scores.non_harm },
{ key: "harmony", label: "SYNERGY", val: scores.harmony },
{ key: "responsibility", label: "AGENCY", val: scores.responsibility },
];
const size = 300;
const cx = size / 2, cy = size / 2, r = 80;
const n = dims.length;
const toXY = (i: number, val: number) => {
const angle = (Math.PI * 2 * i) / n - Math.PI / 2;
const dist = (val / 10) * r;
return { x: cx + dist * Math.cos(angle), y: cy + dist * Math.sin(angle) };
};
const labelXY = (i: number) => {
const angle = (Math.PI * 2 * i) / n - Math.PI / 2;
const dist = r + 40;
return { x: cx + dist * Math.cos(angle), y: cy + dist * Math.sin(angle) };
};
const polygon = dims.map((_, i) => {
const p = toXY(i, dims[i].val);
return `${p.x},${p.y}`;
}).join(" ");
return (
<div className="relative flex justify-center">
<svg viewBox={`0 0 ${size} ${size}`} className="w-full max-w-[280px] overflow-visible">
{/* Subtle Grid */}
{[2.5, 5, 7.5, 10].map((v) => (
<polygon
key={v}
points={Array.from({ length: n }, (_, i) => {
const p = toXY(i, v);
return `${p.x},${p.y}`;
}).join(" ")}
fill="none" stroke="rgba(255,255,255,0.03)" strokeWidth="0.5"
/>
))}
{/* Data area */}
<motion.polygon
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 1 }}
points={polygon}
fill="rgba(255, 255, 255, 0.05)"
stroke="rgba(255, 255, 255, 0.2)"
strokeWidth="1"
/>
{/* Labels */}
{dims.map((d, i) => {
const l = labelXY(i);
return (
<g key={`label-${d.key}`}>
<text x={l.x} y={l.y} textAnchor="middle" dominantBaseline="central" fill="var(--text-dim)" fontSize="8" fontWeight="500" className="tracking-[0.1em]">
{d.label}
</text>
<text x={l.x} y={l.y + 12} textAnchor="middle" dominantBaseline="central" fill="white" fontSize="11" fontWeight="300">
{d.val.toFixed(1)}
</text>
</g>
);
})}
</svg>
</div>
);
}