learning_ai_invt_trdg/web/src/components/LivePulseTicker.tsx

89 lines
4.5 KiB
TypeScript

import React from 'react';
import type { BotState } from '../hooks/useWebSocket';
import { TrendingUp, Zap } from 'lucide-react';
interface LivePulseTickerProps {
botState: BotState;
}
export const LivePulseTicker: React.FC<LivePulseTickerProps> = ({ botState }) => {
const symbols = Object.keys(botState.symbols);
const volatileSymbols = symbols
.sort((a, b) => Math.abs(botState.symbols[b].change24h || 0) - Math.abs(botState.symbols[a].change24h || 0))
.slice(0, 8);
const aiSetups = symbols
.filter(s => botState.symbols[s].rules['AIAnalysisRule']?.metadata?.confidence !== undefined)
.sort((a, b) => (botState.symbols[b].rules['AIAnalysisRule']?.metadata?.confidence || 0) - (botState.symbols[a].rules['AIAnalysisRule']?.metadata?.confidence || 0))
.slice(0, 3);
return (
<div style={{
height: '40px',
background: 'rgba(10, 11, 13, 0.95)',
backdropFilter: 'blur(10px)',
borderTop: '1px solid rgba(255, 255, 255, 0.05)',
borderBottom: '1px solid rgba(255, 255, 255, 0.05)',
display: 'flex',
alignItems: 'center',
overflow: 'hidden',
position: 'sticky',
top: '0',
zIndex: 1000,
padding: '0 24px'
}}>
{/* Market Ticker Section */}
<div style={{ display: 'flex', alignItems: 'center', gap: '8px', borderRight: '1px solid rgba(255,255,255,0.1)', paddingRight: '16px', marginRight: '16px' }}>
<TrendingUp size={14} className="text-[#00ff88]" />
<span style={{ fontSize: '10px', fontWeight: 900, color: '#444', textTransform: 'uppercase', letterSpacing: '1px' }}>Market Pulse</span>
</div>
<div className="ticker-scroll" style={{ display: 'flex', gap: '24px', flex: 1 }}>
{volatileSymbols.map(s => {
const change = botState.symbols[s].change24h || 0;
return (
<div key={s} style={{ display: 'flex', alignItems: 'center', gap: '6px', whiteSpace: 'nowrap' }}>
<span style={{ fontSize: '11px', fontWeight: 800, color: '#aaa' }}>{s.split('/')[0]}</span>
<span style={{
fontSize: '11px',
fontWeight: 900,
color: change >= 0 ? '#00ff88' : '#ff3366',
fontFamily: 'monospace'
}}>
{change >= 0 ? '+' : ''}{change.toFixed(2)}%
</span>
</div>
);
})}
</div>
{/* AI Highlight Section */}
<div style={{ display: 'flex', alignItems: 'center', gap: '16px', marginLeft: 'auto', background: 'rgba(0, 255, 136, 0.03)', padding: '0 16px', height: '100%', borderLeft: '1px solid rgba(0, 255, 136, 0.1)' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
<Zap size={14} className="text-[#00ff88]" fill="#00ff88" style={{ filter: 'drop-shadow(0 0 4px #00ff88)' }} />
<span style={{ fontSize: '10px', fontWeight: 900, color: '#00ff88', textTransform: 'uppercase', letterSpacing: '1px' }}>AI Top Picks</span>
</div>
<div style={{ display: 'flex', gap: '12px' }}>
{aiSetups.map(s => (
<div key={s} style={{ display: 'flex', alignItems: 'center', gap: '4px' }}>
<span style={{ fontSize: '11px', fontWeight: 800, color: '#fff' }}>{s.split('/')[0]}</span>
<span style={{ fontSize: '10px', fontWeight: 900, color: '#00ff88', opacity: 0.6 }}>{botState.symbols[s].rules['AIAnalysisRule']?.metadata?.confidence}%</span>
</div>
))}
{aiSetups.length === 0 && <span style={{ fontSize: '10px', fontWeight: 800, color: '#444' }}>SCANNING...</span>}
</div>
</div>
<style>{`
.ticker-scroll {
animation: ticker-slide 30s linear infinite;
}
@keyframes ticker-slide {
0% { transform: translateX(0); }
100% { transform: translateX(-20%); }
}
`}</style>
</div>
);
};