106 lines
2.9 KiB
TypeScript
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,
|
|
},
|
|
});
|