Files
shorturl-analytics/app/components/dashboard/StatsCard.tsx
2025-03-21 12:08:37 +08:00

72 lines
2.1 KiB
TypeScript

interface StatsCardProps {
title: string;
value: string | number;
change: number;
unit?: string;
colorScheme?: 'blue' | 'green' | 'red' | 'purple';
}
export default function StatsCard({
title,
value,
change,
unit = '',
colorScheme = 'blue'
}: StatsCardProps) {
const isPositive = change >= 0;
const hasPercentUnit = unit === '%';
// Color mappings based on the colorScheme
const gradientBg = {
blue: 'bg-gradient-blue',
green: 'bg-gradient-green',
red: 'bg-gradient-red',
purple: 'bg-gradient-purple',
}[colorScheme];
const accentColor = {
blue: 'text-accent-blue',
green: 'text-accent-green',
red: 'text-accent-red',
purple: 'text-accent-purple',
}[colorScheme];
return (
<div className="bg-card-bg border border-card-border rounded-lg overflow-hidden">
{/* Colorful top bar */}
<div className={`h-1 ${gradientBg}`}></div>
<div className="p-5">
<h2 className="text-text-secondary text-sm font-medium mb-2">{title}</h2>
<div className="flex flex-col">
<div className="flex items-baseline">
<p className={`text-3xl font-bold ${accentColor}`}>
{value}
{hasPercentUnit && <span className={accentColor}>%</span>}
</p>
<div className={`ml-3 px-2 py-0.5 rounded-md text-sm font-medium flex items-center ${
isPositive ? 'text-accent-green' : 'text-accent-red'
}`}>
<span className={`inline-block w-2 h-2 rounded-full mr-1 ${
isPositive ? 'bg-accent-green' : 'bg-accent-red'
}`}></span>
{isPositive ? '+' : ''}{change}%
</div>
</div>
{/* Visual indicator for percentages */}
{hasPercentUnit && (
<div className="mt-3 w-full bg-progress-bg h-2 rounded-full overflow-hidden">
<div
className={`${gradientBg} h-full rounded-full`}
style={{ width: `${Math.min(Number(value), 100)}%` }}
></div>
</div>
)}
</div>
</div>
</div>
);
}