refactor: migrate page components to Design System v4
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -144,7 +144,7 @@ export default function FlowPilotAnalyticsPage() {
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-[60vh]">
|
||||
<Loader2 size={24} className="animate-spin text-muted-foreground" />
|
||||
<Loader2 size={24} className="animate-spin text-[#848b9b]" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -152,7 +152,7 @@ export default function FlowPilotAnalyticsPage() {
|
||||
if (!dashboard) {
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-[60vh]">
|
||||
<p className="text-sm text-muted-foreground">Failed to load analytics</p>
|
||||
<p className="text-sm text-[#848b9b]">Failed to load analytics</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -165,21 +165,21 @@ export default function FlowPilotAnalyticsPage() {
|
||||
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
<span title="FlowPilot Analytics">
|
||||
<BarChart3 size={24} className="text-foreground" />
|
||||
<BarChart3 size={24} className="text-[#e2e5eb]" />
|
||||
</span>
|
||||
<h1 className="text-xl sm:text-2xl font-bold font-heading text-foreground">FlowPilot Analytics</h1>
|
||||
<h1 className="text-xl sm:text-2xl font-bold font-heading text-[#e2e5eb]">FlowPilot Analytics</h1>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<Link
|
||||
to="/analytics"
|
||||
className="text-sm text-muted-foreground hover:text-foreground transition-colors"
|
||||
className="text-sm text-[#848b9b] hover:text-[#e2e5eb] transition-colors"
|
||||
>
|
||||
Team Analytics
|
||||
</Link>
|
||||
<select
|
||||
value={period}
|
||||
onChange={(e) => setPeriod(e.target.value)}
|
||||
className="rounded-lg border border-border bg-card px-3 py-1.5 text-sm text-foreground focus:outline-hidden focus:ring-1 focus:ring-primary/20 [&>option]:bg-[#1a1c21] [&>option]:text-foreground"
|
||||
className="rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-1.5 text-sm text-[#e2e5eb] focus:outline-hidden focus:ring-1 focus:ring-primary/20 [&>option]:bg-[#1a1c21] [&>option]:text-[#e2e5eb]"
|
||||
>
|
||||
{PERIOD_OPTIONS.map((opt) => (
|
||||
<option key={opt.value} value={opt.value}>{opt.label}</option>
|
||||
@@ -189,7 +189,7 @@ export default function FlowPilotAnalyticsPage() {
|
||||
</div>
|
||||
|
||||
{/* Tab bar */}
|
||||
<div className="flex gap-1 border-b border-border overflow-x-auto">
|
||||
<div className="flex gap-1 border-b border-[#1e2130] overflow-x-auto">
|
||||
{TABS.map((tab) => (
|
||||
<button
|
||||
key={tab.id}
|
||||
@@ -197,8 +197,8 @@ export default function FlowPilotAnalyticsPage() {
|
||||
className={cn(
|
||||
'px-4 py-2 text-sm transition-colors',
|
||||
activeTab === tab.id
|
||||
? 'border-b-2 border-primary text-foreground font-medium'
|
||||
: 'text-muted-foreground hover:text-foreground'
|
||||
? 'border-b-2 border-primary text-[#e2e5eb] font-medium'
|
||||
: 'text-[#848b9b] hover:text-[#e2e5eb]'
|
||||
)}
|
||||
>
|
||||
{tab.label}
|
||||
@@ -246,8 +246,8 @@ export default function FlowPilotAnalyticsPage() {
|
||||
{/* Second row — Charts */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||
{/* MTTR Trend */}
|
||||
<div className="glass-card-static p-3 sm:p-5">
|
||||
<h3 className="font-heading text-sm font-semibold text-foreground mb-4">
|
||||
<div className="card-flat p-3 sm:p-5">
|
||||
<h3 className="font-heading text-sm font-semibold text-[#e2e5eb] mb-4">
|
||||
MTTR Trend
|
||||
</h3>
|
||||
{dashboard.mttr_trend.length > 0 ? (
|
||||
@@ -284,15 +284,15 @@ export default function FlowPilotAnalyticsPage() {
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
) : (
|
||||
<div className="flex items-center justify-center h-[220px] text-sm text-muted-foreground">
|
||||
<div className="flex items-center justify-center h-[220px] text-sm text-[#848b9b]">
|
||||
No data for this period
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Domain Breakdown */}
|
||||
<div className="glass-card-static p-3 sm:p-5">
|
||||
<h3 className="font-heading text-sm font-semibold text-foreground mb-4">
|
||||
<div className="card-flat p-3 sm:p-5">
|
||||
<h3 className="font-heading text-sm font-semibold text-[#e2e5eb] mb-4">
|
||||
Sessions by Domain
|
||||
</h3>
|
||||
{dashboard.sessions_by_domain.length > 0 ? (
|
||||
@@ -315,7 +315,7 @@ export default function FlowPilotAnalyticsPage() {
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
) : (
|
||||
<div className="flex items-center justify-center h-[220px] text-sm text-muted-foreground">
|
||||
<div className="flex items-center justify-center h-[220px] text-sm text-[#848b9b]">
|
||||
No domain data
|
||||
</div>
|
||||
)}
|
||||
@@ -325,8 +325,8 @@ export default function FlowPilotAnalyticsPage() {
|
||||
{/* Third row — Confidence + Knowledge Coverage */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||
{/* Confidence Breakdown */}
|
||||
<div className="glass-card-static p-3 sm:p-5">
|
||||
<h3 className="font-heading text-sm font-semibold text-foreground mb-4">
|
||||
<div className="card-flat p-3 sm:p-5">
|
||||
<h3 className="font-heading text-sm font-semibold text-[#e2e5eb] mb-4">
|
||||
Confidence Tiers
|
||||
</h3>
|
||||
<div className="space-y-3">
|
||||
@@ -355,32 +355,32 @@ export default function FlowPilotAnalyticsPage() {
|
||||
</div>
|
||||
|
||||
{/* Knowledge Coverage */}
|
||||
<div className="glass-card-static p-3 sm:p-5">
|
||||
<h3 className="font-heading text-sm font-semibold text-foreground mb-4">
|
||||
<div className="card-flat p-3 sm:p-5">
|
||||
<h3 className="font-heading text-sm font-semibold text-[#e2e5eb] mb-4">
|
||||
Knowledge Coverage
|
||||
</h3>
|
||||
<div className="grid grid-cols-2 gap-3 mb-4">
|
||||
<div className="rounded-lg bg-card/50 p-3">
|
||||
<p className="text-xs text-muted-foreground">Total Flows</p>
|
||||
<p className="text-lg font-semibold text-foreground">{dashboard.knowledge_coverage.total_flows}</p>
|
||||
<div className="rounded-lg bg-[#14161d]/50 p-3">
|
||||
<p className="text-xs text-[#848b9b]">Total Flows</p>
|
||||
<p className="text-lg font-semibold text-[#e2e5eb]">{dashboard.knowledge_coverage.total_flows}</p>
|
||||
</div>
|
||||
<div className="rounded-lg bg-card/50 p-3">
|
||||
<p className="text-xs text-muted-foreground">AI-Generated</p>
|
||||
<p className="text-lg font-semibold text-gradient-brand">{dashboard.knowledge_coverage.ai_generated_flows}</p>
|
||||
<div className="rounded-lg bg-[#14161d]/50 p-3">
|
||||
<p className="text-xs text-[#848b9b]">AI-Generated</p>
|
||||
<p className="text-lg font-semibold text-[#67e8f9]">{dashboard.knowledge_coverage.ai_generated_flows}</p>
|
||||
</div>
|
||||
<div className="rounded-lg bg-card/50 p-3">
|
||||
<p className="text-xs text-muted-foreground">Pending Review</p>
|
||||
<div className="rounded-lg bg-[#14161d]/50 p-3">
|
||||
<p className="text-xs text-[#848b9b]">Pending Review</p>
|
||||
<p className="text-lg font-semibold text-amber-400">{dashboard.knowledge_coverage.total_proposals_pending}</p>
|
||||
</div>
|
||||
<div className="rounded-lg bg-card/50 p-3">
|
||||
<p className="text-xs text-muted-foreground">Approved This Period</p>
|
||||
<div className="rounded-lg bg-[#14161d]/50 p-3">
|
||||
<p className="text-xs text-[#848b9b]">Approved This Period</p>
|
||||
<p className="text-lg font-semibold text-emerald-400">{dashboard.knowledge_coverage.proposals_approved_this_period}</p>
|
||||
</div>
|
||||
</div>
|
||||
{dashboard.knowledge_coverage.total_proposals_pending > 0 && (
|
||||
<Link
|
||||
to="/review-queue"
|
||||
className="flex items-center gap-2 text-xs text-primary hover:underline"
|
||||
className="flex items-center gap-2 text-xs text-[#22d3ee] hover:underline"
|
||||
>
|
||||
<ArrowUpRight size={12} />
|
||||
Review {dashboard.knowledge_coverage.total_proposals_pending} pending proposals
|
||||
@@ -394,7 +394,7 @@ export default function FlowPilotAnalyticsPage() {
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center gap-2 px-1">
|
||||
<AlertTriangle size={14} className="text-amber-400" />
|
||||
<h3 className="font-heading text-sm font-semibold text-foreground">
|
||||
<h3 className="font-heading text-sm font-semibold text-[#e2e5eb]">
|
||||
Knowledge Gaps ({gaps.gaps.length})
|
||||
</h3>
|
||||
</div>
|
||||
@@ -405,11 +405,11 @@ export default function FlowPilotAnalyticsPage() {
|
||||
</div>
|
||||
</div>
|
||||
) : gaps && (
|
||||
<div className="glass-card-static p-4 flex items-center gap-3">
|
||||
<div className="card-flat p-4 flex items-center gap-3">
|
||||
<CheckCircle2 size={20} className="text-emerald-400 shrink-0" />
|
||||
<div>
|
||||
<p className="text-sm text-foreground">No knowledge gaps detected</p>
|
||||
<p className="text-xs text-muted-foreground">Your flow coverage looks healthy for this period.</p>
|
||||
<p className="text-sm text-[#e2e5eb]">No knowledge gaps detected</p>
|
||||
<p className="text-xs text-[#848b9b]">Your flow coverage looks healthy for this period.</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -422,7 +422,7 @@ export default function FlowPilotAnalyticsPage() {
|
||||
<ErrorRetry label="coverage data" onRetry={() => { setCoverageError(false); coveragePeriodRef.current = null; setRetryKey((k) => k + 1) }} />
|
||||
) : coverageLoading ? (
|
||||
<div className="flex items-center justify-center min-h-[200px]">
|
||||
<Loader2 size={20} className="animate-spin text-muted-foreground" />
|
||||
<Loader2 size={20} className="animate-spin text-[#848b9b]" />
|
||||
</div>
|
||||
) : coverageData ? (
|
||||
<CoverageHeatmap data={coverageData} />
|
||||
@@ -436,7 +436,7 @@ export default function FlowPilotAnalyticsPage() {
|
||||
<ErrorRetry label="flow quality data" onRetry={() => { setQualityError(false); qualityPeriodRef.current = null; setRetryKey((k) => k + 1) }} />
|
||||
) : qualityLoading ? (
|
||||
<div className="flex items-center justify-center min-h-[200px]">
|
||||
<Loader2 size={20} className="animate-spin text-muted-foreground" />
|
||||
<Loader2 size={20} className="animate-spin text-[#848b9b]" />
|
||||
</div>
|
||||
) : qualityData ? (
|
||||
<FlowQualityTable data={qualityData} />
|
||||
@@ -450,7 +450,7 @@ export default function FlowPilotAnalyticsPage() {
|
||||
<ErrorRetry label="PSA metrics" onRetry={() => { setPsaError(false); psaPeriodRef.current = null; setRetryKey((k) => k + 1) }} />
|
||||
) : psaLoading ? (
|
||||
<div className="flex items-center justify-center min-h-[200px]">
|
||||
<Loader2 size={20} className="animate-spin text-muted-foreground" />
|
||||
<Loader2 size={20} className="animate-spin text-[#848b9b]" />
|
||||
</div>
|
||||
) : psaData ? (
|
||||
<PsaMetricsPanel data={psaData} />
|
||||
@@ -475,7 +475,7 @@ function MetricCard({
|
||||
iconColor: string
|
||||
}) {
|
||||
return (
|
||||
<div className="glass-card-static p-3 sm:p-4">
|
||||
<div className="card-flat p-3 sm:p-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<span
|
||||
className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg"
|
||||
@@ -484,8 +484,8 @@ function MetricCard({
|
||||
<Icon size={16} style={{ color: iconColor }} />
|
||||
</span>
|
||||
<div>
|
||||
<p className="font-label text-[0.5625rem] uppercase tracking-wider text-[#5a6170]">{label}</p>
|
||||
<p className="text-lg font-semibold text-foreground">{value}</p>
|
||||
<p className="font-sans text-xs text-[0.5625rem] uppercase tracking-wider text-[#5a6170]">{label}</p>
|
||||
<p className="text-lg font-semibold text-[#e2e5eb]">{value}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -509,12 +509,12 @@ function ConfidenceTierRow({
|
||||
return (
|
||||
<div className="space-y-1">
|
||||
<div className="flex items-center justify-between text-xs">
|
||||
<span className="text-foreground font-medium">{label}</span>
|
||||
<span className="text-muted-foreground">
|
||||
<span className="text-[#e2e5eb] font-medium">{label}</span>
|
||||
<span className="text-[#848b9b]">
|
||||
{count} sessions · {rate.toFixed(1)}% resolved
|
||||
</span>
|
||||
</div>
|
||||
<div className="h-2 rounded-full bg-card/80 overflow-hidden">
|
||||
<div className="h-2 rounded-full bg-[#14161d]/80 overflow-hidden">
|
||||
<div
|
||||
className="h-full rounded-full transition-all"
|
||||
style={{ width: `${pct}%`, background: color }}
|
||||
@@ -526,12 +526,12 @@ function ConfidenceTierRow({
|
||||
|
||||
function ErrorRetry({ label, onRetry }: { label: string; onRetry: () => void }) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center py-12 text-muted-foreground">
|
||||
<div className="flex flex-col items-center justify-center py-12 text-[#848b9b]">
|
||||
<AlertTriangle size={24} className="mb-2 text-amber-400" />
|
||||
<p className="text-sm mb-3">Failed to load {label}</p>
|
||||
<button
|
||||
onClick={onRetry}
|
||||
className="inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-[10px] bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-foreground hover:border-[rgba(255,255,255,0.12)] transition-colors"
|
||||
className="inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)] transition-colors"
|
||||
>
|
||||
<RotateCcw size={12} />
|
||||
Retry
|
||||
@@ -543,17 +543,17 @@ function ErrorRetry({ label, onRetry }: { label: string; onRetry: () => void })
|
||||
function GapCard({ gap }: { gap: KnowledgeGap }) {
|
||||
const severityStyle = SEVERITY_STYLES[gap.severity as keyof typeof SEVERITY_STYLES] ?? SEVERITY_STYLES.low
|
||||
return (
|
||||
<div className="glass-card-static p-4 space-y-2">
|
||||
<div className="card-flat p-4 space-y-2">
|
||||
<div className="flex items-start justify-between gap-2">
|
||||
<p className="text-sm font-semibold text-foreground">{gap.title}</p>
|
||||
<span className={`shrink-0 rounded-md border px-1.5 py-0.5 font-label text-[0.5625rem] uppercase tracking-wider ${severityStyle}`}>
|
||||
<p className="text-sm font-semibold text-[#e2e5eb]">{gap.title}</p>
|
||||
<span className={`shrink-0 rounded-md border px-1.5 py-0.5 font-sans text-xs text-[0.5625rem] uppercase tracking-wider ${severityStyle}`}>
|
||||
{gap.severity}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">{gap.description}</p>
|
||||
<p className="text-xs text-[#848b9b]">{gap.description}</p>
|
||||
<div className="flex items-start gap-1.5 pt-1">
|
||||
<Lightbulb size={12} className="text-primary shrink-0 mt-0.5" />
|
||||
<p className="text-xs text-primary">{gap.suggested_action}</p>
|
||||
<Lightbulb size={12} className="text-[#22d3ee] shrink-0 mt-0.5" />
|
||||
<p className="text-xs text-[#22d3ee]">{gap.suggested_action}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user