// Invest (buy units) + Withdraw (sell units) modals — wired to real backend. function InvestModal({ bot, onClose, user }) { const [dash] = useApi('/api/dashboard/user'); const cash = dash?.cash_balance ?? 0; const [amount, setAmount] = React.useState(Math.min(10, cash)); const [step, setStep] = React.useState(0); const [busy, setBusy] = React.useState(false); const [result, setResult] = React.useState(null); const [error, setError] = React.useState(null); React.useEffect(() => { if (cash > 0 && amount === 0) setAmount(Math.min(10, cash)); }, [cash]); const presets = [10, 50, 100, 500].filter(p => p <= cash); const units = bot.unit_price ? amount / bot.unit_price : 0; const insufficient = amount > cash; const submit = async () => { setBusy(true); setError(null); try { const r = await api.post('/api/transactions/buy', { bot_id: bot.id, amount }); setResult(r); setStep(1); } catch (e) { setError(e.detail || e.message); } setBusy(false); }; return (
e.stopPropagation()}>
{emojiFor(bot.risk_category)}
Buy units in
{bot.name}
{step === 0 ? ( <>
setAmount(Number(e.target.value.replace(/[^0-9.]/g, '')) || 0)}/>
Available cash: {USD(cash)}{cash === 0 ? ' — deposit first' : ''}
{presets.map(p => ( ))} {cash > 0 && }
Total {USD(amount)}
{insufficient &&
Amount exceeds available cash. Top up via Deposit first.
} {error &&
{error}
} ) : (

Units purchased

{fmtNum(result?.units, 4)} units of {bot.name}
at NAV ${fmtNum(result?.unit_price, 4)}

)}
); } function WithdrawModal({ bot, onClose, user }) { const [dash] = useApi('/api/dashboard/user'); const holding = (dash?.holdings || []).find(h => h.bot_id === bot.id); const [units, setUnits] = React.useState(holding ? holding.units / 2 : 0); const [busy, setBusy] = React.useState(false); const [result, setResult] = React.useState(null); const [step, setStep] = React.useState(0); const [error, setError] = React.useState(null); React.useEffect(() => { if (holding && units === 0) setUnits(holding.units / 2); }, [holding]); if (!dash) return null; if (!holding) { return (
e.stopPropagation()}>
Sell units

You don't hold any units in this bot.

); } const amount = units * bot.unit_price; const submit = async () => { setBusy(true); setError(null); try { const r = await api.post('/api/transactions/sell', { bot_id: bot.id, units }); setResult(r); setStep(1); } catch (e) { setError(e.detail || e.message); } setBusy(false); }; return (
e.stopPropagation()}>
{emojiFor(bot.risk_category)}
Sell units in
{bot.name}
{step === 0 ? ( <>
setUnits(Math.min(holding.units, Number(e.target.value) || 0))}/>
You hold {fmtNum(holding.units, 4)} units
setUnits(Number(e.target.value))} style={{ width: '100%' }}/>
{[25, 50, 75, 100].map(p => ( ))}
You'll receive {USD(amount)}
{error &&
{error}
} ) : (

Units sold

Sold {fmtNum(units, 4)} units
for {USD(result?.amount || amount)}

)}
); } Object.assign(window, { InvestModal, WithdrawModal });