import { useState } from 'react'; import { useTradingConfig, useSetTradingMode, useSetTradingCapital, usePendingApprovals, useReviewApproval, useActiveLockouts, useMacroStatus, useToggleMacro, useCompetitiveStatus, useToggleCompetitive, } from '../api/hooks'; import { StatusBadge, LoadingSpinner, Card } from '../components/ui'; export function TradingPage() { const { data: config, isLoading: configLoading } = useTradingConfig(); const { data: approvals } = usePendingApprovals(); const { data: lockouts } = useActiveLockouts(); const { data: macroStatus } = useMacroStatus(); const { data: competitiveStatus } = useCompetitiveStatus(); const setMode = useSetTradingMode(); const setCapital = useSetTradingCapital(); const reviewApproval = useReviewApproval(); const toggleMacro = useToggleMacro(); const toggleCompetitive = useToggleCompetitive(); // Normalize API field names (API returns macro_enabled/competitive_enabled, not enabled) const macroEnabled = macroStatus?.enabled ?? macroStatus?.macro_enabled ?? false; const competitiveEnabled = competitiveStatus?.enabled ?? competitiveStatus?.competitive_enabled ?? false; const [confirmMode, setConfirmMode] = useState(null); const [confirmMacroToggle, setConfirmMacroToggle] = useState(false); const [confirmCompetitiveToggle, setConfirmCompetitiveToggle] = useState(false); if (configLoading) return ; const currentMode = config?.trading_mode ?? 'paper'; return (

Trading Controls

{/* Trading Mode */}

Trading Mode

{['paper', 'live', 'disabled'].map((mode) => ( ))}
{/* Confirmation dialog for live mode */} {confirmMode && (

Are you sure you want to switch to {confirmMode} mode? This enables real order execution.

)}
{/* Paper Trading Capital */} setCapital.mutate(amount)} isPending={setCapital.isPending} /> {/* Macro Signal Layer Toggle */}

Macro Signal Layer

{macroEnabled ? 'Enabled' : 'Disabled'} {macroStatus?.toggled_at && ( Last changed: {new Date(macroStatus.toggled_at).toLocaleString()} {macroStatus.toggled_by && ` by ${macroStatus.toggled_by}`} )}
{/* Confirmation dialog for macro toggle */} {confirmMacroToggle && (

Are you sure you want to {macroEnabled ? 'disable' : 'enable'} the macro signal layer? {macroEnabled ? ' Disabling will exclude macro signals from trend summaries and recommendations.' : ' Enabling will include global event macro signals in trend summaries and recommendations.'}

)}
{/* Competitive Signal Layer Toggle */}

Competitive Signal Layer

{competitiveEnabled ? 'Enabled' : 'Disabled'} {competitiveStatus?.toggled_at && ( Last changed: {new Date(competitiveStatus.toggled_at).toLocaleString()} {competitiveStatus.toggled_by && ` by ${competitiveStatus.toggled_by}`} )}
{/* Confirmation dialog for competitive toggle */} {confirmCompetitiveToggle && (

Are you sure you want to {competitiveEnabled ? 'disable' : 'enable'} the competitive signal layer? {competitiveEnabled ? ' Disabling will exclude historical pattern and competitive signals from trend summaries and recommendations.' : ' Enabling will include historical pattern and competitive signals in trend summaries and recommendations.'}

)}
{/* Pending Approvals */}

Pending Approvals ({approvals?.length ?? 0})

{!approvals?.length ? (

No pending approvals

) : (
{approvals.map((a) => ( reviewApproval.mutate({ id: a.id, approved, review_note: note })} /> ))}
)}
{/* Active Lockouts */}

Active Lockouts ({lockouts?.length ?? 0})

{!lockouts?.length ? (

No active lockouts

) : (
{lockouts.map((l) => { const expiresIn = l.expires_at ? Math.max(0, Math.round((new Date(l.expires_at).getTime() - Date.now()) / 60000)) : 0; return (
{l.ticker} {l.reason}
{expiresIn > 0 ? `${expiresIn}m remaining` : 'expired'}
); })}
)}
); } function ApprovalRow({ approval, onReview }: { approval: { id: string; ticker: string; side: string; quantity: number; estimated_value: number | null; requested_at: string }; onReview: (approved: boolean, note: string) => void; }) { const [note, setNote] = useState(''); return (
{approval.ticker} qty: {approval.quantity} {approval.estimated_value != null && ( ${approval.estimated_value.toFixed(2)} )}
{new Date(approval.requested_at).toLocaleString()}
setNote(e.target.value)} className="flex-1 rounded-md border border-surface-700 bg-surface-900 px-2 py-1 text-xs text-gray-200 placeholder-gray-500" aria-label="Review note" />
); } function CapitalCard({ onSetCapital, isPending }: { onSetCapital: (amount: number) => void; isPending: boolean }) { const [amount, setAmount] = useState('100000'); const [showConfirm, setShowConfirm] = useState(false); const presets = [10000, 50000, 100000, 500000]; return (

Paper Trading Capital

setAmount(e.target.value)} className="w-40 rounded-md border border-surface-700 bg-surface-900 px-3 py-1.5 text-sm text-gray-200 focus:border-brand-500 focus:outline-none" />
{presets.map((p) => ( ))}
{showConfirm && (

This will reset the paper trading pools to ${Number(amount).toLocaleString()}. Any existing pool balances will be overwritten.

)}
); }