learning_ai_invt_trdg/mobile/components/dashboard/MarketTicker.tsx

106 lines
2.9 KiB
TypeScript

import React, { useEffect } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import Animated, {
useSharedValue,
useAnimatedStyle,
withRepeat,
withTiming,
Easing,
} from 'react-native-reanimated';
import { TrendingUp } from 'lucide-react-native';
import { Colors, Fonts, FontSize, BorderRadius } from '@/constants/theme';
import { useTradingData } from '@/providers/TradingDataProvider';
export default function MarketTicker() {
const { marketTicker } = useTradingData();
const translateX = useSharedValue(0);
useEffect(() => {
translateX.value = withRepeat(
withTiming(-600, { duration: 30000, easing: Easing.linear }),
-1
);
}, []);
const animStyle = useAnimatedStyle(() => ({
transform: [{ translateX: translateX.value }],
}));
const items = [...marketTicker, ...marketTicker, ...marketTicker];
return (
<View style={styles.container}>
<View style={styles.header}>
<TrendingUp size={14} color={Colors.accent.green} />
<Text style={styles.headerText}>MARKET PULSE</Text>
</View>
<View style={styles.tickerWrap}>
<Animated.View style={[styles.tickerRow, animStyle]}>
{items.map((item, index) => {
const isPositive = item.change >= 0;
return (
<View key={`${item.symbol}-${index}`} style={styles.tickerItem}>
<Text style={styles.symbol}>{item.symbol}</Text>
<Text style={styles.price}>
${item.price >= 1 ? item.price.toLocaleString('en-US', { minimumFractionDigits: 2 }) : item.price.toFixed(4)}
</Text>
<Text style={[styles.change, { color: isPositive ? Colors.accent.green : Colors.accent.red }]}>
{isPositive ? '▲' : '▼'} {isPositive ? '+' : ''}{item.change.toFixed(2)}%
</Text>
</View>
);
})}
</Animated.View>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor: Colors.background.card,
borderRadius: BorderRadius.small,
padding: 14,
borderWidth: 1,
borderColor: Colors.border.default,
},
header: {
flexDirection: 'row',
alignItems: 'center',
gap: 6,
marginBottom: 12,
},
headerText: {
fontFamily: Fonts.inter.black,
fontSize: FontSize.micro,
color: Colors.accent.green,
letterSpacing: 1.5,
},
tickerWrap: {
overflow: 'hidden',
},
tickerRow: {
flexDirection: 'row',
gap: 24,
},
tickerItem: {
flexDirection: 'row',
alignItems: 'center',
gap: 8,
},
symbol: {
fontFamily: Fonts.inter.extraBold,
fontSize: FontSize.badge,
color: Colors.text.primary,
},
price: {
fontFamily: Fonts.mono.medium,
fontSize: FontSize.badge,
color: Colors.text.primary,
},
change: {
fontFamily: Fonts.mono.bold,
fontSize: FontSize.badge,
},
});