import { useColor } from '@/hooks/useColor'; import { useEffect } from 'react'; import { View, ViewStyle } from 'react-native'; import Animated, { useAnimatedProps, useSharedValue, withTiming, } from 'react-native-reanimated'; import Svg, { Circle, Defs, LinearGradient, Stop, Text as SvgText, } from 'react-native-svg'; // Animated SVG Components const AnimatedCircle = Animated.createAnimatedComponent(Circle); interface ChartConfig { animated?: boolean; duration?: number; gradient?: boolean; } type Props = { progress: number; // 0-100 size?: number; strokeWidth?: number; config?: ChartConfig; style?: ViewStyle; showLabel?: boolean; label?: string; centerText?: string; }; export const ProgressRingChart = ({ progress, size = 120, strokeWidth = 8, config = {}, style, showLabel = true, label, centerText, }: Props) => { const { animated = true, duration = 1000, gradient = false } = config; const primaryColor = useColor('primary'); const mutedColor = useColor('mutedForeground'); const animationProgress = useSharedValue(0); useEffect(() => { if (animated) { animationProgress.value = withTiming(1, { duration }); } else { animationProgress.value = 1; } }, [progress, animated, duration]); const radius = (size - strokeWidth) / 2; const circumference = 2 * Math.PI * radius; const center = size / 2; const progressAnimatedProps = useAnimatedProps(() => { const animatedProgress = animationProgress.value * (progress / 100); const strokeDashoffset = circumference - animatedProgress * circumference; return { strokeDashoffset, }; }); return ( {showLabel && label && ( {label} )} {gradient && ( )} {/* Background circle */} {/* Progress circle */} {/* Center text */} {centerText && ( {centerText} )} {/* Progress percentage */} {!centerText && ( {Math.round(progress)}% )} ); };