QuantumShield / frontend /components /RiskDistributionCard.tsx
SantoshKumar1310's picture
Upload folder using huggingface_hub
49e53ae verified
'use client';
import { TrendingUp, TrendingDown, Activity } from 'lucide-react';
interface RiskDistributionCardProps {
lowRisk: number;
mediumRisk: number;
highRisk: number;
criticalRisk: number;
}
export default function RiskDistributionCard({
lowRisk,
mediumRisk,
highRisk,
criticalRisk
}: RiskDistributionCardProps) {
const total = lowRisk + mediumRisk + highRisk + criticalRisk;
const data = [
{ label: 'Low Risk', value: lowRisk, color: 'bg-emerald-400', percentage: (lowRisk / total * 100).toFixed(1) },
{ label: 'Medium Risk', value: mediumRisk, color: 'bg-yellow-400', percentage: (mediumRisk / total * 100).toFixed(1) },
{ label: 'High Risk', value: highRisk, color: 'bg-orange-400', percentage: (highRisk / total * 100).toFixed(1) },
{ label: 'Critical', value: criticalRisk, color: 'bg-red-400', percentage: (criticalRisk / total * 100).toFixed(1) },
];
// Create a simple scatter-like visualization
const generatePoints = () => {
const points: { x: number; y: number; risk: string; color: string }[] = [];
// Generate clustered points for each risk level
data.forEach((item, riskIndex) => {
const count = Math.min(item.value, 30); // Cap at 30 points per category
for (let i = 0; i < count; i++) {
const baseX = 20 + (riskIndex * 20) + Math.random() * 15;
const baseY = 20 + Math.random() * 60;
points.push({
x: Math.min(95, Math.max(5, baseX)),
y: Math.min(95, Math.max(5, baseY)),
risk: item.label,
color: item.color.replace('bg-', '')
});
}
});
return points;
};
const points = generatePoints();
return (
<div className="card-teal rounded-3xl p-6 card-hover h-full">
{/* Header */}
<div className="flex items-center justify-between mb-4">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-xl bg-white/20 flex items-center justify-center">
<Activity className="w-5 h-5" />
</div>
<div>
<h3 className="text-xl font-bold">RISK DISTRIBUTION</h3>
<p className="text-xs text-white/60">Transaction Risk Mapping</p>
</div>
</div>
<button className="text-white/60 hover:text-white transition-colors">
<svg className="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<circle cx="11" cy="11" r="8" />
<path d="m21 21-4.35-4.35" />
</svg>
</button>
</div>
{/* Scatter Plot Visualization */}
<div className="relative h-40 mb-4 bg-white/10 rounded-2xl overflow-hidden">
{/* Grid lines */}
<div className="absolute inset-0">
{[...Array(5)].map((_, i) => (
<div key={`h-${i}`} className="absolute w-full border-t border-white/10" style={{ top: `${i * 25}%` }} />
))}
{[...Array(5)].map((_, i) => (
<div key={`v-${i}`} className="absolute h-full border-l border-white/10" style={{ left: `${i * 25}%` }} />
))}
</div>
{/* Points */}
{points.map((point, i) => {
const colorMap: Record<string, string> = {
'emerald-400': '#34d399',
'yellow-400': '#facc15',
'orange-400': '#fb923c',
'red-400': '#f87171'
};
return (
<div
key={i}
className="absolute w-2 h-2 rounded-full animate-float"
style={{
left: `${point.x}%`,
top: `${point.y}%`,
backgroundColor: colorMap[point.color] || '#fff',
animationDelay: `${i * 0.1}s`,
opacity: 0.8
}}
/>
);
})}
</div>
{/* Legend & Stats */}
<div className="grid grid-cols-2 gap-2">
{data.map((item) => (
<div key={item.label} className="flex items-center gap-2 bg-white/10 rounded-xl p-2">
<div className={`w-3 h-3 rounded-full ${item.color}`} />
<div className="flex-1">
<p className="text-xs text-white/80">{item.label}</p>
<div className="flex items-baseline gap-1">
<span className="text-sm font-bold">{item.value}</span>
<span className="text-xs text-white/60">({item.percentage}%)</span>
</div>
</div>
</div>
))}
</div>
{/* Trend indicator */}
<div className="mt-4 flex items-center justify-between text-sm">
<span className="text-white/60">Risk Trend</span>
<div className="flex items-center gap-1 text-emerald-300">
<TrendingDown className="w-4 h-4" />
<span>-2.3% this week</span>
</div>
</div>
</div>
);
}