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
This commit is contained in:
@@ -0,0 +1,269 @@
|
||||
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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user