127 lines
3.5 KiB
JavaScript
127 lines
3.5 KiB
JavaScript
import React from 'react';
|
|
import { cn } from '@/lib/utils';
|
|
import { TrendingUp, TrendingDown, Minus } from 'lucide-react';
|
|
|
|
/**
|
|
* DashboardKPICard - Versão de Produção
|
|
* Componente de alta fidelidade visual para exibição de KPIs.
|
|
*/
|
|
export const DashboardKPICard = ({
|
|
label,
|
|
value,
|
|
subtitle,
|
|
trend,
|
|
trendDirection = 'stable',
|
|
icon: Icon,
|
|
color = 'blue',
|
|
className
|
|
}) => {
|
|
|
|
// Mapeamento de cores para bordas e backgrounds de ícones
|
|
const colorStyles = {
|
|
blue: {
|
|
border: 'border-l-[#3b82f6]',
|
|
iconBg: 'bg-gradient-to-br from-[#3b82f6] to-[#1d4ed8]',
|
|
iconShadow: 'shadow-[#3b82f6]/20'
|
|
},
|
|
green: {
|
|
border: 'border-l-[#10b981]',
|
|
iconBg: 'bg-gradient-to-br from-[#10b981] to-[#059669]',
|
|
iconShadow: 'shadow-[#10b981]/20'
|
|
},
|
|
orange: {
|
|
border: 'border-l-[#f59e0b]',
|
|
iconBg: 'bg-gradient-to-br from-[#f59e0b] to-[#d97706]',
|
|
iconShadow: 'shadow-[#f59e0b]/20'
|
|
},
|
|
red: {
|
|
border: 'border-l-[#ef4444]',
|
|
iconBg: 'bg-gradient-to-br from-[#ef4444] to-[#b91c1c]',
|
|
iconShadow: 'shadow-[#ef4444]/20'
|
|
},
|
|
workspace: {
|
|
border: 'border-l-[#26b1c7]',
|
|
iconBg: 'bg-gradient-to-br from-[#26b1c7] to-[#003153]',
|
|
iconShadow: 'shadow-[#26b1c7]/20'
|
|
}
|
|
};
|
|
|
|
const style = colorStyles[color] || colorStyles.blue;
|
|
|
|
// Estilos para a badge de tendência
|
|
const trendStyles = {
|
|
up: {
|
|
text: 'text-[#10b981]',
|
|
bg: 'bg-[#10b981]/10',
|
|
icon: <TrendingUp size={12} />
|
|
},
|
|
down: {
|
|
text: 'text-[#ef4444]',
|
|
bg: 'bg-[#ef4444]/10',
|
|
icon: <TrendingDown size={12} />
|
|
},
|
|
stable: {
|
|
text: 'text-slate-500',
|
|
bg: 'bg-slate-500/10',
|
|
icon: <Minus size={12} />
|
|
}
|
|
};
|
|
|
|
const currentTrend = trendStyles[trendDirection] || trendStyles.stable;
|
|
|
|
return (
|
|
<div className={cn(
|
|
"relative bg-[#1c1c1c] rounded-[32px] p-6 border-l-4 shadow-xl transition-all hover:translate-y-[-2px] hover:shadow-2xl",
|
|
style.border,
|
|
className
|
|
)}>
|
|
{/* Header Area */}
|
|
<div className="flex items-center justify-between mb-6">
|
|
<div className="flex items-center gap-3">
|
|
{/* Icon Container */}
|
|
<div className={cn(
|
|
"w-12 h-12 rounded-[20px] flex items-center justify-center shadow-lg",
|
|
style.iconBg,
|
|
style.iconShadow
|
|
)}>
|
|
{Icon && <Icon size={24} className="text-white" />}
|
|
</div>
|
|
|
|
{/* Label */}
|
|
<span className="text-[15px] font-bold text-white tracking-tight uppercase">
|
|
{label}
|
|
</span>
|
|
</div>
|
|
|
|
{/* Trend Badge */}
|
|
{trend && (
|
|
<div className={cn(
|
|
"flex items-center gap-1.5 px-2.5 py-1 rounded-full text-[11px] font-black tracking-tight",
|
|
currentTrend.bg,
|
|
currentTrend.text
|
|
)}>
|
|
{currentTrend.icon}
|
|
{trend}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Value Area */}
|
|
<div className="space-y-1">
|
|
<h3 className="text-2xl font-black text-white leading-none tracking-tight truncate">
|
|
{value}
|
|
</h3>
|
|
|
|
{subtitle && (
|
|
<p className="text-[11px] font-bold text-slate-500 leading-tight uppercase tracking-wide max-w-[200px]">
|
|
{subtitle}
|
|
</p>
|
|
)}
|
|
</div>
|
|
|
|
{/* Glassy Overlay effect (optional for premium feel) */}
|
|
<div className="absolute top-0 right-0 w-32 h-32 bg-white/5 blur-3xl rounded-full -mr-16 -mt-16 pointer-events-none" />
|
|
</div>
|
|
);
|
|
};
|