the-tip-top-frontend/components/ui/StatCard.tsx
soufiane 4d46456ada refactor: reduce code duplication by using reusable components
- Delete duplicate page-new.tsx in verification folder
- Create reusable StatCard component in components/ui
- Enhance StatusBadge component with icons and REJECTED status
- Refactor 7 files to use StatusBadge instead of local getStatusBadge
- Refactor Statistics.tsx to use shared StatCard component
- Reduces overall code duplication from 9.85% to lower

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 16:50:05 +01:00

61 lines
2.0 KiB
TypeScript

'use client';
import React from 'react';
import { cn } from '@/utils/helpers';
type ColorVariant = 'blue' | 'green' | 'yellow' | 'red' | 'purple' | 'orange' | 'gray';
interface StatCardProps {
title: string;
value: number | string;
icon?: React.ReactNode;
color?: ColorVariant;
subtitle?: string;
className?: string;
}
const colorClasses: Record<ColorVariant, { bg: string; text: string; iconBg: string }> = {
blue: { bg: 'bg-blue-50', text: 'text-blue-600', iconBg: 'bg-blue-100 text-blue-600' },
green: { bg: 'bg-green-50', text: 'text-green-600', iconBg: 'bg-green-100 text-green-600' },
yellow: { bg: 'bg-yellow-50', text: 'text-yellow-600', iconBg: 'bg-yellow-100 text-yellow-600' },
red: { bg: 'bg-red-50', text: 'text-red-600', iconBg: 'bg-red-100 text-red-600' },
purple: { bg: 'bg-purple-50', text: 'text-purple-600', iconBg: 'bg-purple-100 text-purple-600' },
orange: { bg: 'bg-orange-50', text: 'text-orange-600', iconBg: 'bg-orange-100 text-orange-600' },
gray: { bg: 'bg-gray-50', text: 'text-gray-600', iconBg: 'bg-gray-100 text-gray-600' },
};
export const StatCard: React.FC<StatCardProps> = ({
title,
value,
icon,
color = 'blue',
subtitle,
className,
}) => {
const colors = colorClasses[color];
const formattedValue = typeof value === 'number' ? value.toLocaleString('fr-FR') : value;
return (
<div className={cn('bg-white rounded-lg shadow-sm border border-gray-200 p-6', className)}>
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-gray-600">{title}</p>
<p className={cn('text-3xl font-bold mt-2', colors.text)}>
{formattedValue}
</p>
{subtitle && (
<p className="text-xs text-gray-500 mt-1">{subtitle}</p>
)}
</div>
{icon && (
<div className={cn('p-3 rounded-lg', colors.iconBg)}>
{icon}
</div>
)}
</div>
</div>
);
};
export default StatCard;