/** * SummaryBar — top bar showing stats, overall confidence meter, and Finalize button. * Finalize is disabled until all flagged rules are actioned. */ import React, { useMemo } from 'react' function Stat({ label, value, color = 'text-slate-200' }) { return (
{value}
{label}
) } /** Animated SVG arc ring showing 0-100% confidence */ function ConfidenceRing({ score }) { const pct = Math.round((score ?? 0) * 100) const radius = 28 const circumference = 2 * Math.PI * radius const filled = (pct / 100) * circumference const color = pct >= 90 ? '#34d399' // emerald : pct >= 70 ? '#fbbf24' // amber : '#f87171' // red const label = pct >= 90 ? 'High Confidence' : pct >= 70 ? 'Medium — Review Flags' : 'Low — Do Not Finalize' return (
{pct}%
Policy Confidence
{label}
) } function GraphIcon({ className = 'w-4 h-4' }) { return ( ) } export default function SummaryBar({ rules, onFinalize, finalizing, onFlaggedClick, onGraphClick, graphPanelOpen, fallbackActive }) { const total = rules.length const flagged = rules.filter( (r) => r.confidence_score < 0.9 || r.conflict_with?.length > 0 ).length const resolved = rules.filter((r) => ['accepted', 'modified', 'kept_original'].includes(r.review_status) ).length const lowConfidence = rules.filter((r) => r.confidence_score < 0.7).length const unresolvedFlags = rules.filter( (r) => (r.confidence_score < 0.9 || r.conflict_with?.length > 0) && !['accepted', 'modified', 'kept_original'].includes(r.review_status) ).length const avgConfidence = useMemo(() => { if (!rules.length) return 0 const sum = rules.reduce((acc, r) => { let score = r.confidence_score ?? 0 const isFlagged = r.confidence_score < 0.9 || r.conflict_with?.length > 0 const isResolved = ['accepted', 'modified', 'kept_original'].includes(r.review_status) if (isFlagged && !isResolved) score = score * 0.5 return acc + score }, 0) return sum / rules.length }, [rules]) const allFlaggedResolved = unresolvedFlags === 0 const canFinalize = allFlaggedResolved && total > 0 return (
{fallbackActive && (
Fallback LLM Active
)}
PolicyPilot / Rule Review
0 ? 'text-amber-400' : 'text-slate-400'} /> 0 ? 'text-emerald-400' : 'text-slate-400'} /> 0 ? 'text-red-400' : 'text-slate-400'} />
{/* Rule Graph — left of Next Flag, flows purple, unlocks when all flags resolved */} {/* Next Flag */} {/* Finalize */}
) }