import React, { useState, useEffect } from 'react';
import { useAuth } from '../components/AuthContext';
import { getStrategyExplanation } from '../lib/StrategyExplanationService';
import { getUserTier } from '../lib/TierPolicy';
import {
Play,
Pause,
Trash2,
Activity,
TrendingUp,
Plus,
Shield,
Zap,
Scale,
Settings,
ChevronDown,
ChevronUp,
Lightbulb,
Cpu,
Fingerprint,
Target,
DollarSign,
Lock
} from 'lucide-react';
import { StrategyWizard } from '../components/StrategyWizard';
import { BacktestRunnerPanel } from '../backtest/components/BacktestRunnerPanel';
import { useBacktestFeatureGate } from '../backtest/useBacktestFeatureGate';
import { deleteTradeProfile, fetchTradeProfiles, setTradeProfileActive } from '../lib/profileApi';
import { Button, IconButton } from '../components/ui/Primitives';
function getStrategyKindLabel(config: any) {
if (config?.type === 'visual') return 'Visual Builder';
if (config?.type === 'code') return 'Code Strategy';
return 'V4.0 Core';
}
const ActiveStrategyCard: React.FC<{
profile: any;
botState: any;
tier: string;
onToggle: (p: any) => void;
onEdit: (p: any) => void;
onBacktest?: (p: any) => void;
onDelete: (id: string) => void;
isExpanded: boolean;
onToggleExpand: (id: string) => void;
}> = ({ profile, botState, tier, onToggle, onEdit, onBacktest, onDelete, isExpanded, onToggleExpand }) => {
const config = profile.strategy_config;
const isAggressive = config?.execution?.minRulePassRatio < 0.9;
const isSafe = config?.execution?.minRulePassRatio >= 1.0;
const strategyKindLabel = getStrategyKindLabel(config);
const explanation = getStrategyExplanation(profile, botState);
return (
{/* 1. Direct Status Strip */}
{/* 2. Header Area */}
{isSafe ? : isAggressive ? : }
Active Strategy
{profile.is_active ? 'Running' : 'Paused'}
{onBacktest && (
} onClick={() => onBacktest(profile)} style={{ width: '38px', height: '38px', borderRadius: '10px', background: 'var(--bl-surface-highlight)', border: '1px solid var(--bl-border-subtle)', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--bl-text-quiet)', cursor: 'pointer' }} className="icon-btn-hover" />
)}
} onClick={() => onEdit(profile)} style={{ width: '38px', height: '38px', borderRadius: '10px', background: 'var(--bl-surface-highlight)', border: '1px solid var(--bl-border-subtle)', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--bl-text-quiet)', cursor: 'pointer' }} className="icon-btn-hover" />
} onClick={() => onDelete(profile.id)} style={{ width: '38px', height: '38px', borderRadius: '10px', background: 'var(--bl-surface-highlight)', border: '1px solid var(--bl-border-subtle)', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--bl-text-quiet)', cursor: 'pointer' }} className="icon-btn-hover" />
{/* 3. Identity */}
{profile.name}
{profile.symbols}
{strategyKindLabel}
{/* 4. Operational DNA (Specs) */}
{[
{ label: 'Allocation', value: `$${profile.allocated_capital.toLocaleString()}`, icon:
, color: 'var(--bl-success)' },
{ label: 'PnL (Global)', value: '$0.00', icon:
, color: 'var(--bl-info-strong)' },
{ label: 'Target', value: `$${config?.riskLimits?.dailyProfitTargetUsd || 0}`, icon:
, color: 'var(--bl-warning)' },
{ label: 'Latency', value: '5ms', icon:
, color: 'var(--bl-danger)' }
].map((spec, i) => (
{spec.icon} {spec.label}
{spec.value}
))}
{/* 5. Health Diagnostic (Education Layer) */}
{/* 6. Action */}
);
};
export const MyStrategiesTab: React.FC<{ botState: any; alerts?: any[]; previewAsCustomer?: boolean }> = ({
botState,
alerts = [],
previewAsCustomer = false
}) => {
const { user, profile: userProfile } = useAuth();
const [profiles, setProfiles] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [showWizard, setShowWizard] = useState(false);
const [editingProfile, setEditingProfile] = useState(null);
const [expandedExplanations, setExpandedExplanations] = useState>({});
const [backtestProfile, setBacktestProfile] = useState(null);
const tier = getUserTier(userProfile);
const { enabled: backtestEnabled, loading: backtestGateLoading } = useBacktestFeatureGate({ previewAsCustomer });
const fetchProfiles = async () => {
if (!user) return;
setIsLoading(true);
const data = await fetchTradeProfiles();
setProfiles(data || []);
setIsLoading(false);
};
useEffect(() => {
fetchProfiles();
window.addEventListener('profiles-updated', fetchProfiles);
return () => window.removeEventListener('profiles-updated', fetchProfiles);
}, [user]);
const toggleBot = async (profile: any) => {
try {
await setTradeProfileActive(profile.id, !profile.is_active);
fetchProfiles();
} catch {
// existing UI remains silent on toggle failure
}
};
const deleteBot = async (id: string) => {
if (!confirm('Are you sure you want to delete this strategy?')) return;
try {
await deleteTradeProfile(id);
fetchProfiles();
} catch {
// existing UI remains silent on delete failure
}
};
if (showWizard) {
return (
{
setShowWizard(false);
setEditingProfile(null);
fetchProfiles();
}}
/>
);
}
return (
Strategy operations
My strategies
Monitor active profiles, review recent signals, and create new automated trading workflows.
{botState?.connected ? 'Systems online' : 'Systems disconnected'}
{/* Contextual Intelligence Row: Recent Activity + Symbol Volatility */}
{(() => {
const activeSymbols = [...new Set(profiles.flatMap(p => p.symbols?.split(',').map((s: string) => s.trim()) || []))];
const recentAlerts = [...alerts].reverse().slice(0, 5);
const symbolVolatility = activeSymbols
.filter(s => botState?.symbols?.[s])
.map(s => ({ symbol: s, change: botState.symbols[s].change24h || 0 }))
.sort((a, b) => Math.abs(b.change) - Math.abs(a.change));
return (
{/* Recent Activity */}
{recentAlerts.map((alert, i) => {
const mins = Math.floor((Date.now() - alert.timestamp) / 60000);
const timeAgo = mins < 1 ? 'just now' : mins < 60 ? `${mins}m ago` : `${Math.floor(mins / 60)}h ago`;
return (
{alert.symbol}
{alert.message}
{timeAgo}
);
})}
{recentAlerts.length === 0 &&
No activity yet...
}
{/* Symbol-Specific Volatility */}
Your Markets (24h)
{symbolVolatility.map(({ symbol, change }) => (
{symbol}
= 0 ? 'var(--bl-success)' : 'var(--bl-danger)', borderRadius: '99px' }} />
= 0 ? 'var(--bl-success)' : 'var(--bl-danger)', minWidth: '55px', textAlign: 'right' }}>
{change >= 0 ? '+' : ''}{change.toFixed(2)}%
))}
{symbolVolatility.length === 0 &&
Deploy a strategy to see its market data
}
);
})()}
{!backtestGateLoading && backtestEnabled && backtestProfile && (
s.trim()).filter(Boolean)}
initialCapitalUsd={Number(backtestProfile.allocated_capital || 1000)}
title={`Backtest: ${backtestProfile.name}`}
onClose={() => setBacktestProfile(null)}
/>
)}
{profiles.map(profile => (
{
setEditingProfile(p);
setShowWizard(true);
}}
onBacktest={!backtestGateLoading && backtestEnabled ? ((p) => setBacktestProfile(p)) : undefined}
onDelete={deleteBot}
isExpanded={!!expandedExplanations[profile.id]}
onToggleExpand={(id) => setExpandedExplanations(prev => ({ ...prev, [id]: !prev[id] }))}
/>
))}
{profiles.length === 0 && !isLoading && (
No strategies yet
Create your first strategy to start monitoring markets and testing automated execution.
)}
);
};