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 ## Phase 4: Remaining legacy component cleanup
- [ ] Normalize `web/src/components/TradeProfileManager.tsx` - [x] Normalize `web/src/components/TradeProfileManager.tsx`
- [ ] Normalize `web/src/components/StrategyWizard.tsx` - [x] Normalize `web/src/components/StrategyWizard.tsx`
- [ ] Normalize `web/src/tabs/ReconciliationAuditPanel.tsx` - [ ] Normalize `web/src/tabs/ReconciliationAuditPanel.tsx`
- [ ] Normalize `web/src/components/GlobalConfigManager.tsx` - [ ] Normalize `web/src/components/GlobalConfigManager.tsx`
- [ ] Normalize `web/src/components/EntryForm.tsx` - [ ] Normalize `web/src/components/EntryForm.tsx`

View File

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

File diff suppressed because it is too large Load Diff