project setup
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
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>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user