refactor(web): normalize strategy profile theme surfaces

This commit is contained in:
Saravana Achu Mac 2026-05-05 21:49:36 -07:00
parent 6b2ddeb837
commit 5d0f138cd1
3 changed files with 391 additions and 469 deletions

View File

@ -95,8 +95,8 @@ Current public bundle:
## Phase 4: Remaining legacy component cleanup
- [ ] Normalize `web/src/components/TradeProfileManager.tsx`
- [ ] Normalize `web/src/components/StrategyWizard.tsx`
- [x] Normalize `web/src/components/TradeProfileManager.tsx`
- [x] Normalize `web/src/components/StrategyWizard.tsx`
- [ ] Normalize `web/src/tabs/ReconciliationAuditPanel.tsx`
- [ ] Normalize `web/src/components/GlobalConfigManager.tsx`
- [ ] Normalize `web/src/components/EntryForm.tsx`

View File

@ -21,6 +21,9 @@ import { useAuth } from './AuthContext';
import { BacktestRunnerPanel } from '../backtest/components/BacktestRunnerPanel';
import { useBacktestFeatureGate } from '../backtest/useBacktestFeatureGate';
import { createTradeProfile, updateTradeProfile } from '../lib/profileApi';
import { Button } from './ui/button';
import { Card } from './ui/card';
import { Input } from './ui/input';
interface WizardState {
step: number;
@ -43,6 +46,13 @@ const SESSION_MAP = {
'Asia only': 'TOK,SYD'
};
const sectionTitleClass = 'mb-2 text-2xl font-bold text-[var(--foreground)]';
const sectionDescriptionClass = 'text-sm text-[var(--muted-foreground)]';
const labelClass = 'text-xs font-bold uppercase tracking-widest text-[var(--muted-foreground)]';
const optionBaseClass = 'w-full rounded-2xl border-2 p-5 text-left transition-all';
const optionSelectedClass = 'border-[var(--accent)] bg-[var(--accent-soft)]';
const optionIdleClass = 'border-[var(--border)] bg-[var(--card)] hover:border-[var(--border-strong)]';
const buildStrategyConfig = (state: WizardState) => ({
rules: [
{ ruleId: 'RiskManagementRule', enabled: true, ruleType: 'mandatory', params: {} },
@ -148,16 +158,16 @@ export const StrategyWizard: React.FC<{
};
return (
<div className="max-w-3xl mx-auto py-8 px-4">
{/* Progress Bar */}
<div className="flex justify-between mb-12 relative">
<div className="absolute top-1/2 left-0 w-full h-0.5 bg-zinc-800 -translate-y-1/2 z-0" />
{[1, 2, 3, 4, 5].map(i => (
<div
key={i}
className={`relative z-10 w-10 h-10 rounded-full flex items-center justify-center font-bold text-sm transition-all duration-300 ${state.step >= i ? 'bg-[#00ff88] text-black scale-110' : 'bg-zinc-800 text-zinc-500 border border-zinc-700'
}`}
>
<div className="mx-auto max-w-3xl px-4 py-8">
{/* Progress Bar */}
<div className="relative mb-12 flex justify-between">
<div className="absolute left-0 top-1/2 z-0 h-0.5 w-full -translate-y-1/2 bg-[var(--border)]" />
{[1, 2, 3, 4, 5].map(i => (
<div
key={i}
className={`relative z-10 flex h-10 w-10 items-center justify-center rounded-full text-sm font-bold transition-all duration-300 ${state.step >= i ? 'scale-110 bg-[var(--primary)] text-[var(--primary-foreground)]' : 'border border-[var(--border)] bg-[var(--card)] text-[var(--muted-foreground)]'
}`}
>
{state.step > i ? <CheckCircle2 size={18} /> : i}
</div>
))}
@ -166,9 +176,9 @@ export const StrategyWizard: React.FC<{
{/* Step 1: Risk Style */}
{state.step === 1 && (
<div className="space-y-6 animate-in fade-in slide-in-from-bottom-4 duration-500">
<div className="text-center mb-8">
<h2 className="text-2xl font-bold text-white mb-2">How should this bot behave?</h2>
<p className="text-zinc-400 text-sm">Select a pre-configured risk style. High-frequency options seek more opportunities but require more flexibility.</p>
<div className="mb-8 text-center">
<h2 className={sectionTitleClass}>How should this bot behave?</h2>
<p className={sectionDescriptionClass}>Select a pre-configured risk style. High-frequency options seek more opportunities but require more flexibility.</p>
</div>
<div className="grid grid-cols-1 gap-4">
{RISK_STYLE_TEMPLATES.map(style => {
@ -178,27 +188,27 @@ export const StrategyWizard: React.FC<{
<button
disabled={isLocked}
onClick={() => setState({ ...state, riskStyle: style })}
className={`w-full p-5 rounded-2xl border-2 text-left transition-all ${isLocked ? 'opacity-40 cursor-not-allowed grayscale' : 'hover:scale-[1.01] active:scale-[0.99]'
} ${state.riskStyle?.id === style.id
? 'border-[#00ff88] bg-[#00ff88]/5'
: 'border-white/5 bg-zinc-900/50 hover:border-white/10'
}`}
className={`${optionBaseClass} ${isLocked ? 'cursor-not-allowed opacity-40 grayscale' : 'hover:scale-[1.01] active:scale-[0.99]'
} ${state.riskStyle?.id === style.id
? optionSelectedClass
: optionIdleClass
}`}
>
<div className="flex items-start gap-4">
<div className={`w-12 h-12 rounded-xl flex items-center justify-center ${style.id === 'safe' ? 'bg-blue-500/10 text-blue-400' :
style.id === 'balanced' ? 'bg-[#00ff88]/10 text-[#00ff88]' : 'bg-orange-500/10 text-orange-400'
}`}>
style.id === 'balanced' ? 'bg-[var(--accent-soft)] text-[var(--accent)]' : 'bg-orange-500/10 text-orange-400'
}`}>
{style.id === 'safe' ? <ShieldCheck size={24} /> : style.id === 'balanced' ? <Scale size={24} /> : <Zap size={24} />}
</div>
<div className="flex-1">
<div className="flex justify-between items-center mb-1">
<span className="text-lg font-bold text-white flex items-center gap-2">
{style.label}
{isLocked && <Lock size={14} className="text-zinc-500" />}
</span>
<span className="flex items-center gap-2 text-lg font-bold text-[var(--foreground)]">
{style.label}
{isLocked && <Lock size={14} className="text-[var(--muted-foreground)]" />}
</span>
<span className="text-[10px] uppercase tracking-widest font-black opacity-40">{style.tradeFrequency}</span>
</div>
<p className="text-sm text-zinc-400 leading-relaxed">{style.description}</p>
<p className="text-sm leading-relaxed text-[var(--muted-foreground)]">{style.description}</p>
</div>
</div>
</button>
@ -212,13 +222,13 @@ export const StrategyWizard: React.FC<{
})}
</div>
<div className="flex justify-end pt-4">
<button
disabled={!state.riskStyle}
onClick={next}
className="flex items-center gap-2 bg-[#00ff88] text-black px-8 py-3 rounded-xl font-bold hover:brightness-110 transition-all disabled:opacity-30"
>
Continue <ChevronRight size={18} />
</button>
<Button
disabled={!state.riskStyle}
onClick={next}
className="px-8"
>
Continue <ChevronRight size={18} />
</Button>
</div>
</div>
)}
@ -226,14 +236,14 @@ export const StrategyWizard: React.FC<{
{/* Step 2: Assets & Capital */}
{state.step === 2 && (
<div className="space-y-8 animate-in fade-in slide-in-from-right-4 duration-500">
<div className="text-center">
<h2 className="text-2xl font-bold text-white mb-2">Assets & Capital</h2>
<p className="text-zinc-400 text-sm">Define what to trade and how much capital to use.</p>
<div className="text-center">
<h2 className={sectionTitleClass}>Assets & Capital</h2>
<p className={sectionDescriptionClass}>Define what to trade and how much capital to use.</p>
</div>
<div className="space-y-6">
<div className="space-y-3">
<label className="text-xs font-bold text-zinc-500 uppercase tracking-widest">Select Trading Assets</label>
<label className={labelClass}>Select Trading Assets</label>
<div className="flex flex-wrap gap-3">
{ASSETS.map(asset => (
<button
@ -244,10 +254,10 @@ export const StrategyWizard: React.FC<{
: [...state.assets, asset.id];
if (newAssets.length > 0) setState({ ...state, assets: newAssets });
}}
className={`px-5 py-3 rounded-xl border-2 font-bold text-sm transition-all ${state.assets.includes(asset.id)
? 'border-[#00ff88] bg-[#00ff88]/10 text-white'
: 'border-white/5 bg-zinc-900 text-zinc-500 hover:border-white/10'
}`}
className={`rounded-xl border-2 px-5 py-3 text-sm font-bold transition-all ${state.assets.includes(asset.id)
? 'border-[var(--accent)] bg-[var(--accent-soft)] text-[var(--foreground)]'
: 'border-[var(--border)] bg-[var(--card)] text-[var(--muted-foreground)] hover:border-[var(--border-strong)]'
}`}
>
{asset.label}
</button>
@ -257,33 +267,33 @@ export const StrategyWizard: React.FC<{
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="space-y-3">
<label className="text-xs font-bold text-zinc-500 uppercase tracking-widest">Capital Allocation</label>
<div className="relative">
<div className="absolute inset-y-0 left-4 flex items-center pointer-events-none text-zinc-500">
<DollarSign size={16} />
</div>
<input
type="number"
value={state.capital}
onChange={e => setState({ ...state, capital: Number(e.target.value) })}
className="w-full bg-zinc-900 border-2 border-white/5 rounded-xl py-4 pl-10 pr-4 text-white font-bold outline-none focus:border-[#00ff88]/50 transition-all"
/>
</div>
<p className="text-[10px] text-zinc-500">Total USD balance this bot is allowed to manage.</p>
<label className={labelClass}>Capital Allocation</label>
<div className="relative">
<div className="pointer-events-none absolute inset-y-0 left-4 flex items-center text-[var(--muted-foreground)]">
<DollarSign size={16} />
</div>
<Input
type="number"
value={state.capital}
onChange={e => setState({ ...state, capital: Number(e.target.value) })}
className="h-14 pl-10 font-bold"
/>
</div>
<p className="text-[10px] text-[var(--muted-foreground)]">Total USD balance this bot is allowed to manage.</p>
</div>
<div className="space-y-3">
<label className="text-xs font-bold text-zinc-500 uppercase tracking-widest flex items-center justify-between">
<label className="flex items-center justify-between text-xs font-bold uppercase tracking-widest text-[var(--muted-foreground)]">
Daily Profit Target
{!isFeatureAllowed(tier, 'profit_target', policy.maxDailyProfitTargetUsd + 1) && (
<span className="text-[9px] text-amber-500 flex items-center gap-1"><Lock size={10} /> Limited to ${policy.maxDailyProfitTargetUsd}</span>
)}
</label>
<div className="relative">
<div className="absolute inset-y-0 left-4 flex items-center pointer-events-none text-zinc-500">
<div className="pointer-events-none absolute inset-y-0 left-4 flex items-center text-[var(--muted-foreground)]">
<Target size={16} />
</div>
<input
<Input
type="number"
disabled={tier === 'free'}
value={state.profitTarget}
@ -293,24 +303,24 @@ export const StrategyWizard: React.FC<{
setState({ ...state, profitTarget: val });
}
}}
className={`w-full bg-zinc-900 border-2 border-white/5 rounded-xl py-4 pl-10 pr-4 text-white font-bold outline-none focus:border-[#00ff88]/50 transition-all ${tier === 'free' ? 'opacity-50 cursor-not-allowed' : ''}`}
/>
className={`h-14 pl-10 font-bold ${tier === 'free' ? 'cursor-not-allowed opacity-50' : ''}`}
/>
</div>
<div className="flex gap-2 items-start mt-1">
<Info size={12} className="text-[#00ff88] mt-0.5 shrink-0" />
<p className="text-[10px] text-zinc-500 italic">Once this profit is reached, the bot automatically pauses for the day to lock in gains.</p>
<Info size={12} className="mt-0.5 shrink-0 text-[var(--accent)]" />
<p className="text-[10px] italic text-[var(--muted-foreground)]">Once this profit is reached, the bot automatically pauses for the day to lock in gains.</p>
</div>
</div>
</div>
</div>
<div className="flex justify-between pt-4">
<button onClick={back} className="flex items-center gap-2 text-zinc-500 hover:text-white font-bold px-6 transition-all">
<ChevronLeft size={18} /> Back
</button>
<button onClick={next} className="flex items-center gap-2 bg-[#00ff88] text-black px-8 py-3 rounded-xl font-bold hover:brightness-110 transition-all">
Continue <ChevronRight size={18} />
</button>
<Button onClick={back} variant="ghost" className="px-6">
<ChevronLeft size={18} /> Back
</Button>
<Button onClick={next} className="px-8">
Continue <ChevronRight size={18} />
</Button>
</div>
</div>
)}
@ -319,8 +329,8 @@ export const StrategyWizard: React.FC<{
{state.step === 3 && (
<div className="space-y-8 animate-in fade-in slide-in-from-right-4 duration-500">
<div className="text-center">
<h2 className="text-2xl font-bold text-white mb-2">Trading Hours</h2>
<p className="text-zinc-400 text-sm">When should the bot look for signals?</p>
<h2 className={sectionTitleClass}>Trading Hours</h2>
<p className={sectionDescriptionClass}>When should the bot look for signals?</p>
</div>
<div className="grid grid-cols-1 gap-4">
@ -328,18 +338,18 @@ export const StrategyWizard: React.FC<{
<button
key={option}
onClick={() => setState({ ...state, hours: option })}
className={`p-6 rounded-2xl border-2 text-left transition-all ${state.hours === option
? 'border-[#00ff88] bg-[#00ff88]/5'
: 'border-white/5 bg-zinc-900/50 hover:border-white/10'
}`}
className={`rounded-2xl border-2 p-6 text-left transition-all ${state.hours === option
? optionSelectedClass
: optionIdleClass
}`}
>
<div className="flex items-center gap-4">
<div className={`w-10 h-10 rounded-lg flex items-center justify-center ${state.hours === option ? 'bg-[#00ff88]/10 text-[#00ff88]' : 'bg-zinc-800 text-zinc-500'}`}>
<div className={`flex h-10 w-10 items-center justify-center rounded-lg ${state.hours === option ? 'bg-[var(--accent-soft)] text-[var(--accent)]' : 'bg-[var(--muted)] text-[var(--muted-foreground)]'}`}>
<Clock size={20} />
</div>
<div>
<span className="block font-bold text-white text-lg">{option}</span>
<span className="text-xs text-zinc-500">
<span className="block text-lg font-bold text-[var(--foreground)]">{option}</span>
<span className="text-xs text-[var(--muted-foreground)]">
{option === '24/7' ? 'Universal coverage, trades any time signals appear.' :
option === 'London + New York' ? 'Focuses on the most liquid market overlap (07:00 - 21:00 UTC).' :
'Optimized for Tokoyo and Sydney sessions.'}
@ -351,12 +361,12 @@ export const StrategyWizard: React.FC<{
</div>
<div className="flex justify-between pt-4">
<button onClick={back} className="flex items-center gap-2 text-zinc-500 hover:text-white font-bold px-6 transition-all">
<ChevronLeft size={18} /> Back
</button>
<button onClick={next} className="flex items-center gap-2 bg-[#00ff88] text-black px-8 py-3 rounded-xl font-bold hover:brightness-110 transition-all">
Continue <ChevronRight size={18} />
</button>
<Button onClick={back} variant="ghost" className="px-6">
<ChevronLeft size={18} /> Back
</Button>
<Button onClick={next} className="px-8">
Continue <ChevronRight size={18} />
</Button>
</div>
</div>
)}
@ -365,26 +375,26 @@ export const StrategyWizard: React.FC<{
{state.step === 4 && (
<div className="space-y-8 animate-in fade-in slide-in-from-right-4 duration-500">
<div className="text-center">
<h2 className="text-2xl font-bold text-white mb-2">Safety Confirmation</h2>
<p className="text-zinc-400 text-sm">Review the built-in safeguards protecting your capital.</p>
<h2 className={sectionTitleClass}>Safety Confirmation</h2>
<p className={sectionDescriptionClass}>Review the built-in safeguards protecting your capital.</p>
</div>
<div className="bg-zinc-900/80 rounded-2xl border border-white/5 overflow-hidden">
<Card className="overflow-hidden rounded-2xl">
<div className="p-6 space-y-4">
<div className="flex items-center justify-between py-3 border-b border-white/5">
<span className="text-zinc-500 text-sm font-medium">Auto-Protective Stop Loss</span>
<span className="text-[#00ff88] text-sm font-bold">Enabled (Mandatory)</span>
</div>
<div className="flex items-center justify-between py-3 border-b border-white/5">
<span className="text-zinc-500 text-sm font-medium">Position Sizing Limit</span>
<span className="text-white text-sm font-bold font-mono">Max {state.riskStyle?.riskPerTrade}% per trade</span>
</div>
<div className="flex items-center justify-between py-3 border-b border-white/5">
<span className="text-zinc-500 text-sm font-medium">Daily Recovery Halt</span>
<div className="flex items-center justify-between border-b border-[var(--border)] py-3">
<span className="text-sm font-medium text-[var(--muted-foreground)]">Auto-Protective Stop Loss</span>
<span className="text-sm font-bold text-[var(--accent)]">Enabled (Mandatory)</span>
</div>
<div className="flex items-center justify-between border-b border-[var(--border)] py-3">
<span className="text-sm font-medium text-[var(--muted-foreground)]">Position Sizing Limit</span>
<span className="font-mono text-sm font-bold text-[var(--foreground)]">Max {state.riskStyle?.riskPerTrade}% per trade</span>
</div>
<div className="flex items-center justify-between border-b border-[var(--border)] py-3">
<span className="text-sm font-medium text-[var(--muted-foreground)]">Daily Recovery Halt</span>
<span className="text-rose-400 text-sm font-bold font-mono">-${Math.floor(state.capital * 0.05)} (5%)</span>
</div>
<div className="flex items-center justify-between py-3">
<span className="text-zinc-500 text-sm font-medium">Market Volatility Guard</span>
<span className="text-sm font-medium text-[var(--muted-foreground)]">Market Volatility Guard</span>
<span className="text-blue-400 text-sm font-bold">Smart ATR Check</span>
</div>
</div>
@ -392,17 +402,17 @@ export const StrategyWizard: React.FC<{
<AlertTriangle className="text-amber-500 shrink-0" size={20} />
<p className="text-xs text-amber-500/90 leading-relaxed font-medium">
Risk management and safety rules are coded into the engine core. These cannot be disabled or bypassed, ensuring your bot always operates within safety boundaries.
</p>
</div>
</div>
</p>
</div>
</Card>
<div className="flex justify-between pt-4">
<button onClick={back} className="flex items-center gap-2 text-zinc-500 hover:text-white font-bold px-6 transition-all">
<ChevronLeft size={18} /> Back
</button>
<button onClick={next} className="flex items-center gap-2 bg-[#00ff88] text-black px-8 py-3 rounded-xl font-bold hover:brightness-110 transition-all">
I Understand <ChevronRight size={18} />
</button>
<Button onClick={back} variant="ghost" className="px-6">
<ChevronLeft size={18} /> Back
</Button>
<Button onClick={next} className="px-8">
I Understand <ChevronRight size={18} />
</Button>
</div>
</div>
)}
@ -411,79 +421,78 @@ export const StrategyWizard: React.FC<{
{state.step === 5 && (
<div className="space-y-8 animate-in fade-in zoom-in-95 duration-500">
<div className="text-center">
<h2 className="text-3xl font-bold text-white mb-2">Ready to Deploy</h2>
<p className="text-zinc-400 text-sm">Verify your bot strategy one last time.</p>
</div>
<div className="bg-[#00ff88]/5 rounded-3xl border-2 border-[#00ff88]/20 p-8 space-y-6 relative overflow-hidden">
{/* Decorative background element */}
<div className="absolute -top-24 -right-24 w-64 h-64 bg-[#00ff88]/10 blur-[100px] rounded-full pointer-events-none" />
<div className="flex items-center gap-6">
<div className="w-20 h-20 rounded-2xl bg-[#00ff88] text-black flex items-center justify-center">
{state.riskStyle?.id === 'safe' ? <ShieldCheck size={40} /> : state.riskStyle?.id === 'balanced' ? <Scale size={40} /> : <Zap size={40} />}
</div>
<div>
<h3 className="text-2xl font-bold text-white">{state.riskStyle?.label} Bot</h3>
<div className="flex gap-2 mt-1">
{state.assets.map(a => (
<span key={a} className="bg-white/10 px-2 py-0.5 rounded text-[10px] font-black text-white/80">{a.split('/')[0]}</span>
))}
</div>
</div>
<h2 className="mb-2 text-3xl font-bold text-[var(--foreground)]">Ready to Deploy</h2>
<p className={sectionDescriptionClass}>Verify your bot strategy one last time.</p>
</div>
<Card className="relative space-y-6 overflow-hidden rounded-3xl border-[var(--border-strong)] p-8">
<div className="flex items-center gap-6">
<div className="flex h-20 w-20 items-center justify-center rounded-2xl bg-[var(--primary)] text-[var(--primary-foreground)]">
{state.riskStyle?.id === 'safe' ? <ShieldCheck size={40} /> : state.riskStyle?.id === 'balanced' ? <Scale size={40} /> : <Zap size={40} />}
</div>
<div>
<h3 className="text-2xl font-bold text-[var(--foreground)]">{state.riskStyle?.label} Bot</h3>
<div className="flex gap-2 mt-1">
{state.assets.map(a => (
<span key={a} className="rounded border border-[var(--border)] bg-[var(--muted)] px-2 py-0.5 text-[10px] font-black text-[var(--muted-foreground)]">{a.split('/')[0]}</span>
))}
</div>
</div>
</div>
<div className="grid grid-cols-2 gap-8 pt-4">
<div className="space-y-1">
<span className="text-zinc-500 text-[10px] uppercase font-black tracking-widest">Target Capital</span>
<div className="text-xl font-bold text-white flex items-baseline gap-1">
<span className="text-[10px] font-black uppercase tracking-widest text-[var(--muted-foreground)]">Target Capital</span>
<div className="flex items-baseline gap-1 text-xl font-bold text-[var(--foreground)]">
<span className="text-sm opacity-50 opacity-40">$</span>{state.capital}
</div>
</div>
<div className="space-y-1">
<span className="text-zinc-500 text-[10px] uppercase font-black tracking-widest">Profit Threshold</span>
<div className="text-xl font-bold text-[#00ff88] flex items-baseline gap-1">
<span className="text-[10px] font-black uppercase tracking-widest text-[var(--muted-foreground)]">Profit Threshold</span>
<div className="flex items-baseline gap-1 text-xl font-bold text-[var(--accent)]">
<span className="text-sm opacity-40">$</span>{state.profitTarget}<span className="text-[10px] opacity-60 ml-1">/day</span>
</div>
</div>
<div className="space-y-1">
<span className="text-zinc-500 text-[10px] uppercase font-black tracking-widest">Risk Level</span>
<div className="text-xl font-bold text-white">{(state.riskStyle?.riskPerTrade || 0)}% <span className="text-xs opacity-50 font-normal">per trade</span></div>
<span className="text-[10px] font-black uppercase tracking-widest text-[var(--muted-foreground)]">Risk Level</span>
<div className="text-xl font-bold text-[var(--foreground)]">{(state.riskStyle?.riskPerTrade || 0)}% <span className="text-xs font-normal opacity-50">per trade</span></div>
</div>
<div className="space-y-1">
<span className="text-zinc-500 text-[10px] uppercase font-black tracking-widest">Active Schedule</span>
<div className="text-xl font-bold text-white">{state.hours}</div>
<span className="text-[10px] font-black uppercase tracking-widest text-[var(--muted-foreground)]">Active Schedule</span>
<div className="text-xl font-bold text-[var(--foreground)]">{state.hours}</div>
</div>
</div>
<div className="pt-6 border-t border-white/5 flex gap-4 items-center">
<div className="w-12 h-12 rounded-full border border-zinc-800 flex items-center justify-center text-zinc-600">
<div className="flex items-center gap-4 border-t border-[var(--border)] pt-6">
<div className="flex h-12 w-12 items-center justify-center rounded-full border border-[var(--border)] text-[var(--muted-foreground)]">
<Wallet size={20} />
</div>
<div className="flex-1">
<p className="text-sm text-zinc-400">Bots are created in <span className="text-white font-bold">PAUSED</span> mode by default. You must manually enable trading from your dashboard.</p>
</div>
</div>
</div>
<p className="text-sm text-[var(--muted-foreground)]">Bots are created in <span className="font-bold text-[var(--foreground)]">PAUSED</span> mode by default. You must manually enable trading from your dashboard.</p>
</div>
</div>
</Card>
<div className="flex justify-between pt-4">
<button onClick={back} className="flex items-center gap-2 text-zinc-500 hover:text-white font-bold px-6 transition-all">
<Button onClick={back} variant="ghost" className="px-6">
<ChevronLeft size={18} /> Back
</button>
</Button>
<div className="flex items-center gap-3">
{!backtestGateLoading && backtestEnabled && (
<button
<Button
type="button"
onClick={() => setShowBacktest((prev) => !prev)}
className="flex items-center gap-2 bg-white/10 text-white px-5 py-3 rounded-xl font-black text-xs uppercase tracking-wider hover:bg-white/20 transition-all"
variant="outline"
className="px-5 text-xs uppercase tracking-wider"
>
{showBacktest ? 'Hide Backtest' : 'Run Backtest'}
</button>
</Button>
)}
<button
<Button
disabled={loading}
onClick={handleSave}
className="group relative flex items-center gap-3 bg-[#00ff88] text-black px-12 py-4 rounded-2xl font-black text-lg hover:brightness-110 hover:scale-[1.02] active:scale-[0.98] transition-all shadow-2xl shadow-[#00ff88]/20 disabled:opacity-50"
size="lg"
className="group rounded-2xl px-12 text-lg font-black"
>
{loading ? 'Processing...' : (
<>
@ -491,7 +500,7 @@ export const StrategyWizard: React.FC<{
<ChevronRight size={20} className="group-hover:translate-x-1 transition-transform" />
</>
)}
</button>
</Button>
</div>
</div>

File diff suppressed because it is too large Load Diff