Files
robinhood/frontend/src/components/ManualTradeLogger.tsx
T
Krikorios b5e2b02cb8 Reorganize UI for external trading workflow with manual trade logging
- Restructure tabs to analysis-focused workflow:
  * Analysis Hub: AI analysis, risk management, manual trade logger
  * Daily Prep: Market summary, alerts, checklist, news, trading plan
  * Journal & Review: Trading journal, habit tracker, advanced analytics
  * Live Charts: Technical analysis with streaming charts

- Add ManualTradeLogger component for logging trades from MT5/TradingView/cTrader
- Remove execution-focused components (TradeControls, PortfolioTracker)
- Update XAU/USD price to realistic ,084.99
- Add indicator preferences and AI plan service
- Add comprehensive documentation on decision coverage and implementation
2025-11-16 07:50:00 +02:00

270 lines
9.2 KiB
TypeScript

import { useState } from 'react';
import { Plus, TrendingUp, TrendingDown, Save, X } from 'lucide-react';
interface ManualTradeLoggerProps {
onTradeLogged?: (trade: any) => void;
}
export default function ManualTradeLogger({ onTradeLogged }: ManualTradeLoggerProps) {
const [isOpen, setIsOpen] = useState(false);
const [trade, setTrade] = useState({
symbol: 'XAU/USD',
action: 'BUY' as 'BUY' | 'SELL',
entryPrice: '',
quantity: '',
stopLoss: '',
takeProfit: '',
entryTime: new Date().toISOString().slice(0, 16),
platform: 'MT5',
notes: ''
});
const handleSubmit = () => {
if (!trade.entryPrice || !trade.quantity) {
alert('Please enter at least entry price and quantity');
return;
}
const loggedTrade = {
...trade,
id: Date.now(),
entryPrice: parseFloat(trade.entryPrice),
quantity: parseFloat(trade.quantity),
stopLoss: trade.stopLoss ? parseFloat(trade.stopLoss) : null,
takeProfit: trade.takeProfit ? parseFloat(trade.takeProfit) : null,
status: 'OPEN',
loggedAt: new Date().toISOString()
};
// Save to localStorage
const existingTrades = JSON.parse(localStorage.getItem('logged-trades') || '[]');
existingTrades.push(loggedTrade);
localStorage.setItem('logged-trades', JSON.stringify(existingTrades));
if (onTradeLogged) {
onTradeLogged(loggedTrade);
}
// Reset form
setTrade({
symbol: 'XAU/USD',
action: 'BUY',
entryPrice: '',
quantity: '',
stopLoss: '',
takeProfit: '',
entryTime: new Date().toISOString().slice(0, 16),
platform: 'MT5',
notes: ''
});
setIsOpen(false);
alert('Trade logged successfully!');
};
return (
<div className="card">
<div className="flex items-center justify-between mb-4">
<h3 className="text-lg font-semibold">📝 Log External Trade</h3>
<button
onClick={() => setIsOpen(!isOpen)}
className="btn-primary flex items-center gap-2"
>
<Plus className="w-4 h-4" />
Log Trade
</button>
</div>
{isOpen && (
<div className="bg-dark-bg rounded-lg p-6 border-2 border-blue-500">
<div className="flex items-center justify-between mb-4">
<h4 className="font-semibold text-lg">Log Trade from External Platform</h4>
<button onClick={() => setIsOpen(false)} className="text-gray-400 hover:text-white">
<X className="w-5 h-5" />
</button>
</div>
<div className="grid grid-cols-2 gap-4">
{/* Symbol */}
<div>
<label className="block text-sm text-gray-400 mb-2">Symbol</label>
<select
value={trade.symbol}
onChange={(e) => setTrade({ ...trade, symbol: e.target.value })}
className="input w-full"
>
<option value="XAU/USD">XAU/USD (Gold)</option>
<option value="EUR/USD">EUR/USD</option>
<option value="GBP/USD">GBP/USD</option>
<option value="BTC/USD">BTC/USD</option>
<option value="Other">Other</option>
</select>
</div>
{/* Action */}
<div>
<label className="block text-sm text-gray-400 mb-2">Action</label>
<div className="grid grid-cols-2 gap-2">
<button
onClick={() => setTrade({ ...trade, action: 'BUY' })}
className={`py-2 px-4 rounded font-medium ${
trade.action === 'BUY'
? 'bg-green-500 text-white'
: 'bg-dark-surface text-gray-400'
}`}
>
<TrendingUp className="w-4 h-4 inline mr-1" />
BUY
</button>
<button
onClick={() => setTrade({ ...trade, action: 'SELL' })}
className={`py-2 px-4 rounded font-medium ${
trade.action === 'SELL'
? 'bg-red-500 text-white'
: 'bg-dark-surface text-gray-400'
}`}
>
<TrendingDown className="w-4 h-4 inline mr-1" />
SELL
</button>
</div>
</div>
{/* Entry Price */}
<div>
<label className="block text-sm text-gray-400 mb-2">Entry Price *</label>
<input
type="number"
step="0.01"
value={trade.entryPrice}
onChange={(e) => setTrade({ ...trade, entryPrice: e.target.value })}
className="input w-full"
placeholder="2030.50"
required
/>
</div>
{/* Quantity */}
<div>
<label className="block text-sm text-gray-400 mb-2">Quantity (lots/oz) *</label>
<input
type="number"
step="0.01"
value={trade.quantity}
onChange={(e) => setTrade({ ...trade, quantity: e.target.value })}
className="input w-full"
placeholder="1.0"
required
/>
</div>
{/* Stop Loss */}
<div>
<label className="block text-sm text-gray-400 mb-2">Stop Loss</label>
<input
type="number"
step="0.01"
value={trade.stopLoss}
onChange={(e) => setTrade({ ...trade, stopLoss: e.target.value })}
className="input w-full"
placeholder="2020.00"
/>
</div>
{/* Take Profit */}
<div>
<label className="block text-sm text-gray-400 mb-2">Take Profit</label>
<input
type="number"
step="0.01"
value={trade.takeProfit}
onChange={(e) => setTrade({ ...trade, takeProfit: e.target.value })}
className="input w-full"
placeholder="2050.00"
/>
</div>
{/* Entry Time */}
<div>
<label className="block text-sm text-gray-400 mb-2">Entry Time</label>
<input
type="datetime-local"
value={trade.entryTime}
onChange={(e) => setTrade({ ...trade, entryTime: e.target.value })}
className="input w-full"
/>
</div>
{/* Platform */}
<div>
<label className="block text-sm text-gray-400 mb-2">Platform</label>
<select
value={trade.platform}
onChange={(e) => setTrade({ ...trade, platform: e.target.value })}
className="input w-full"
>
<option value="MT4">MetaTrader 4</option>
<option value="MT5">MetaTrader 5</option>
<option value="TradingView">TradingView</option>
<option value="cTrader">cTrader</option>
<option value="Broker Platform">Broker Platform</option>
<option value="Other">Other</option>
</select>
</div>
{/* Notes */}
<div className="col-span-2">
<label className="block text-sm text-gray-400 mb-2">Trade Notes</label>
<textarea
value={trade.notes}
onChange={(e) => setTrade({ ...trade, notes: e.target.value })}
className="input w-full"
rows={3}
placeholder="Why did you enter this trade? What's your plan?"
/>
</div>
</div>
<div className="flex gap-3 mt-6">
<button
onClick={handleSubmit}
className="btn-primary flex items-center gap-2 flex-1"
>
<Save className="w-4 h-4" />
Log Trade
</button>
<button
onClick={() => setIsOpen(false)}
className="btn bg-dark-surface text-gray-300 hover:bg-dark-hover"
>
Cancel
</button>
</div>
</div>
)}
{/* Quick Stats */}
<div className="mt-4 grid grid-cols-3 gap-3">
<div className="bg-dark-bg rounded p-3">
<div className="text-xs text-gray-400">Today's Trades</div>
<div className="text-xl font-bold">0</div>
</div>
<div className="bg-dark-bg rounded p-3">
<div className="text-xs text-gray-400">Open Positions</div>
<div className="text-xl font-bold text-blue-500">0</div>
</div>
<div className="bg-dark-bg rounded p-3">
<div className="text-xs text-gray-400">Win Rate</div>
<div className="text-xl font-bold text-green-500">--</div>
</div>
</div>
<div className="mt-4 p-3 bg-blue-500/10 border border-blue-500/30 rounded">
<p className="text-sm text-blue-300">
💡 <strong>Tip:</strong> Log your trades from MT5/TradingView/Broker platform here for
continuous analysis and journaling.
</p>
</div>
</div>
);
}