"use client" import React, { useState, useEffect } from 'react' interface TradeMonitoring { tradeId: string symbol: string side: 'BUY' | 'SELL' entryPrice: number stopLoss?: number takeProfit?: number currentPrice?: number currentPnL?: number pnlPercentage?: number distanceToTP?: number distanceToSL?: number status: 'ACTIVE' | 'APPROACHING_TP' | 'APPROACHING_SL' | 'CRITICAL' } interface PriceAlert { id: string symbol: string tradeId: string alertType: 'TP_APPROACH' | 'SL_APPROACH' | 'BREAKOUT' | 'REVERSAL' currentPrice: number targetPrice: number threshold: number triggered: boolean createdAt: string } export default function RealTimePriceMonitor() { const [monitoringData, setMonitoringData] = useState([]) const [alerts, setAlerts] = useState([]) const [prices, setPrices] = useState>({}) const [lastUpdated, setLastUpdated] = useState('') const [monitoringActive, setMonitoringActive] = useState(false) const [loading, setLoading] = useState(true) useEffect(() => { fetchMonitoringData() // Update every 30 seconds for UI refresh const interval = setInterval(fetchMonitoringData, 30000) return () => clearInterval(interval) }, []) const fetchMonitoringData = async () => { try { console.log('🔄 RealTimePriceMonitor: Fetching data...') const response = await fetch('/api/price-monitor') const data = await response.json() console.log('📊 RealTimePriceMonitor: API Response:', { success: data.success, tradesCount: data.data?.trades?.length || 0, monitoringActive: data.data?.monitoringActive, prices: Object.keys(data.data?.prices || {}) }) if (data.success) { setMonitoringData(data.data.trades || []) setAlerts(data.data.alerts || []) setPrices(data.data.prices || {}) setLastUpdated(data.data.lastUpdated || '') setMonitoringActive(data.data.monitoringActive || false) console.log('✅ RealTimePriceMonitor: State updated with', data.data.trades?.length || 0, 'trades') } else { console.error('❌ RealTimePriceMonitor: API returned error:', data.error) } } catch (error) { console.error('❌ RealTimePriceMonitor: Error fetching data:', error) } finally { setLoading(false) } } const startMonitoring = async () => { try { const response = await fetch('/api/price-monitor', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'start_monitoring' }) }) if (response.ok) { setMonitoringActive(true) await fetchMonitoringData() } } catch (error) { console.error('Error starting monitoring:', error) } } const stopMonitoring = async () => { try { const response = await fetch('/api/price-monitor', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'stop_monitoring' }) }) if (response.ok) { setMonitoringActive(false) } } catch (error) { console.error('Error stopping monitoring:', error) } } const forceUpdatePrice = async (symbol: string) => { try { const response = await fetch('/api/price-monitor', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'force_update', symbol }) }) if (response.ok) { await fetchMonitoringData() } } catch (error) { console.error('Error force updating price:', error) } } const getStatusColor = (status: TradeMonitoring['status']) => { switch (status) { case 'CRITICAL': return 'text-red-400 bg-red-900/20 border-red-600' case 'APPROACHING_TP': return 'text-green-400 bg-green-900/20 border-green-600' case 'APPROACHING_SL': return 'text-yellow-400 bg-yellow-900/20 border-yellow-600' default: return 'text-blue-400 bg-blue-900/20 border-blue-600' } } const getPnLColor = (pnl?: number) => { if (!pnl) return 'text-gray-400' return pnl >= 0 ? 'text-green-400' : 'text-red-400' } const formatCurrency = (amount?: number) => { if (amount === undefined || amount === null) return 'N/A' return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', minimumFractionDigits: 2, maximumFractionDigits: 4 }).format(amount) } const formatPercentage = (pct?: number) => { if (pct === undefined || pct === null) return 'N/A' return `${pct >= 0 ? '+' : ''}${pct.toFixed(2)}%` } const formatDistance = (distance?: number) => { if (distance === undefined || distance === null) return 'N/A' return `${(distance * 100).toFixed(1)}%` } if (loading) { return (
) } return (
{/* Header Controls */}

Real-Time Price Monitor

Tracks active trades and triggers analysis when approaching TP/SL

{monitoringActive ? '🟢 Active' : '🔴 Stopped'}
{monitoringActive ? ( ) : ( )}
{lastUpdated && (
Last updated: {new Date(lastUpdated).toLocaleString()}
)}
{/* Active Alerts */} {alerts.length > 0 && (

🚨 Active Alerts

{alerts.map((alert) => (
{alert.symbol} {alert.alertType.replace('_', ' ')}
Current: {formatCurrency(alert.currentPrice)} → Target: {formatCurrency(alert.targetPrice)}
))}
)} {/* Current Prices */}

💰 Current Prices

{Object.entries(prices).map(([symbol, price]) => (
{symbol}
{formatCurrency(price)}
))}
{/* Active Trades Monitoring */}

📊 Active Trades Monitor

{(() => { console.log('🎯 RealTimePriceMonitor: Rendering with', monitoringData.length, 'trades', monitoringData) return null })()} {monitoringData.length === 0 ? (

No active trades to monitor

Debug: Monitoring Active: {monitoringActive ? 'Yes' : 'No'} | Last Updated: {lastUpdated ? new Date(lastUpdated).toLocaleTimeString() : 'Never'}

) : (
{monitoringData.map((trade) => (
{/* Trade Header */}
{trade.side} {trade.symbol} {trade.status.replace('_', ' ')}
Current: {formatCurrency(trade.currentPrice)}
Entry: {formatCurrency(trade.entryPrice)}
{/* Trade Details Grid */}
P&L
{formatCurrency(trade.currentPnL)}
{formatPercentage(trade.pnlPercentage)}
Take Profit
{formatCurrency(trade.takeProfit)}
{trade.distanceToTP ? `${formatDistance(trade.distanceToTP)} away` : 'N/A'}
Stop Loss
{formatCurrency(trade.stopLoss)}
{trade.distanceToSL ? `${formatDistance(trade.distanceToSL)} away` : 'N/A'}
Status
{trade.status === 'CRITICAL' ? '🚨 Critical' : trade.status === 'APPROACHING_TP' ? '🎯 Near TP' : trade.status === 'APPROACHING_SL' ? '⚠️ Near SL' : '✅ Normal'}
))}
)}
) }