// TradeDetail.jsx — slide-in detail drawer for a single trade const TradeDetailDrawer = ({ trade, onClose, onEdit, onDelete }) => { const { useState } = React; const [imgOpen, setImgOpen] = useState(false); if (!trade) return null; const isPos = (trade.pnl || 0) >= 0; const pnlColor = trade.pnl == null ? 'var(--muted)' : isPos ? '#00d27a' : '#f04060'; const section = (title, children) => React.createElement('div', { style: { marginBottom: '22px' } }, [ React.createElement('div', { key: 'title', style: { fontSize: '10px', color: 'var(--muted)', fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.1em', marginBottom: '10px', paddingBottom: '6px', borderBottom: '1px solid var(--surface2)' } }, title), children ]); const row = (label, value, mono = false) => React.createElement('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '5px 0' } }, [ React.createElement('span', { key: 'l', style: { fontSize: '12px', color: 'var(--muted)' } }, label), React.createElement('span', { key: 'v', style: { fontSize: '13px', color: 'var(--text)', fontFamily: mono ? 'JetBrains Mono, monospace' : 'Space Grotesk, sans-serif', fontWeight: mono ? 500 : 400 } }, value ?? '—') ]); // Compute net debit/credit for multi-leg options const netPremium = trade.legs ? trade.legs.reduce((s, l) => s + (l.legType === 'long' ? -(l.premium || 0) : (l.premium || 0)) * (l.contracts || 1) * 100, 0) : null; return React.createElement('div', { style: { position: 'fixed', inset: 0, zIndex: 1000, display: 'flex', pointerEvents: 'none' } }, [ // Overlay React.createElement('div', { key: 'ov', onClick: onClose, style: { position: 'absolute', inset: 0, background: 'rgba(0,0,0,0.5)', pointerEvents: 'all', backdropFilter: 'blur(2px)' } }), // Drawer — right side, wider than form React.createElement('div', { key: 'drawer', style: { position: 'absolute', right: 0, top: 0, bottom: 0, width: '420px', background: 'var(--sidebar)', borderLeft: '1px solid var(--border)', display: 'flex', flexDirection: 'column', pointerEvents: 'all', overflowY: 'auto' } }, [ // Header bar React.createElement('div', { key: 'hdr', style: { padding: '18px 22px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', alignItems: 'center', position: 'sticky', top: 0, background: 'var(--sidebar)', zIndex: 1 } }, [ React.createElement('div', { key: 'left', style: { display: 'flex', alignItems: 'center', gap: '10px' } }, [ React.createElement('span', { key: 'sym', style: { fontFamily: 'JetBrains Mono, monospace', fontWeight: 700, fontSize: '18px', color: 'var(--text)', letterSpacing: '0.04em' } }, trade.symbol), React.createElement(TypeBadge, { key: 'type', type: trade.type, optionType: trade.optionType, strategy: trade.strategy }), React.createElement(DirectionBadge, { key: 'dir', direction: trade.direction }), ]), React.createElement('div', { key: 'right', style: { display: 'flex', gap: '6px', alignItems: 'center' } }, [ React.createElement('button', { key: 'edit', onClick: onEdit, style: { background: 'var(--surface2)', border: '1px solid var(--border)', borderRadius: '6px', color: 'var(--text2)', fontSize: '12px', cursor: 'pointer', padding: '5px 12px', fontFamily: 'Space Grotesk, sans-serif' } }, 'Edit'), React.createElement('button', { key: 'del', onClick: () => { if (confirm('Delete this trade?')) { onDelete(trade.id); onClose(); } }, style: { background: 'rgba(240,64,96,0.08)', border: '1px solid rgba(240,64,96,0.2)', borderRadius: '6px', color: '#f04060', fontSize: '12px', cursor: 'pointer', padding: '5px 10px' } }, '✕'), React.createElement('button', { key: 'x', onClick: onClose, style: { background: 'none', border: 'none', color: 'var(--muted)', fontSize: '20px', cursor: 'pointer', lineHeight: 1, padding: '2px 6px' } }, '×'), ]) ]), // Body React.createElement('div', { key: 'body', style: { padding: '22px', flex: 1 } }, [ // P&L Hero React.createElement('div', { key: 'hero', style: { background: 'var(--surface)', border: `1px solid ${pnlColor}22`, borderRadius: '10px', padding: '18px 22px', marginBottom: '22px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' } }, [ React.createElement('div', { key: 'left' }, [ React.createElement('div', { key: 'l', style: { fontSize: '11px', color: 'var(--muted)', fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: '4px' } }, 'Realized P&L'), React.createElement('div', { key: 'v', style: { fontSize: '32px', fontWeight: 700, color: pnlColor, fontFamily: 'JetBrains Mono, monospace', lineHeight: 1 } }, fmtPnL(trade.pnl)), ]), React.createElement('div', { key: 'right', style: { textAlign: 'right' } }, [ React.createElement('div', { key: 'l', style: { fontSize: '11px', color: 'var(--muted)', marginBottom: '4px' } }, 'R Multiple'), React.createElement('div', { key: 'v', style: { fontSize: '24px', fontWeight: 700, fontFamily: 'JetBrains Mono, monospace', color: trade.rMultiple >= 0 ? '#00d27a' : '#f04060' } }, fmtR(trade.rMultiple)), React.createElement(StatusDot, { key: 'st', status: trade.status }), ]) ]), // Trade info section('Trade Info', React.createElement('div', {}, [ row('Date', fmtDate(trade.date)), row('Symbol', trade.symbol, true), row('Direction', trade.direction.toUpperCase()), row('Status', trade.status.charAt(0).toUpperCase() + trade.status.slice(1)), trade.type === 'stock' && row('Entry Price', fmtPrice(trade.entryPrice), true), trade.type === 'stock' && row('Shares', trade.quantity?.toLocaleString(), true), trade.type === 'stock' && trade.stopLoss && row('Stop Loss', fmtPrice(trade.stopLoss), true), ].filter(Boolean))), // Option legs trade.type === 'option' && trade.legs && trade.legs.length > 0 && section( `Option Legs (${(OPTION_STRATEGIES.find(s => s.id === trade.strategy) || {}).label || 'Single'})`, React.createElement('div', { style: { display: 'flex', flexDirection: 'column', gap: '8px' } }, trade.legs.map((leg, i) => { const isLong = leg.legType === 'long'; const isCall = leg.optionType === 'call'; return React.createElement('div', { key: leg.id || i, style: { background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: '7px', padding: '10px 14px' } }, [ React.createElement('div', { key: 'hdr', style: { display: 'flex', gap: '6px', marginBottom: '6px', alignItems: 'center' } }, [ React.createElement('span', { key: 'lt', style: { fontSize: '11px', fontWeight: 600, color: isLong ? '#00d27a' : '#f04060', background: isLong ? 'rgba(0,210,122,0.1)' : 'rgba(240,64,96,0.1)', border: `1px solid ${isLong ? 'rgba(0,210,122,0.25)' : 'rgba(240,64,96,0.25)'}`, borderRadius: '3px', padding: '1px 6px' } }, isLong ? 'BUY' : 'SELL'), React.createElement('span', { key: 'ot', style: { fontSize: '11px', fontWeight: 600, color: isCall ? '#00d27a' : '#f04060', background: isCall ? 'rgba(0,210,122,0.1)' : 'rgba(240,64,96,0.1)', border: `1px solid ${isCall ? 'rgba(0,210,122,0.25)' : 'rgba(240,64,96,0.25)'}`, borderRadius: '3px', padding: '1px 6px' } }, isCall ? 'CALL' : 'PUT'), React.createElement('span', { key: 'name', style: { fontSize: '11px', color: 'var(--muted)' } }, `Leg ${i + 1}`) ]), React.createElement('div', { key: 'details', style: { display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: '6px' } }, [ React.createElement('div', { key: 'str' }, [React.createElement('div', { style: { fontSize: '10px', color: 'var(--muted)', marginBottom: '2px' } }, 'Strike'), React.createElement('div', { style: { fontSize: '12px', color: 'var(--text)', fontFamily: 'JetBrains Mono, monospace' } }, `$${leg.strike}`)]), React.createElement('div', { key: 'exp' }, [React.createElement('div', { style: { fontSize: '10px', color: 'var(--muted)', marginBottom: '2px' } }, 'Expiry'), React.createElement('div', { style: { fontSize: '12px', color: 'var(--text)' } }, fmtDate(leg.expiry))]), React.createElement('div', { key: 'cts' }, [React.createElement('div', { style: { fontSize: '10px', color: 'var(--muted)', marginBottom: '2px' } }, 'Contracts'), React.createElement('div', { style: { fontSize: '12px', color: 'var(--text)', fontFamily: 'JetBrains Mono, monospace' } }, leg.contracts)]), React.createElement('div', { key: 'prem' }, [React.createElement('div', { style: { fontSize: '10px', color: 'var(--muted)', marginBottom: '2px' } }, isLong ? 'Debit' : 'Credit'), React.createElement('div', { style: { fontSize: '12px', color: isLong ? '#f04060' : '#00d27a', fontFamily: 'JetBrains Mono, monospace' } }, `$${leg.premium}`)]), ]) ]); }) ) ), // Net debit/credit for multi-leg trade.type === 'option' && trade.legs && trade.legs.length > 1 && netPremium != null && React.createElement('div', { key: 'net', style: { background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: '7px', padding: '10px 14px', marginBottom: '22px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' } }, [ React.createElement('span', { key: 'l', style: { fontSize: '12px', color: 'var(--muted)' } }, 'Net Position Cost'), React.createElement('span', { key: 'v', style: { fontSize: '13px', fontFamily: 'JetBrains Mono, monospace', color: netPremium < 0 ? '#f04060' : '#00d27a', fontWeight: 600 } }, `${netPremium < 0 ? 'Debit' : 'Credit'} $${Math.abs(netPremium).toFixed(2)}` ) ]), // Exits section(`Exit${trade.exits.length !== 1 ? 's' : ''} (${trade.exits.length})`, trade.exits.length === 0 ? React.createElement('div', { style: { fontSize: '13px', color: 'var(--muted)' } }, 'Position still open') : React.createElement('div', { style: { display: 'flex', flexDirection: 'column', gap: '8px' } }, trade.exits.map((ex, i) => { const exitVal = trade.type === 'stock' ? ((ex.price - (trade.entryPrice || 0)) * (ex.quantity || 0)) : ((ex.price - (trade.legs?.[0]?.premium || trade.premium || 0)) * (ex.contracts || 1) * 100); return React.createElement('div', { key: ex.id || i, style: { background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: '7px', padding: '10px 14px' } }, [ React.createElement('div', { key: 'hdr', style: { display: 'flex', justifyContent: 'space-between', marginBottom: '6px' } }, [ React.createElement('span', { key: 'l', style: { fontSize: '11px', color: 'var(--muted)', fontWeight: 600 } }, `Exit ${i + 1}`), React.createElement('span', { key: 'd', style: { fontSize: '11px', color: 'var(--muted)' } }, fmtDate(ex.date)) ]), React.createElement('div', { key: 'row', style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' } }, [ React.createElement('span', { key: 'v', style: { fontFamily: 'JetBrains Mono, monospace', fontSize: '14px', color: 'var(--text)' } }, trade.type === 'stock' ? `${fmtPrice(ex.price)} × ${ex.quantity} shares` : `${fmtPrice(ex.price)} × ${ex.contracts} contracts` ), ]) ]); }) ) ), // Signals (trade.signals?.length > 0 || trade.customSignal) && section('Signals', React.createElement('div', { style: { display: 'flex', flexWrap: 'wrap', gap: '6px' } }, [ ...(trade.signals || []).map(s => React.createElement(Badge, { key: s, color: 'blue' }, s)), trade.customSignal && React.createElement(Badge, { key: 'cs', color: 'blue' }, trade.customSignal) ]) ), // Labels (trade.labels?.length > 0 || trade.customLabel) && section('Labels', React.createElement('div', { style: { display: 'flex', flexWrap: 'wrap', gap: '6px' } }, [ ...(trade.labels || []).map(l => React.createElement(LabelBadge, { key: l, label: l })), trade.customLabel && React.createElement(LabelBadge, { key: 'cl', label: trade.customLabel }) ]) ), // Notes trade.notes && section('Notes', React.createElement('div', { style: { fontSize: '13px', color: 'var(--text2)', lineHeight: '1.6', background: 'var(--surface)', borderRadius: '7px', padding: '12px 14px', border: '1px solid var(--border)' } }, trade.notes) ), // Chart snapshot trade.snapshot && section('Chart Snapshot', React.createElement('div', { style: { position: 'relative', cursor: 'zoom-in' }, onClick: () => setImgOpen(true) }, [ React.createElement('img', { key: 'img', src: trade.snapshot, alt: 'Chart', style: { width: '100%', borderRadius: '8px', border: '1px solid var(--border)', display: 'block' } }), React.createElement('div', { key: 'hint', style: { position: 'absolute', bottom: '8px', right: '8px', background: 'rgba(0,0,0,0.6)', color: '#fff', fontSize: '11px', padding: '3px 8px', borderRadius: '4px' } }, 'Click to enlarge') ]) ), ]), // Full-screen image modal imgOpen && React.createElement('div', { key: 'imgmodal', onClick: () => setImgOpen(false), style: { position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.92)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 9999 } }, React.createElement('img', { src: trade.snapshot, alt: 'Chart', style: { maxWidth: '92vw', maxHeight: '90vh', borderRadius: '8px', border: '1px solid var(--border)' } }) ) ]) ]); }; Object.assign(window, { TradeDetailDrawer });