mirror of
https://github.com/christianvidalwolf-prog/CrazeAnalytix.git
synced 2026-08-03 13:35:24 +02:00
feat: enable custom baseline periods for Experiments to solve seasonality
This commit is contained in:
@@ -555,10 +555,9 @@ const ExperimentDetailView: React.FC<{
|
||||
{/* Confidence bar */}
|
||||
<div className="mt-4 h-1.5 bg-slate-700/50 rounded-full overflow-hidden">
|
||||
<div
|
||||
className={`h-full rounded-full transition-all duration-500 ${
|
||||
experiment.verdict === 'winner' ? 'bg-emerald-400' :
|
||||
className={`h-full rounded-full transition-all duration-500 ${experiment.verdict === 'winner' ? 'bg-emerald-400' :
|
||||
experiment.verdict === 'loser' ? 'bg-red-400' : 'bg-slate-400'
|
||||
}`}
|
||||
}`}
|
||||
style={{ width: `${Math.round((experiment.verdict_probability || 0) * 100)}%` }}
|
||||
/>
|
||||
</div>
|
||||
@@ -577,6 +576,17 @@ const ExperimentDetailView: React.FC<{
|
||||
{/* Timeline */}
|
||||
<Card title="Timeline">
|
||||
<div className="space-y-3">
|
||||
{experiment.baseline_start_date && experiment.baseline_end_date && (
|
||||
<div className="flex flex-col mb-3 pb-3 border-b border-slate-700/50">
|
||||
<span className="text-xs font-semibold text-indigo-400 mb-1 uppercase tracking-wider">Baseline Period</span>
|
||||
<span className="text-white text-sm">
|
||||
{new Date(experiment.baseline_start_date).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' })}
|
||||
{' — '}
|
||||
{new Date(experiment.baseline_end_date).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' })}
|
||||
</span>
|
||||
<span className="text-[10px] text-slate-500 mt-0.5">Custom Seasonal Comparison</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex justify-between text-sm">
|
||||
<span className="text-slate-400">Start</span>
|
||||
<span className="text-white font-medium">{new Date(experiment.start_date).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' })}</span>
|
||||
@@ -721,9 +731,8 @@ const ExperimentDetailView: React.FC<{
|
||||
return (
|
||||
<div
|
||||
key={metric}
|
||||
className={`p-4 rounded-xl border transition-colors ${
|
||||
isPrimary ? 'border-indigo-500/40 bg-indigo-500/5' : 'border-slate-800 bg-slate-900/50'
|
||||
}`}
|
||||
className={`p-4 rounded-xl border transition-colors ${isPrimary ? 'border-indigo-500/40 bg-indigo-500/5' : 'border-slate-800 bg-slate-900/50'
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<span className="text-xs font-medium text-slate-400 uppercase tracking-wide">
|
||||
@@ -742,10 +751,9 @@ const ExperimentDetailView: React.FC<{
|
||||
<div className="mt-2 flex items-center gap-2">
|
||||
<div className="flex-1 h-1 bg-slate-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
className={`h-full rounded-full ${
|
||||
result.posterior_prob_positive >= 0.9 ? 'bg-emerald-400' :
|
||||
className={`h-full rounded-full ${result.posterior_prob_positive >= 0.9 ? 'bg-emerald-400' :
|
||||
result.posterior_prob_positive <= 0.1 ? 'bg-red-400' : 'bg-slate-400'
|
||||
}`}
|
||||
}`}
|
||||
style={{ width: `${Math.round(result.posterior_prob_positive * 100)}%` }}
|
||||
/>
|
||||
</div>
|
||||
@@ -850,6 +858,9 @@ const ExperimentCreateView: React.FC<{
|
||||
const [primaryMetric, setPrimaryMetric] = useState<ExperimentMetric>('units');
|
||||
const [startDate, setStartDate] = useState(new Date().toISOString().split('T')[0]);
|
||||
const [endDate, setEndDate] = useState('');
|
||||
const [enableCustomBaseline, setEnableCustomBaseline] = useState(false);
|
||||
const [baselineStartDate, setBaselineStartDate] = useState('');
|
||||
const [baselineEndDate, setBaselineEndDate] = useState('');
|
||||
const [treatmentAsins, setTreatmentAsins] = useState('');
|
||||
const [controlAsins, setControlAsins] = useState('');
|
||||
const [changes, setChanges] = useState<ExperimentChangeAnnotation[]>([{ field: '', before_value: '', after_value: '' }]);
|
||||
@@ -895,6 +906,8 @@ const ExperimentCreateView: React.FC<{
|
||||
marketplace,
|
||||
start_date: startDate,
|
||||
end_date: endDate || undefined,
|
||||
baseline_start_date: enableCustomBaseline && baselineStartDate ? baselineStartDate : undefined,
|
||||
baseline_end_date: enableCustomBaseline && baselineEndDate ? baselineEndDate : undefined,
|
||||
hypothesis: hypothesis.trim() || undefined,
|
||||
primary_metric: primaryMetric,
|
||||
changes: validChanges,
|
||||
@@ -1073,7 +1086,7 @@ const ExperimentCreateView: React.FC<{
|
||||
|
||||
{/* Timeline */}
|
||||
<Card title="Timeline">
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="grid grid-cols-2 gap-4 mb-6">
|
||||
<FormField label="Start Date" required>
|
||||
<input type="date" value={startDate} onChange={e => setStartDate(e.target.value)} className="input-field" />
|
||||
</FormField>
|
||||
@@ -1081,6 +1094,32 @@ const ExperimentCreateView: React.FC<{
|
||||
<input type="date" value={endDate} onChange={e => setEndDate(e.target.value)} className="input-field" />
|
||||
</FormField>
|
||||
</div>
|
||||
|
||||
<div className="border-t border-slate-700/50 pt-4">
|
||||
<label className="flex items-center gap-2 cursor-pointer mb-4">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={enableCustomBaseline}
|
||||
onChange={e => setEnableCustomBaseline(e.target.checked)}
|
||||
className="w-4 h-4 rounded-md border-slate-600 bg-slate-800 text-indigo-500 focus:ring-indigo-500/50"
|
||||
/>
|
||||
<span className="text-sm font-medium text-slate-300">Set Custom Baseline Period (Solves Seasonality)</span>
|
||||
</label>
|
||||
|
||||
{enableCustomBaseline && (
|
||||
<div className="grid grid-cols-2 gap-4 bg-indigo-500/5 p-4 rounded-xl border border-indigo-500/20">
|
||||
<div className="col-span-2 text-xs text-slate-400 mb-1">
|
||||
Instead of dynamically looking right before the start date, specify an exact previous period (like year-over-year).
|
||||
</div>
|
||||
<FormField label="Baseline Start Date">
|
||||
<input type="date" value={baselineStartDate} onChange={e => setBaselineStartDate(e.target.value)} className="input-field" />
|
||||
</FormField>
|
||||
<FormField label="Baseline End Date">
|
||||
<input type="date" value={baselineEndDate} onChange={e => setBaselineEndDate(e.target.value)} className="input-field" />
|
||||
</FormField>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Error + Submit */}
|
||||
|
||||
Reference in New Issue
Block a user