22
33import { LucideIcon } from 'lucide-react' ;
44import { cn } from '@/lib/utils' ;
5+ import { useTheme } from '@/hooks/useTheme' ;
56
67interface StatsCardProps {
78 title : string ;
@@ -11,39 +12,86 @@ interface StatsCardProps {
1112 value : number ;
1213 isPositive : boolean ;
1314 } ;
14- color ?: 'blue' | 'green' | 'red' | 'yellow' | 'purple' ;
15+ color ?: 'blue' | 'green' | 'red' | 'yellow' | 'purple' | 'orange' ;
1516}
1617
1718export default function StatsCard ( { title, value, icon : Icon , trend, color = 'blue' } : StatsCardProps ) {
18- const colorClasses = {
19- blue : 'from-blue-500/10 to-blue-600/10 border-blue-500/20 text-blue-500' ,
20- green : 'from-green-500/10 to-green-600/10 border-green-500/20 text-green-500' ,
21- red : 'from-red-500/10 to-red-600/10 border-red-500/20 text-red-500' ,
22- yellow : 'from-yellow-500/10 to-yellow-600/10 border-yellow-500/20 text-yellow-500' ,
23- purple : 'from-purple-500/10 to-purple-600/10 border-purple-500/20 text-purple-500' ,
19+ const { theme, textPrimary, textSecondary } = useTheme ( ) ;
20+
21+ const getColorClasses = ( ) => {
22+ const colors = {
23+ blue : {
24+ light : 'from-blue-50 to-blue-100 border-blue-200 hover:from-blue-100 hover:to-blue-200' ,
25+ dark : 'from-blue-500/10 to-blue-600/20 border-blue-500/30 hover:from-blue-500/20 hover:to-blue-600/30' ,
26+ icon : 'bg-blue-500/20' ,
27+ iconDark : 'bg-blue-500/10' ,
28+ text : theme === 'light' ? 'text-blue-700' : 'text-blue-400' ,
29+ } ,
30+ green : {
31+ light : 'from-green-50 to-green-100 border-green-200 hover:from-green-100 hover:to-green-200' ,
32+ dark : 'from-green-500/10 to-green-600/20 border-green-500/30 hover:from-green-500/20 hover:to-green-600/30' ,
33+ icon : 'bg-green-500/20' ,
34+ iconDark : 'bg-green-500/10' ,
35+ text : theme === 'light' ? 'text-green-700' : 'text-green-400' ,
36+ } ,
37+ red : {
38+ light : 'from-red-50 to-red-100 border-red-200 hover:from-red-100 hover:to-red-200' ,
39+ dark : 'from-red-500/10 to-red-600/20 border-red-500/30 hover:from-red-500/20 hover:to-red-600/30' ,
40+ icon : 'bg-red-500/20' ,
41+ iconDark : 'bg-red-500/10' ,
42+ text : theme === 'light' ? 'text-red-700' : 'text-red-400' ,
43+ } ,
44+ yellow : {
45+ light : 'from-yellow-50 to-yellow-100 border-yellow-200 hover:from-yellow-100 hover:to-yellow-200' ,
46+ dark : 'from-yellow-500/10 to-yellow-600/20 border-yellow-500/30 hover:from-yellow-500/20 hover:to-yellow-600/30' ,
47+ icon : 'bg-yellow-500/20' ,
48+ iconDark : 'bg-yellow-500/10' ,
49+ text : theme === 'light' ? 'text-yellow-700' : 'text-yellow-400' ,
50+ } ,
51+ purple : {
52+ light : 'from-purple-50 to-purple-100 border-purple-200 hover:from-purple-100 hover:to-purple-200' ,
53+ dark : 'from-purple-500/10 to-purple-600/20 border-purple-500/30 hover:from-purple-500/20 hover:to-purple-600/30' ,
54+ icon : 'bg-purple-500/20' ,
55+ iconDark : 'bg-purple-500/10' ,
56+ text : theme === 'light' ? 'text-purple-700' : 'text-purple-400' ,
57+ } ,
58+ orange : {
59+ light : 'from-orange-50 to-orange-100 border-orange-200 hover:from-orange-100 hover:to-orange-200' ,
60+ dark : 'from-orange-500/10 to-orange-600/20 border-orange-500/30 hover:from-orange-500/20 hover:to-orange-600/30' ,
61+ icon : 'bg-orange-500/20' ,
62+ iconDark : 'bg-orange-500/10' ,
63+ text : theme === 'light' ? 'text-orange-700' : 'text-orange-400' ,
64+ } ,
65+ } ;
66+ return colors [ color ] ;
2467 } ;
2568
69+ const colorClasses = getColorClasses ( ) ;
70+
2671 return (
2772 < div className = { cn (
2873 'bg-gradient-to-br border rounded-xl p-6 transition-all hover:scale-105' ,
29- colorClasses [ color ]
74+ theme === 'light' ? ` ${ colorClasses . light } shadow-sm hover:shadow-md` : colorClasses . dark
3075 ) } >
3176 < div className = "flex items-start justify-between" >
3277 < div >
33- < p className = " text-zinc-400 text- sm font-medium mb-2" > { title } </ p >
34- < p className = " text-3xl font-bold text-white mb-1" > { value } </ p >
78+ < p className = { ` text-sm font-medium mb-2 ${ colorClasses . text } ` } > { title } </ p >
79+ < p className = { ` text-3xl font-bold mb-1 ${ textPrimary } ` } > { value } </ p >
3580 { trend && (
3681 < div className = { cn (
3782 'text-xs font-medium flex items-center gap-1' ,
38- trend . isPositive ? 'text-green-400 ' : 'text-red-400 '
83+ trend . isPositive ? 'text-green-500 ' : 'text-red-500 '
3984 ) } >
4085 < span > { trend . isPositive ? '↗' : '↘' } </ span >
4186 < span > { Math . abs ( trend . value ) } %</ span >
4287 </ div >
4388 ) }
4489 </ div >
45- < div className = { cn ( 'p-3 rounded-lg' , colorClasses [ color ] ) } >
46- < Icon className = "w-6 h-6" />
90+ < div className = { cn (
91+ 'p-3 rounded-lg' ,
92+ theme === 'light' ? colorClasses . icon : colorClasses . iconDark
93+ ) } >
94+ < Icon className = { `w-6 h-6 ${ colorClasses . text . replace ( 'text-' , 'text-' ) } ` } />
4795 </ div >
4896 </ div >
4997 </ div >
0 commit comments