import React, { useEffect } from 'react'; import { View, Text, StyleSheet } from 'react-native'; import { LinearGradient } from 'expo-linear-gradient'; import { useSharedValue, withTiming } from 'react-native-reanimated'; import { Colors, Fonts, FontSize, BorderRadius, Shadows, Spacing } from '@/constants/theme'; import { formatNumber } from '@/utils/format'; import { useTradingData } from '@/providers/TradingDataProvider'; function CountUpValue({ target, prefix, suffix, style, duration = 800 }: { target: number; prefix?: string; suffix?: string; style: any; duration?: number; }) { const [display, setDisplay] = React.useState('0'); const value = useSharedValue(0); useEffect(() => { value.value = withTiming(target, { duration }); }, [target]); useEffect(() => { const interval = setInterval(() => { const current = value.value; if (Math.abs(current) >= 1000) { setDisplay(current.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })); } else { setDisplay(current.toFixed(2)); } }, 16); return () => clearInterval(interval); }, []); return ( {prefix}{display}{suffix} ); } export default function PortfolioHeroCard() { const { portfolio } = useTradingData(); const positive = portfolio.netPnl >= 0; return ( PORTFOLIO OVERVIEW {portfolio.utilization.toFixed(1)}% utilized Realized P&L {portfolio.realizedPnl >= 0 ? '+' : '-'}${Math.abs(portfolio.realizedPnl).toLocaleString('en-US', { minimumFractionDigits: 2 })} Unrealized P&L {portfolio.unrealizedPnl >= 0 ? '+' : '-'}${Math.abs(portfolio.unrealizedPnl).toLocaleString('en-US', { minimumFractionDigits: 2 })} ); } function MetricItem({ label, value }: { label: string; value: string }) { return ( {label} {value} ); } const styles = StyleSheet.create({ wrapper: { borderRadius: BorderRadius.large, overflow: 'hidden', }, card: { borderRadius: BorderRadius.large, padding: Spacing.cardPaddingLarge, borderWidth: 1, borderColor: Colors.border.default, overflow: 'hidden', }, accentLine: { position: 'absolute', top: 0, left: 0, right: 0, height: 2, backgroundColor: Colors.accent.green, opacity: 0.6, }, label: { fontFamily: Fonts.inter.black, fontSize: FontSize.micro, color: Colors.accent.green, letterSpacing: 4, marginBottom: 16, }, heroValue: { fontFamily: Fonts.mono.extraBold, fontSize: FontSize.pageTitle, color: Colors.accent.green, letterSpacing: -0.5, }, heroPercent: { fontFamily: Fonts.mono.bold, fontSize: FontSize.bodyLarge, color: Colors.accent.green, marginTop: 2, }, divider: { height: 1, backgroundColor: Colors.border.default, marginVertical: 16, }, metricsRow: { flexDirection: 'row', justifyContent: 'space-between', }, metricItem: { flex: 1, }, metricLabel: { fontFamily: Fonts.inter.black, fontSize: FontSize.micro, color: Colors.text.secondary, letterSpacing: 1, marginBottom: 4, }, metricValue: { fontFamily: Fonts.mono.extraBold, fontSize: FontSize.subheading, color: Colors.text.primary, }, utilizationContainer: { marginTop: 16, }, utilizationTrack: { height: 4, borderRadius: 2, backgroundColor: Colors.background.elevated, overflow: 'hidden', }, utilizationFill: { height: 4, borderRadius: 2, }, utilizationText: { fontFamily: Fonts.inter.medium, fontSize: FontSize.micro, color: Colors.text.secondary, marginTop: 6, }, pnlRow: { flexDirection: 'row', marginTop: 16, gap: 24, }, pnlItem: { flex: 1, }, pnlLabel: { fontFamily: Fonts.inter.medium, fontSize: FontSize.micro, color: Colors.text.secondary, marginBottom: 2, }, pnlValue: { fontFamily: Fonts.mono.bold, fontSize: FontSize.body, }, });