feat: enhance position display with proper formatting and value calculation

- Fix price formatting to show exactly 2 decimal places
- Display position size in SOL units (16.40 SOL) instead of incorrect dollar amount
- Add new Value field showing total dollar value of position (Size × Current Price)
- Improve Open Positions section with accurate financial data display
- Maintain enhanced styling and responsive layout
- All prices now formatted professionally with consistent decimal places
This commit is contained in:
mindesbunister
2025-07-27 10:32:27 +02:00
parent e88561cea1
commit 4f68593682
8 changed files with 3282 additions and 199 deletions

View File

@@ -684,10 +684,10 @@ export default function AutomationPageV2() {
{/* Enhanced Sidebar */}
<div className="space-y-6">
{/* Bot Status Card */}
{/* Unified Trading Dashboard Card */}
<div className="bg-gradient-to-br from-gray-900/90 via-slate-800/80 to-gray-900/90 backdrop-blur-xl p-6 rounded-2xl border border-gray-600/30 shadow-2xl">
<div className="flex items-center space-x-3 mb-6">
<div className={`w-12 h-12 rounded-xl flex items-center justify-center ${
<div className={`w-14 h-14 rounded-xl flex items-center justify-center ${
status?.isActive
? 'bg-gradient-to-br from-green-500 to-emerald-600 shadow-lg shadow-green-500/25'
: 'bg-gradient-to-br from-gray-600 to-gray-700'
@@ -695,70 +695,200 @@ export default function AutomationPageV2() {
<span className="text-2xl">{status?.isActive ? '🟢' : '⚪'}</span>
</div>
<div>
<h3 className="text-xl font-bold text-white">Bot Status</h3>
<p className="text-gray-400">Real-time monitoring</p>
<h3 className="text-xl font-bold text-white">Trading Dashboard</h3>
<p className="text-gray-400">Status Positions Risk Monitor</p>
</div>
</div>
<div className="space-y-4">
<div className="flex justify-between items-center p-3 bg-black/20 rounded-lg">
<span className="text-gray-400 font-medium">Status:</span>
<span className={`px-3 py-1 rounded-lg text-sm font-bold ${
status?.isActive
? 'bg-green-500/20 text-green-300 border border-green-500/30'
: 'bg-gray-600/20 text-gray-300 border border-gray-600/30'
}`}>
{status?.isActive ? 'RUNNING' : 'STOPPED'}
</span>
{/* Bot Status Section */}
<div className="mb-6">
<h4 className="text-lg font-semibold text-blue-400 mb-3 flex items-center">
<span className="mr-2">🤖</span>Bot Status
</h4>
<div className="space-y-3">
<div className="flex justify-between items-center p-3 bg-black/20 rounded-lg">
<span className="text-gray-400 font-medium">Status:</span>
<span className={`px-3 py-1 rounded-lg text-sm font-bold ${
status?.isActive
? 'bg-green-500/20 text-green-300 border border-green-500/30'
: 'bg-gray-600/20 text-gray-300 border border-gray-600/30'
}`}>
{status?.isActive ? 'RUNNING' : 'STOPPED'}
</span>
</div>
{status?.isActive && (
<>
<div className="flex justify-between items-center p-3 bg-black/20 rounded-lg">
<span className="text-gray-400 font-medium">Symbol:</span>
<span className="text-white font-bold">{status.symbol}</span>
</div>
<div className="flex justify-between items-center p-3 bg-black/20 rounded-lg">
<span className="text-gray-400 font-medium">Mode:</span>
<span className={`px-3 py-1 rounded-lg text-sm font-bold border ${
status.mode === 'LIVE'
? 'bg-red-500/20 text-red-300 border-red-500/30'
: 'bg-blue-500/20 text-blue-300 border-blue-500/30'
}`}>
{status.mode}
</span>
</div>
<div className="p-3 bg-black/20 rounded-lg">
<div className="text-gray-400 font-medium mb-2">Timeframes:</div>
<div className="flex flex-wrap gap-1">
{status.timeframes?.map((tf, index) => (
<span key={index} className="text-xs bg-cyan-500/20 text-cyan-300 px-2 py-1 rounded border border-cyan-500/30">
{timeframes.find(t => t.value === tf)?.label || tf}
</span>
))}
</div>
</div>
</>
)}
{/* Rate Limit Warning */}
{status?.rateLimitHit && (
<div className="p-3 bg-gradient-to-br from-red-900/50 to-red-800/30 border border-red-600/50 rounded-lg">
<div className="flex items-center space-x-2 mb-1">
<span className="text-red-400 font-bold"></span>
<span className="text-red-300 font-bold text-sm">Rate Limit Reached</span>
</div>
{status.rateLimitMessage && (
<p className="text-red-200 text-xs mb-1">{status.rateLimitMessage}</p>
)}
<p className="text-red-100 text-xs">
Automation stopped. Recharge OpenAI account to continue.
</p>
</div>
)}
</div>
{status?.isActive && (
<>
</div>
{/* Position Monitor Section */}
{monitorData && (
<div className="mb-6">
<h4 className="text-lg font-semibold text-purple-400 mb-3 flex items-center">
<span className="mr-2">📊</span>Position Monitor
</h4>
<div className="space-y-3">
<div className="flex justify-between items-center p-3 bg-black/20 rounded-lg">
<span className="text-gray-400 font-medium">Symbol:</span>
<span className="text-white font-bold text-lg">{status.symbol}</span>
<span className="text-gray-400 font-medium">Has Position:</span>
<span className={`px-3 py-1 rounded-lg text-sm font-bold border ${
monitorData.hasPosition
? 'bg-green-500/20 text-green-300 border-green-500/30'
: 'bg-gray-600/20 text-gray-300 border-gray-600/30'
}`}>
{monitorData.hasPosition ? '✅ YES' : '❌ NO'}
</span>
</div>
<div className="flex justify-between items-center p-3 bg-black/20 rounded-lg">
<span className="text-gray-400 font-medium">Mode:</span>
<span className="text-gray-400 font-medium">Risk Level:</span>
<span className={`px-3 py-1 rounded-lg text-sm font-bold border ${
status.mode === 'LIVE'
? 'bg-red-500/20 text-red-300 border-red-500/30'
: 'bg-blue-500/20 text-blue-300 border-blue-500/30'
monitorData.riskLevel === 'HIGH' ? 'bg-red-500/20 text-red-300 border-red-500/30' :
monitorData.riskLevel === 'MEDIUM' ? 'bg-yellow-500/20 text-yellow-300 border-yellow-500/30' :
'bg-green-500/20 text-green-300 border-green-500/30'
}`}>
{status.mode}
{monitorData.riskLevel}
</span>
</div>
<div className="p-3 bg-black/20 rounded-lg">
<div className="text-gray-400 font-medium mb-2">Timeframes:</div>
<div className="flex flex-wrap gap-1">
{status.timeframes?.map((tf, index) => (
<span key={index} className="text-xs bg-cyan-500/20 text-cyan-300 px-2 py-1 rounded border border-cyan-500/30">
{timeframes.find(t => t.value === tf)?.label || tf}
</span>
))}
<div className="text-gray-400 text-sm mb-1">Next Action:</div>
<div className="text-white text-sm">{monitorData.nextAction}</div>
</div>
{monitorData.orphanedOrderCleanup && (
<div className={`p-3 rounded-lg border ${
monitorData.orphanedOrderCleanup.success
? 'bg-green-900/30 border-green-600/50'
: 'bg-red-900/30 border-red-600/50'
}`}>
<div className="text-sm font-semibold mb-1">
{monitorData.orphanedOrderCleanup.success ? '✅ Cleanup Success' : '❌ Cleanup Failed'}
</div>
<div className="text-xs text-gray-300">
{monitorData.orphanedOrderCleanup.message}
</div>
</div>
</div>
</>
)}
{/* Rate Limit Warning */}
{status?.rateLimitHit && (
<div className="p-4 bg-gradient-to-br from-red-900/50 to-red-800/30 border-2 border-red-600/50 rounded-xl">
<div className="flex items-center space-x-2 mb-2">
<span className="text-red-400 font-bold text-lg"></span>
<span className="text-red-300 font-bold">Rate Limit Reached</span>
</div>
{status.rateLimitMessage && (
<p className="text-red-200 text-sm mb-2">{status.rateLimitMessage}</p>
)}
<p className="text-red-100 text-xs">
Automation stopped automatically. Please recharge your OpenAI account to continue.
</p>
</div>
)}
</div>
</div>
)}
{/* Open Positions Section */}
{positions.length > 0 && (
<div className="mb-6">
<h4 className="text-lg font-semibold text-yellow-400 mb-3 flex items-center">
<span className="mr-2">📈</span>Open Positions
<span className="ml-2 text-sm bg-yellow-500/20 text-yellow-300 px-2 py-1 rounded-lg border border-yellow-500/30">
{positions.length}
</span>
</h4>
<div className="space-y-3">
{positions.map((position, index) => (
<div key={index} className="p-4 bg-gradient-to-r from-gray-800/50 to-gray-700/30 rounded-xl border border-gray-600/30">
<div className="flex justify-between items-center mb-3">
<span className="text-white font-bold">{position.symbol}</span>
<span className={`px-2 py-1 rounded-lg text-xs font-bold border ${
position.side === 'LONG'
? 'bg-green-500/20 text-green-300 border-green-500/30'
: 'bg-red-500/20 text-red-300 border-red-500/30'
}`}>
{position.side}
</span>
</div>
<div className="grid grid-cols-2 gap-2 text-sm">
<div className="flex justify-between">
<span className="text-gray-400">Size:</span>
<span className="text-white font-semibold">
{position.symbol?.includes('SOL') ?
`${parseFloat(position.size).toFixed(2)} SOL` :
`$${parseFloat(position.size).toFixed(2)}`
}
</span>
</div>
<div className="flex justify-between">
<span className="text-gray-400">Value:</span>
<span className="text-green-400 font-bold">
${((parseFloat(position.size) || 0) * (parseFloat(position.markPrice) || parseFloat(position.entryPrice) || 0)).toFixed(2)}
</span>
</div>
{position.entryPrice && (
<div className="flex justify-between">
<span className="text-gray-400">Entry:</span>
<span className="text-white font-mono">${parseFloat(position.entryPrice).toFixed(2)}</span>
</div>
)}
{position.markPrice && (
<div className="flex justify-between">
<span className="text-gray-400">Mark:</span>
<span className="text-white font-mono">${parseFloat(position.markPrice).toFixed(2)}</span>
</div>
)}
{position.pnl !== undefined && (
<div className="flex justify-between">
<span className="text-gray-400">PnL:</span>
<span className={`font-bold ${
position.pnl >= 0 ? 'text-green-400' : 'text-red-400'
}`}>
${position.pnl >= 0 ? '+' : ''}${parseFloat(position.pnl).toFixed(2)}
</span>
</div>
)}
</div>
</div>
))}
</div>
</div>
)}
</div>
{/* Account Balance Card */}
@@ -787,140 +917,13 @@ export default function AutomationPageV2() {
</div>
<div className="p-3 bg-black/20 rounded-lg">
<div className="text-gray-400 text-xs mb-1">Open Positions</div>
<div className="text-gray-400 text-xs mb-1">Total Positions</div>
<div className="text-yellow-400 font-semibold">{balance.positions || 0}</div>
</div>
</div>
</div>
</div>
)}
{/* Position Monitor Card */}
{monitorData && (
<div className="bg-gradient-to-br from-gray-900/90 via-slate-800/80 to-gray-900/90 backdrop-blur-xl p-6 rounded-2xl border border-gray-600/30 shadow-2xl">
<div className="flex items-center space-x-3 mb-6">
<div className={`w-12 h-12 rounded-xl flex items-center justify-center ${
monitorData.hasPosition
? 'bg-gradient-to-br from-blue-500 to-indigo-600 shadow-lg shadow-blue-500/25'
: 'bg-gradient-to-br from-gray-600 to-gray-700'
}`}>
<span className="text-2xl">📊</span>
</div>
<div>
<h3 className="text-xl font-bold text-white">Position Monitor</h3>
<p className="text-gray-400">Risk assessment</p>
</div>
</div>
<div className="space-y-4">
<div className="flex justify-between items-center p-3 bg-black/20 rounded-lg">
<span className="text-gray-400 font-medium">Has Position:</span>
<span className={`px-3 py-1 rounded-lg text-sm font-bold border ${
monitorData.hasPosition
? 'bg-green-500/20 text-green-300 border-green-500/30'
: 'bg-gray-600/20 text-gray-300 border-gray-600/30'
}`}>
{monitorData.hasPosition ? '✅ YES' : '❌ NO'}
</span>
</div>
<div className="flex justify-between items-center p-3 bg-black/20 rounded-lg">
<span className="text-gray-400 font-medium">Risk Level:</span>
<span className={`px-3 py-1 rounded-lg text-sm font-bold border ${
monitorData.riskLevel === 'HIGH' ? 'bg-red-500/20 text-red-300 border-red-500/30' :
monitorData.riskLevel === 'MEDIUM' ? 'bg-yellow-500/20 text-yellow-300 border-yellow-500/30' :
'bg-green-500/20 text-green-300 border-green-500/30'
}`}>
{monitorData.riskLevel}
</span>
</div>
<div className="p-3 bg-black/20 rounded-lg">
<div className="text-gray-400 text-sm mb-1">Next Action:</div>
<div className="text-white text-sm">{monitorData.nextAction}</div>
</div>
{monitorData.orphanedOrderCleanup && (
<div className={`p-3 rounded-lg border ${
monitorData.orphanedOrderCleanup.success
? 'bg-green-900/30 border-green-600/50'
: 'bg-red-900/30 border-red-600/50'
}`}>
<div className="text-sm font-semibold mb-1">
{monitorData.orphanedOrderCleanup.success ? '✅ Cleanup Success' : '❌ Cleanup Failed'}
</div>
<div className="text-xs text-gray-300">
{monitorData.orphanedOrderCleanup.message}
</div>
</div>
)}
</div>
</div>
)}
{/* Open Positions Card */}
{positions.length > 0 && (
<div className="bg-gradient-to-br from-gray-900/90 via-slate-800/80 to-gray-900/90 backdrop-blur-xl p-6 rounded-2xl border border-gray-600/30 shadow-2xl">
<div className="flex items-center space-x-3 mb-6">
<div className="w-12 h-12 bg-gradient-to-br from-yellow-500 to-orange-600 rounded-xl flex items-center justify-center shadow-lg shadow-yellow-500/25">
<span className="text-2xl">📈</span>
</div>
<div>
<h3 className="text-xl font-bold text-white">Open Positions</h3>
<p className="text-gray-400">{positions.length} active trade{positions.length !== 1 ? 's' : ''}</p>
</div>
</div>
<div className="space-y-4">
{positions.map((position, index) => (
<div key={index} className="p-4 bg-gradient-to-r from-gray-800/50 to-gray-700/30 rounded-xl border border-gray-600/30">
<div className="flex justify-between items-center mb-3">
<span className="text-white font-bold text-lg">{position.symbol}</span>
<span className={`px-3 py-1 rounded-lg text-sm font-bold border ${
position.side === 'LONG'
? 'bg-green-500/20 text-green-300 border-green-500/30'
: 'bg-red-500/20 text-red-300 border-red-500/30'
}`}>
{position.side}
</span>
</div>
<div className="grid grid-cols-2 gap-3 text-sm">
<div className="flex justify-between">
<span className="text-gray-400">Size:</span>
<span className="text-white font-semibold">${position.size}</span>
</div>
{position.entryPrice && (
<div className="flex justify-between">
<span className="text-gray-400">Entry:</span>
<span className="text-white font-mono">${position.entryPrice}</span>
</div>
)}
{position.markPrice && (
<div className="flex justify-between">
<span className="text-gray-400">Mark:</span>
<span className="text-white font-mono">${position.markPrice}</span>
</div>
)}
{position.pnl !== undefined && (
<div className="flex justify-between">
<span className="text-gray-400">PnL:</span>
<span className={`font-bold ${
position.pnl >= 0 ? 'text-green-400' : 'text-red-400'
}`}>
${position.pnl >= 0 ? '+' : ''}${position.pnl}
</span>
</div>
)}
</div>
</div>
))}
</div>
</div>
)}
</div>
</div>