diff --git a/client/components/StatusBadge.tsx b/client/components/StatusBadge.tsx
index 16db054..4bed9d0 100644
--- a/client/components/StatusBadge.tsx
+++ b/client/components/StatusBadge.tsx
@@ -3,12 +3,12 @@ import { AlertCircle } from 'lucide-react';
import { cn } from '@/lib/utils';
const STATUS_META = {
- paid: { label: 'Paid', cls: 'bg-emerald-500/15 text-emerald-500 border border-emerald-500/30 dark:bg-emerald-300/10 dark:text-emerald-200 dark:border-emerald-300/30' },
+ paid: { label: 'Paid', cls: 'bg-emerald-500/15 text-emerald-700 border border-emerald-500/30 dark:bg-emerald-300/10 dark:text-emerald-200 dark:border-emerald-300/30' },
upcoming: { label: 'Upcoming', cls: 'bg-secondary text-muted-foreground border border-border' },
- due_soon: { label: 'Due Soon', cls: 'bg-amber-400/15 text-amber-500 border border-amber-400/30 dark:bg-amber-300/10 dark:text-amber-200 dark:border-amber-300/28' },
- late: { label: 'Late', cls: 'bg-orange-500/30 text-orange-800 border border-orange-500/60 shadow-sm shadow-orange-950/10 dark:bg-orange-400/25 dark:text-orange-100 dark:border-orange-300/60' },
- missed: { label: 'Missed', cls: 'bg-rose-500/30 text-rose-800 border border-rose-500/70 shadow-sm shadow-rose-950/10 dark:bg-rose-400/25 dark:text-rose-100 dark:border-rose-300/60' },
- autodraft: { label: 'Autodraft', cls: 'bg-sky-400/15 text-sky-500 border border-sky-400/30 dark:bg-sky-300/10 dark:text-sky-200 dark:border-sky-300/28' },
+ due_soon: { label: 'Due Soon', cls: 'bg-amber-400/15 text-amber-700 border border-amber-400/35 dark:bg-amber-300/10 dark:text-amber-200 dark:border-amber-300/28' },
+ late: { label: 'Late', cls: 'bg-orange-500/20 text-orange-700 border border-orange-500/50 shadow-sm shadow-orange-950/10 dark:bg-orange-400/25 dark:text-orange-100 dark:border-orange-300/60' },
+ missed: { label: 'Missed', cls: 'bg-rose-500/20 text-rose-700 border border-rose-500/55 shadow-sm shadow-rose-950/10 dark:bg-rose-400/25 dark:text-rose-100 dark:border-rose-300/60' },
+ autodraft: { label: 'Autodraft', cls: 'bg-teal-400/15 text-teal-700 border border-teal-400/35 dark:bg-teal-300/10 dark:text-teal-200 dark:border-teal-300/28' },
skipped: { label: 'Skipped', cls: 'bg-muted text-muted-foreground border border-border' },
};
diff --git a/client/components/tracker/CashFlowCard.tsx b/client/components/tracker/CashFlowCard.tsx
index e719496..e94d400 100644
--- a/client/components/tracker/CashFlowCard.tsx
+++ b/client/components/tracker/CashFlowCard.tsx
@@ -134,7 +134,7 @@ export default function CashFlowCard({ cashflow, onSetStartingAmounts }: { cashf
See your safe-to-spend
- Add what's in your account for the 1st and 15th, and BillTracker projects what's left after bills.
+ Add what's in your account for the 1st and 15th, and Bill Tracker projects what's left after bills.
diff --git a/client/components/tracker/OverdueCommandCenter.tsx b/client/components/tracker/OverdueCommandCenter.tsx
index 4a4d6dd..01ccb48 100644
--- a/client/components/tracker/OverdueCommandCenter.tsx
+++ b/client/components/tracker/OverdueCommandCenter.tsx
@@ -93,13 +93,13 @@ function OverdueRow({ row, year, month, onPayNow, onRefresh }: OverdueRowProps)
)}
-
+
{daysOverdueLabel(row.due_date)}
{/* Amount */}
-
+
{fmt(threshold)}
@@ -108,7 +108,7 @@ function OverdueRow({ row, year, month, onPayNow, onRefresh }: OverdueRowProps)
onPayNow(row)}
>
@@ -185,17 +185,17 @@ export default function OverdueCommandCenter({ rows, year, month, refresh, onPay
return (
-
+
{/* Header */}
-
+
{`${overdueRows.length} overdue ${overdueRows.length === 1 ? 'bill' : 'bills'}`}
-
+
{fmt(asDollars(totalOverdue))}
diff --git a/client/components/tracker/SummaryCards.tsx b/client/components/tracker/SummaryCards.tsx
index cce386f..2ed446a 100644
--- a/client/components/tracker/SummaryCards.tsx
+++ b/client/components/tracker/SummaryCards.tsx
@@ -1,16 +1,15 @@
import { TrendingUp, AlertCircle, Clock, CheckCircle2, Settings2, type LucideIcon } from 'lucide-react';
import { cn, fmt } from '@/lib/utils';
import type { Dollars } from '@/lib/money';
+import { MetricCard } from '@/components/ui/app-primitives';
type CardType = 'starting' | 'paid' | 'remaining' | 'overdue';
interface CardDef {
label: string;
icon: LucideIcon;
- bar: string;
- glow: string;
- borderActive?: string;
valueClass: string;
+ tone: 'neutral' | 'good' | 'warn' | 'danger' | 'info';
activateWhen: (v: number) => boolean;
}
@@ -18,35 +17,29 @@ const CARD_DEFS: Record = {
starting: {
label: 'Starting',
icon: TrendingUp,
- bar: 'from-slate-400 to-slate-300',
- glow: '',
valueClass: 'text-foreground',
+ tone: 'neutral',
activateWhen: () => true,
},
paid: {
label: 'Total Paid',
icon: CheckCircle2,
- bar: 'from-emerald-500 to-emerald-300',
- glow: 'shadow-[0_4px_20px_rgba(16,185,129,0.15)]',
- borderActive: 'border-emerald-400/40',
valueClass: 'text-emerald-600 dark:text-emerald-200',
+ tone: 'good',
activateWhen: (v) => v > 0,
},
remaining: {
label: 'Remaining',
icon: Clock,
- bar: 'from-blue-400 to-indigo-300',
- glow: '',
valueClass: 'text-foreground',
+ tone: 'info',
activateWhen: () => true,
},
overdue: {
label: 'Overdue',
icon: AlertCircle,
- bar: 'from-rose-400 to-orange-300',
- glow: 'shadow-[0_4px_20px_rgba(251,113,133,0.10)]',
- borderActive: 'border-rose-400/35',
valueClass: 'text-red-500 dark:text-rose-200',
+ tone: 'danger',
activateWhen: (v) => v > 0,
},
};
@@ -106,23 +99,18 @@ export function SummaryCard({ type, value, onEdit, hint, label }: SummaryCardPro
const displayLabel = label || def.label;
return (
-
-
-
-
-
- {displayLabel}
-
- {type === 'starting' && onEdit && (
+
+ {fmt(value)}
+
+ )}
+ hint={hint}
+ action={type === 'starting' && onEdit ? (
- )}
-
-
- {fmt(value)}
-
- {hint &&
{hint}
}
-
+ ) : undefined}
+ />
);
}
@@ -148,17 +128,16 @@ export function TrendCard({ trend }: { trend?: TrendInfo | null }) {
if (!trend) return null;
return (
-
+
+ )}
+ />
);
}
diff --git a/client/components/tracker/TrackerBucket.tsx b/client/components/tracker/TrackerBucket.tsx
index eb2f872..37268df 100644
--- a/client/components/tracker/TrackerBucket.tsx
+++ b/client/components/tracker/TrackerBucket.tsx
@@ -223,7 +223,7 @@ export function TrackerBucket({
}
return (
-