All checks were successful
Build and Deploy / build-and-push (push) Successful in 1m54s
- Enforced tenant isolation and Role-Based Access Control across all API routes - Implemented secure profile avatar upload using multer and UUIDs - Redesigned UI with a premium "Onyx & Gold" Charcoal dark mode - Added Funnel Stage and Origin filters to Dashboard and User Detail pages - Replaced "Referral" with "Indicação" across the platform and database - Optimized Dockerfile and local environment setup for reliable deployments - Fixed frontend syntax errors and improved KPI/Chart visualizations
39 lines
1.8 KiB
TypeScript
39 lines
1.8 KiB
TypeScript
import React from 'react';
|
|
import { LucideIcon } from 'lucide-react';
|
|
|
|
interface KPICardProps {
|
|
title: string;
|
|
value: string | number;
|
|
subValue?: string;
|
|
trend?: 'up' | 'down' | 'neutral';
|
|
trendValue?: string;
|
|
icon: LucideIcon;
|
|
colorClass?: string;
|
|
}
|
|
|
|
export const KPICard: React.FC<KPICardProps> = ({ title, value, subValue, trend, trendValue, icon: Icon, colorClass = "text-blue-600" }) => {
|
|
// Extract base color from colorClass (e.g., 'text-yellow-600' -> 'yellow')
|
|
const baseColor = colorClass.split('-')[1] || 'blue';
|
|
|
|
return (
|
|
<div className="bg-white dark:bg-dark-card p-6 rounded-2xl shadow-sm border border-zinc-100 dark:border-dark-border flex flex-col justify-between hover:shadow-md transition-all duration-300">
|
|
<div className="flex justify-between items-start mb-4">
|
|
<div>
|
|
<h3 className="text-zinc-500 dark:text-dark-muted text-sm font-medium mb-1">{title}</h3>
|
|
<div className="text-3xl font-bold text-zinc-800 dark:text-dark-text tracking-tight">{value}</div>
|
|
</div>
|
|
<div className={`p-3 rounded-xl bg-${baseColor}-100 dark:bg-${baseColor}-500/20 flex items-center justify-center transition-colors border border-transparent dark:border-${baseColor}-500/30`}>
|
|
<Icon size={20} className={`${colorClass} dark:text-${baseColor}-400`} />
|
|
</div>
|
|
</div>
|
|
|
|
{(trend || subValue) && (
|
|
<div className="flex items-center gap-2 text-sm mt-auto">
|
|
{trend === 'up' && <span className="text-green-500 flex items-center font-medium">▲ {trendValue}</span>}
|
|
{trend === 'down' && <span className="text-red-500 flex items-center font-medium">▼ {trendValue}</span>}
|
|
{subValue && <span className="text-zinc-400 dark:text-dark-muted">{subValue}</span>}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}; |