tyndale-ai-frontend/src/components/chat/TradingBackground.tsx

168 lines
5.2 KiB
TypeScript

interface Candle {
id: number
x: number
y: number
open: number
close: number
high: number
low: number
delay: number
duration: number
}
// Generate static candlesticks once
const generateCandles = (): Candle[] => {
const newCandles: Candle[] = []
const numCandles = 15
for (let i = 0; i < numCandles; i++) {
const open = Math.random() * 60 + 20
const movement = (Math.random() - 0.5) * 40
const close = open + movement
const high = Math.max(open, close) + Math.random() * 20
const low = Math.min(open, close) - Math.random() * 20
newCandles.push({
id: i,
x: Math.random() * 100,
y: Math.random() * 100,
open,
close,
high,
low,
delay: Math.random() * 5,
duration: 8 + Math.random() * 4,
})
}
return newCandles
}
const CANDLES = generateCandles()
const TradingBackground = () => {
return (
<div className="absolute inset-0 overflow-hidden pointer-events-none">
<svg className="w-full h-full" viewBox="0 0 100 100" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="bullishGradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stopColor="rgba(16, 185, 129, 0.5)" />
<stop offset="100%" stopColor="rgba(16, 185, 129, 0.2)" />
</linearGradient>
<linearGradient id="bearishGradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stopColor="rgba(239, 68, 68, 0.5)" />
<stop offset="100%" stopColor="rgba(239, 68, 68, 0.2)" />
</linearGradient>
</defs>
{CANDLES.map((candle) => {
const isBullish = candle.close > candle.open
const color = isBullish ? 'url(#bullishGradient)' : 'url(#bearishGradient)'
const strokeColor = isBullish ? 'rgba(16, 185, 129, 0.6)' : 'rgba(239, 68, 68, 0.6)'
const bodyTop = Math.min(candle.open, candle.close)
const bodyHeight = Math.abs(candle.close - candle.open)
const bodyWidth = 1.5
return (
<g
key={candle.id}
className="animate-pulse"
style={{
animationDelay: `${candle.delay}s`,
animationDuration: `${candle.duration}s`,
}}
>
{/* High-Low line (wick) */}
<line
x1={candle.x}
y1={candle.y - (candle.high - candle.close) / 3}
x2={candle.x}
y2={candle.y + (candle.close - candle.low) / 3}
stroke={strokeColor}
strokeWidth="0.3"
/>
{/* Candle body */}
<rect
x={candle.x - bodyWidth / 2}
y={candle.y - (bodyTop - candle.close) / 3}
width={bodyWidth}
height={bodyHeight / 3}
fill={color}
stroke={strokeColor}
strokeWidth="0.15"
rx="0.15"
/>
</g>
)
})}
{/* Animated trend lines - now spanning full width */}
<g className="animate-pulse" style={{ animationDuration: '6s' }}>
<path
d="M 0,30 Q 25,15 50,20 T 100,10"
stroke="rgba(96, 165, 250, 0.4)"
strokeWidth="0.5"
fill="none"
strokeDasharray="3,3"
vectorEffect="non-scaling-stroke"
>
<animate
attributeName="stroke-dashoffset"
from="0"
to="6"
dur="3s"
repeatCount="indefinite"
/>
</path>
</g>
<g className="animate-pulse" style={{ animationDuration: '8s', animationDelay: '1s' }}>
<path
d="M 0,70 Q 25,85 50,80 T 100,95"
stroke="rgba(168, 85, 247, 0.4)"
strokeWidth="0.5"
fill="none"
strokeDasharray="3,3"
vectorEffect="non-scaling-stroke"
>
<animate
attributeName="stroke-dashoffset"
from="0"
to="6"
dur="3s"
repeatCount="indefinite"
/>
</path>
</g>
<g className="animate-pulse" style={{ animationDuration: '7s', animationDelay: '0.5s' }}>
<path
d="M 0,50 Q 30,40 60,45 Q 80,50 100,55"
stroke="rgba(59, 130, 246, 0.35)"
strokeWidth="0.4"
fill="none"
strokeDasharray="2.5,2.5"
vectorEffect="non-scaling-stroke"
>
<animate
attributeName="stroke-dashoffset"
from="0"
to="5"
dur="4s"
repeatCount="indefinite"
/>
</path>
</g>
</svg>
{/* Floating gradient orbs */}
<div className="absolute top-1/4 left-1/4 w-96 h-96 bg-blue-500/10 rounded-full blur-3xl animate-pulse" style={{ animationDuration: '8s' }}></div>
<div className="absolute bottom-1/4 right-1/4 w-96 h-96 bg-purple-500/10 rounded-full blur-3xl animate-pulse" style={{ animationDuration: '10s', animationDelay: '2s' }}></div>
</div>
)
}
export default TradingBackground