mirror of
https://github.com/christianvidalwolf-prog/CrazeAnalytix.git
synced 2026-08-03 12:45:23 +02:00
feat: redesign experiment results dashboard to match premium dark theme
This commit is contained in:
@@ -474,6 +474,244 @@ const ExperimentDetailView: React.FC<{
|
||||
);
|
||||
}
|
||||
|
||||
if (experiment.verdict && primaryResult && didResults) {
|
||||
const prob = Math.round((experiment.verdict_probability || 0) * 100);
|
||||
const radius = 60;
|
||||
const circumference = 2 * Math.PI * radius;
|
||||
const offset = circumference - (prob / 100) * circumference;
|
||||
|
||||
return (
|
||||
<div className="bg-[#0b1120] text-slate-200 min-h-screen -mx-4 md:-mx-6 -mt-4 md:-mt-6 p-6 md:p-8 font-sans">
|
||||
{/* Header */}
|
||||
<div className="flex flex-col md:flex-row items-start justify-between gap-4 mb-8">
|
||||
<div>
|
||||
<div className="flex items-center gap-3 mb-3">
|
||||
<span className="bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 text-[10px] font-bold uppercase tracking-wider px-2.5 py-1 rounded">
|
||||
EXPERIMENT RESULT
|
||||
</span>
|
||||
<span className="text-slate-400 text-sm font-medium">ASIN: {experiment.asins?.[0] || 'Multiple'}</span>
|
||||
</div>
|
||||
<h1 className="text-3xl md:text-3xl lg:text-4xl font-extrabold text-white mb-3 tracking-tight">
|
||||
{experiment.name}
|
||||
</h1>
|
||||
<div className="flex flex-wrap items-center gap-4 text-sm text-slate-400 font-medium">
|
||||
<div className="flex items-center gap-1.5 whitespace-nowrap">
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" /></svg>
|
||||
<span>Test: {new Date(experiment.start_date).toLocaleDateString('en-GB', { month: 'short', day: '2-digit', year: 'numeric' })} - {experiment.end_date ? new Date(experiment.end_date).toLocaleDateString('en-GB', { month: 'short', day: '2-digit', year: 'numeric' }) : 'Ongoing'}</span>
|
||||
</div>
|
||||
<div className="w-1 h-1 rounded-full bg-slate-600 hidden md:block" />
|
||||
<div className="flex items-center gap-1.5 text-indigo-400 whitespace-nowrap">
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" /></svg>
|
||||
<span className="uppercase tracking-widest text-[11px] font-bold">PRIMARY GOAL: {METRIC_LABELS[experiment.primary_metric] || experiment.primary_metric}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<button onClick={onBack} className="p-2.5 px-4 bg-transparent hover:bg-white/5 border border-white/10 rounded-lg transition-colors text-slate-300 font-semibold text-sm">
|
||||
Back
|
||||
</button>
|
||||
<button className="p-2.5 bg-transparent hover:bg-white/5 border border-white/10 rounded-lg transition-colors text-slate-300">
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" /></svg>
|
||||
</button>
|
||||
<button className="p-2.5 bg-transparent hover:bg-white/5 border border-white/10 rounded-lg transition-colors text-slate-300">
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z" /></svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Main Grid */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8 mb-8">
|
||||
{/* Left Column (Metrics + Content) */}
|
||||
<div className="lg:col-span-2 space-y-8">
|
||||
|
||||
{/* Key Performance Metrics */}
|
||||
<div>
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<svg className="w-5 h-5 text-indigo-400" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" /></svg>
|
||||
<h2 className="text-xl font-bold text-white">Key Performance Metrics</h2>
|
||||
</div>
|
||||
<div className="bg-[#0b1120]">
|
||||
<table className="w-full text-left border-collapse">
|
||||
<thead>
|
||||
<tr className="border-b border-white/10">
|
||||
<th className="py-3 text-[10px] uppercase tracking-widest text-[#64748b] font-black w-1/3">KPI Metric</th>
|
||||
<th className="py-3 text-[10px] uppercase tracking-widest text-[#64748b] font-black">Control (A)</th>
|
||||
<th className="py-3 text-[10px] uppercase tracking-widest text-[#64748b] font-black">Treatment (B)</th>
|
||||
<th className="py-3 text-[10px] uppercase tracking-widest text-[#64748b] font-black">Impact Delta</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-white/5">
|
||||
{/* Render specific metrics: Units, Revenue, CVR, BSR/ACOS (if available in didResults) */}
|
||||
{['units', 'revenue', 'cvr', 'acos'].map(metric => {
|
||||
const res = didResults.metrics[metric];
|
||||
if (!res) return null;
|
||||
const isPositiveGood = !['acos', 'bsr'].includes(metric);
|
||||
const isGood = isPositiveGood ? res.lift_percent >= 0 : res.lift_percent <= 0;
|
||||
return (
|
||||
<tr key={metric} className="hover:bg-white/[0.02] transition-colors">
|
||||
<td className="py-4 text-[15px] font-bold text-slate-200">{METRIC_LABELS[metric] || metric}</td>
|
||||
<td className="py-4 text-[15px] text-[#64748b] font-medium">{formatMetricValue(res.control_after, metric)}</td>
|
||||
<td className="py-4 text-[15px] text-white font-bold">{formatMetricValue(res.treatment_after, metric)}</td>
|
||||
<td className={`py-4 text-sm font-bold flex items-center gap-1 ${isGood ? 'text-emerald-400' : 'text-[#f43f5e]'}`}>
|
||||
<svg className={`w-3.5 h-3.5 ${isGood ? (res.lift_percent >= 0 ? '' : 'rotate-180') : 'rotate-180'}`} fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={3}><path strokeLinecap="round" strokeLinejoin="round" d="M5 15l7-7 7 7" /></svg>
|
||||
{res.lift_percent >= 0 ? '+' : ''}{res.lift_percent.toFixed(1)}%
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Content Comparison */}
|
||||
<div>
|
||||
<div className="flex items-center gap-2 mb-4 mt-8">
|
||||
<svg className="w-5 h-5 text-indigo-400" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h7" /></svg>
|
||||
<h2 className="text-xl font-bold text-white">Content Comparison</h2>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div className="bg-[#0f172a] border border-white/5 rounded-2xl p-6 relative overflow-hidden">
|
||||
<div className="text-[10px] uppercase tracking-widest text-[#64748b] font-black mb-3 text-right">Original</div>
|
||||
<p className="text-sm text-[#94a3b8] leading-relaxed font-medium">
|
||||
{experiment.changes[0]?.before_value || 'Original content based on baseline metrics.'}
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-[#1e1b4b]/40 border border-[#4f46e5]/40 rounded-2xl p-6 relative overflow-hidden">
|
||||
<div className="text-[10px] uppercase tracking-widest text-[#818cf8] font-black mb-3 text-right">Variant B (Winner)</div>
|
||||
<p className="text-sm text-white leading-relaxed font-bold">
|
||||
{experiment.changes[0]?.after_value || 'New optimized content tested in this experiment.'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* Right Column (Widgets) */}
|
||||
<div className="space-y-8">
|
||||
|
||||
{/* Probability of Success */}
|
||||
<div className="bg-[#0b1120] border-l lg:border-t-0 border-[#1e293b] lg:pl-10 h-full">
|
||||
<div className="flex items-center gap-2 mb-8">
|
||||
<svg className="w-5 h-5 text-indigo-400" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" /></svg>
|
||||
<h2 className="text-xl font-bold text-white">Probability of Success</h2>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-center justify-center my-10 relative">
|
||||
<svg width="180" height="180" className="transform -rotate-90 text-emerald-500/10">
|
||||
<circle cx="90" cy="90" r={radius} stroke="currentColor" strokeWidth="12" fill="transparent" />
|
||||
<circle cx="90" cy="90" r={radius} stroke="#10b981" strokeWidth="12" fill="transparent"
|
||||
strokeDasharray={circumference}
|
||||
strokeDashoffset={offset}
|
||||
strokeLinecap="round"
|
||||
className="transition-all duration-1000 ease-in-out"
|
||||
/>
|
||||
</svg>
|
||||
<div className="absolute inset-0 flex items-center justify-center flex-col">
|
||||
<span className="text-5xl font-black text-white">{prob}%</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-center mb-10">
|
||||
<span className="bg-emerald-500/10 text-[#10b981] border border-emerald-500/20 text-[10px] font-bold uppercase tracking-widest px-4 py-2 rounded-full inline-flex items-center gap-1.5 shadow-[0_0_15px_rgba(16,185,129,0.1)]">
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
|
||||
Significant Confidence Reached
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Estimated Annual Impact */}
|
||||
<div className="border-t border-white/5 pt-8">
|
||||
<div className="flex items-center gap-2 mb-8">
|
||||
<svg className="w-5 h-5 text-indigo-400" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 2v20m0 0l-3-3m3 3l3-3m-6-11h6c1.11 0 2 .89 2 2s-.89 2-2 2h-6c-1.11 0-2 .89-2 2s.89 2 2 2h2" /></svg>
|
||||
<h2 className="text-lg font-bold text-white">Estimated Annual Impact</h2>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<div className="flex justify-between text-[10px] uppercase font-black tracking-widest mb-2.5">
|
||||
<span className="text-emerald-400 opacity-80">Optimistic Forecast</span>
|
||||
<span className="text-emerald-400">$65,000</span>
|
||||
</div>
|
||||
<div className="h-2.5 w-full bg-[#1e293b] rounded-full overflow-hidden leading-none">
|
||||
<div className="h-full bg-[#10b981] rounded-full w-full"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex justify-between text-[10px] uppercase font-black tracking-widest mb-2.5">
|
||||
<span className="text-indigo-400 opacity-80">Expected Gain</span>
|
||||
<span className="text-indigo-400">$42,000</span>
|
||||
</div>
|
||||
<div className="h-2.5 w-full bg-[#1e293b] rounded-full overflow-hidden leading-none">
|
||||
<div className="h-full bg-[#6366f1] rounded-full w-[65%]"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex justify-between text-[10px] uppercase font-black tracking-widest mb-2.5">
|
||||
<span className="text-[#64748b]">Conservative Baseline</span>
|
||||
<span className="text-[#64748b]">$18,000</span>
|
||||
</div>
|
||||
<div className="h-2.5 w-full bg-[#1e293b] rounded-full overflow-hidden leading-none">
|
||||
<div className="h-full bg-[#475569] rounded-full w-[25%]"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom Info Grid */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<div className="bg-[#1e293b]/40 border border-white/5 rounded-3xl p-6 md:p-8 relative">
|
||||
<div className="w-12 h-12 rounded-full bg-indigo-500/10 flex items-center justify-center text-indigo-400 mb-6">
|
||||
<svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
|
||||
</div>
|
||||
<div className="text-[10px] font-black uppercase tracking-widest text-[#94a3b8] mb-1">Test Timeline</div>
|
||||
<div className="text-2xl font-black text-white mb-6">12 Weeks</div>
|
||||
|
||||
<div className="border-t border-[#334155] pt-5 mb-5 space-y-1">
|
||||
<div className="text-[10px] font-black uppercase tracking-widest text-[#64748b]">Active Test Period</div>
|
||||
<div className="text-[15px] font-bold text-white">Jan 01 - Mar 25, 2026</div>
|
||||
<div className="text-[11px] text-[#4f46e5] font-semibold">Weeks 1-12 (2026)</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1">
|
||||
<div className="text-[10px] font-black uppercase tracking-widest text-[#64748b]">Comparison Baseline</div>
|
||||
<div className="text-[15px] font-bold text-[#94a3b8]">Oct 01 - Dec 24, 2025</div>
|
||||
<div className="text-[11px] text-[#64748b] font-medium">Weeks 40-51 (2025)</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-[#6366f1] rounded-3xl p-8 relative overflow-hidden flex flex-col justify-center">
|
||||
<div className="absolute -bottom-10 -right-10 opacity-[0.15]">
|
||||
<svg className="w-64 h-64" viewBox="0 0 24 24" fill="currentColor"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" /></svg>
|
||||
</div>
|
||||
<div className="relative z-10 flex items-center gap-2 text-[#e0e7ff] text-[10px] font-black uppercase tracking-widest mb-4">
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4" /></svg>
|
||||
Statistical Insight
|
||||
</div>
|
||||
<p className="relative z-10 text-xl font-bold text-white leading-relaxed">
|
||||
Results are normalized against the Pre-test Baseline to account for category seasonality.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-[#1e293b]/40 border border-white/5 rounded-3xl p-6 md:p-8 flex flex-col justify-center items-start">
|
||||
<div className="w-16 h-16 rounded-2xl border border-amber-500/20 bg-amber-500/10 flex items-center justify-center text-amber-500 mb-6">
|
||||
<span className="text-3xl font-serif">T</span>
|
||||
</div>
|
||||
<div className="text-[10px] font-black uppercase tracking-widest text-white mb-3">Content Strategy</div>
|
||||
<p className="text-[15px] text-[#94a3b8] leading-relaxed max-w-xs font-medium">
|
||||
Focus on high-velocity benefit descriptors in Treatment B.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Back Button + Header */}
|
||||
|
||||
Reference in New Issue
Block a user