Files
AthenaFE/components/ui/RiskScoreIndicator.tsx
2025-11-02 10:08:56 +01:00

94 lines
2.4 KiB
TypeScript

import { useCallback, useEffect, useState } from "react";
import { Text, View } from "react-native";
import PieChart from "react-native-pie-chart";
import { getRiskLevel } from "@/utils/getRiskLevel";
interface RiskScoreIndicatorProps {
value: number;
maxValue?: number;
size?: number;
subtitle?: string;
}
/**
* RiskScoreIndicator component displays a visual representation of risk level
* using PieChart from react-native-pie-chart
*/
export const RiskScoreIndicator = ({
value,
maxValue = 100,
size = 100,
subtitle,
}: RiskScoreIndicatorProps) => {
const { color } = getRiskLevel(value);
const [animatedValue, setAnimatedValue] = useState(0.1);
const finalValue = value > 0 ? value : 0.1;
const animationSetup = useCallback(() => {
const startTime = Date.now();
const duration = 1000;
const animate = () => {
const elapsed = Date.now() - startTime;
const progress = Math.min(elapsed / duration, 1);
const easeOut = (t: number) => 1 - Math.pow(1 - t, 2);
const currentValue = 0.1 + easeOut(progress) * (finalValue - 0.1);
setAnimatedValue(currentValue);
if (progress < 1) {
requestAnimationFrame(animate);
}
};
const animationFrame = requestAnimationFrame(animate);
return () => cancelAnimationFrame(animationFrame);
}, [finalValue]);
useEffect(() => {
animationSetup();
}, [animationSetup]);
return (
<View className="items-center">
<View
className="relative justify-center items-center bg-white p-3 rounded-full"
style={{
width: size,
height: size,
}}
>
<View className="absolute rotate-[-145deg]">
<PieChart
widthAndHeight={size - 12}
series={[
{
value: animatedValue,
color,
},
{
value:
maxValue - animatedValue > 0 ? maxValue - animatedValue : 0.1,
color: "white",
},
{ value: maxValue / 4, color: "transparent" },
]}
cover={{ radius: 0.8, color: "white" }}
/>
</View>
<View className="absolute bottom-10 items-center">
<Text className="text-black text-3xl font-normal">
{Math.round(value)}
</Text>
</View>
</View>
{subtitle && <Text className="text-black text-sm mt-2">{subtitle}</Text>}
</View>
);
};