- Fix Dashboard stat card: show "Budget Remaining" instead of "Budget Spent" with correct remaining value accounting for campaign allocations - Add expense system: budget entries now have income/expense type with server-side split, per-campaign and per-project expense tracking, colored amounts, type filters, and summary bar in Budgets page - Add configurable currency in Settings (SAR default, supports 10 currencies) replacing all hardcoded SAR references across the app - Replace PiggyBank icon with Landmark (culturally appropriate for KSA) - Visual upgrade: mesh background, gradient text, premium stat cards with accent bars, section-card containers, sidebar active glow - UX polish: consistent text-2xl headers, skeleton loaders for Finance and Budgets pages - Finance page: expenses column in campaign/project breakdown tables, ROI accounts for expenses, expense stat card Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
45 lines
1.8 KiB
JavaScript
45 lines
1.8 KiB
JavaScript
export default function StatCard({ icon: Icon, label, value, subtitle, color = 'brand-primary', trend }) {
|
|
const accentMap = {
|
|
'brand-primary': 'accent-primary',
|
|
'brand-secondary': 'accent-secondary',
|
|
'brand-tertiary': 'accent-tertiary',
|
|
'brand-quaternary': 'accent-quaternary',
|
|
}
|
|
|
|
const iconBgMap = {
|
|
'brand-primary': 'bg-indigo-50 text-indigo-600 shadow-lg shadow-indigo-500/20',
|
|
'brand-secondary': 'bg-pink-50 text-pink-600 shadow-lg shadow-pink-500/20',
|
|
'brand-tertiary': 'bg-amber-50 text-amber-600 shadow-lg shadow-amber-500/20',
|
|
'brand-quaternary': 'bg-emerald-50 text-emerald-600 shadow-lg shadow-emerald-500/20',
|
|
}
|
|
|
|
const accentClass = accentMap[color] || 'accent-primary'
|
|
|
|
return (
|
|
<div className={`stat-card-premium ${accentClass} bg-white rounded-xl border border-border p-5 card-hover`}>
|
|
<div className="flex items-start justify-between">
|
|
<div>
|
|
<p className="text-sm font-medium text-text-tertiary">{label}</p>
|
|
<p className="text-3xl font-bold text-text-primary mt-1">{value}</p>
|
|
{subtitle && (
|
|
<p className="text-xs text-text-tertiary mt-1">{subtitle}</p>
|
|
)}
|
|
</div>
|
|
<div className={`w-11 h-11 rounded-xl flex items-center justify-center ${iconBgMap[color] || iconBgMap['brand-primary']}`}>
|
|
<Icon className="w-5 h-5" />
|
|
</div>
|
|
</div>
|
|
{trend && (
|
|
<div className="mt-3 pt-3 border-t border-border-light">
|
|
<div className="flex items-center gap-1">
|
|
<span className={`text-xs font-medium ${trend > 0 ? 'text-emerald-600' : 'text-red-500'}`}>
|
|
{trend > 0 ? '+' : ''}{trend}%
|
|
</span>
|
|
<span className="text-xs text-text-tertiary">vs last month</span>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|