11import React from 'react' ;
22import { Server , ShieldCheck , Lock , Puzzle } from 'lucide-react' ;
3- import { Card } from '../ui/card' ;
3+ import { Card , CardContent } from '../ui/card' ;
44import { cn } from '../../lib/utils' ;
55
66const icons = {
@@ -10,51 +10,62 @@ const icons = {
1010 puzzle : Puzzle ,
1111} ;
1212
13+ /**
14+ * Stat card component for displaying dashboard statistics
15+ * 100% Shadcn UI with proper Card/CardContent structure
16+ */
1317const StatCard = ( { title, value, subtitle = null , status = null , icon = null } ) => {
14- let statusClasses = '' ;
18+ let borderColor = 'border-l-border ' ;
1519 let iconColor = 'text-muted-foreground' ;
20+ let bgColor = 'bg-muted/50' ;
1621
1722 if ( status ) {
1823 switch ( status ) {
1924 case 'success' :
20- statusClasses = 'border-l-4 border-green-500' ;
21- iconColor = 'text-green-500' ;
25+ borderColor = 'border-l-green-500 dark:border-l-green-400' ;
26+ iconColor = 'text-green-600 dark:text-green-400' ;
27+ bgColor = 'bg-green-100 dark:bg-green-900/20' ;
2228 break ;
2329 case 'warning' :
24- statusClasses = 'border-l-4 border-yellow-500' ;
25- iconColor = 'text-yellow-500' ;
30+ borderColor = 'border-l-yellow-500 dark:border-l-yellow-400' ;
31+ iconColor = 'text-yellow-600 dark:text-yellow-400' ;
32+ bgColor = 'bg-yellow-100 dark:bg-yellow-900/20' ;
2633 break ;
2734 case 'danger' :
28- statusClasses = 'border-l-4 border-red-500' ;
29- iconColor = 'text-red-500' ;
35+ borderColor = 'border-l-red-500 dark:border-l-red-400' ;
36+ iconColor = 'text-red-600 dark:text-red-400' ;
37+ bgColor = 'bg-red-100 dark:bg-red-900/20' ;
3038 break ;
3139 case 'neutral' :
32- statusClasses = 'border-l-4 border-gray-400' ;
33- iconColor = 'text-gray-500' ;
40+ borderColor = 'border-l-gray-400 dark:border-l-gray-500' ;
41+ iconColor = 'text-gray-500 dark:text-gray-400' ;
42+ bgColor = 'bg-gray-100 dark:bg-gray-800/50' ;
3443 break ;
3544 default :
36- statusClasses = 'border-l-4 border -border' ;
45+ borderColor = 'border-l-border' ;
3746 }
38- } else {
39- statusClasses = 'border-l-4 border-border' ;
4047 }
4148
4249 const IconComponent = icon ? icons [ icon ] : null ;
4350
4451 return (
45- < Card className = { cn ( 'flex items-start p-4 sm:p-6' , statusClasses ) } >
46- { IconComponent && (
47- < div className = { cn ( 'flex-shrink-0 mr-4 p-2 bg-secondary rounded-full' , iconColor ) } >
48- < IconComponent className = "h-6 w-6" />
49- </ div >
50- ) }
51- < div className = "flex-1" >
52- < h3 className = "text-sm font-medium text-muted-foreground uppercase tracking-wider" > { title } </ h3 >
53- < p className = "mt-1 text-3xl font-semibold" > { value } </ p >
54- { subtitle && (
55- < p className = "mt-1 text-sm text-muted-foreground" > { subtitle } </ p >
52+ < Card className = { cn ( 'border-l-4' , borderColor ) } >
53+ < CardContent className = "flex items-start gap-4 p-6" >
54+ { IconComponent && (
55+ < div className = { cn ( 'p-3 rounded-full flex-shrink-0' , bgColor , iconColor ) } >
56+ < IconComponent className = "h-6 w-6" />
57+ </ div >
5658 ) }
57- </ div >
59+ < div className = "flex-1 space-y-1" >
60+ < p className = "text-sm font-medium text-muted-foreground uppercase tracking-wide" >
61+ { title }
62+ </ p >
63+ < p className = "text-3xl font-bold" > { value } </ p >
64+ { subtitle && (
65+ < p className = "text-sm text-muted-foreground" > { subtitle } </ p >
66+ ) }
67+ </ div >
68+ </ CardContent >
5869 </ Card >
5970 ) ;
6071} ;
0 commit comments