diff --git a/client/components/SearchFilterPanel.tsx b/client/components/SearchFilterPanel.tsx index 1accc85..eb614e5 100644 --- a/client/components/SearchFilterPanel.tsx +++ b/client/components/SearchFilterPanel.tsx @@ -37,18 +37,21 @@ export default function SearchFilterPanel({
-
+
{hasFilters && onClear && ( - @@ -71,7 +74,7 @@ export default function SearchFilterPanel({ {!collapsed && (
{children}
diff --git a/client/components/tracker/FilterChip.tsx b/client/components/tracker/FilterChip.tsx index d689a91..aa1a853 100644 --- a/client/components/tracker/FilterChip.tsx +++ b/client/components/tracker/FilterChip.tsx @@ -1,4 +1,5 @@ import type { ReactNode } from 'react'; +import { Check } from 'lucide-react'; import { cn } from '@/lib/utils'; interface FilterChipProps { @@ -12,13 +13,15 @@ export function FilterChip({ active, children, onClick }: FilterChipProps) { ); diff --git a/client/components/tracker/MobileTrackerRow.tsx b/client/components/tracker/MobileTrackerRow.tsx index f8d136d..d2dd173 100644 --- a/client/components/tracker/MobileTrackerRow.tsx +++ b/client/components/tracker/MobileTrackerRow.tsx @@ -176,7 +176,7 @@ export function MobileTrackerRow({ row, year, month, refresh, index, onEditBill, onDragEnd={dragProps?.onDragEnd as React.ComponentProps['onDragEnd']} onDrop={dragProps?.onDrop} className={cn( - 'rounded-lg border border-border/60 bg-background/60 p-3 shadow-sm', + 'rounded-lg border border-border/60 bg-card/70 p-3 shadow-sm shadow-black/5', 'space-y-3 transition-colors', isSkipped ? 'opacity-55' : rowBg, dragProps?.isDragging && 'opacity-45', @@ -325,17 +325,17 @@ export function MobileTrackerRow({ row, year, month, refresh, index, onEditBill,
-
+
setPaymentLedgerOpen(true)} compact />
-
+
Paid - {row.total_paid > 0 ? fmt(row.total_paid) : '—'} + {row.total_paid > 0 ? fmt(row.total_paid) : '—'}
-
+
Date ) : undefined} /> @@ -134,8 +134,8 @@ export function TrendCard({ trend }: { trend?: TrendInfo | null }) { icon={TrendingUp} label="3-Month Trend" value={( - - + + )} /> diff --git a/client/components/tracker/TrackerBucket.tsx b/client/components/tracker/TrackerBucket.tsx index 37268df..26a6b28 100644 --- a/client/components/tracker/TrackerBucket.tsx +++ b/client/components/tracker/TrackerBucket.tsx @@ -223,10 +223,10 @@ export function TrackerBucket({ } return ( -
+
{/* Bucket header */} -
+
@@ -239,7 +239,7 @@ export function TrackerBucket({ )}
-
+
- + {fmt(asDollars(totalPaidTowardDue))} @@ -308,10 +308,10 @@ export function TrackerBucket({ -
+
{loading ? ( Array.from({ length: 3 }).map((_, i) => ( -
+
@@ -334,7 +334,7 @@ export function TrackerBucket({
)) ) : rows.length === 0 ? ( -
+
No bills match — try adjusting your filters.
) : ( @@ -361,7 +361,7 @@ export function TrackerBucket({
- + Bill {showColumn('due') && ( Due diff --git a/client/components/ui/app-primitives.tsx b/client/components/ui/app-primitives.tsx index db04db6..cc5f03f 100644 --- a/client/components/ui/app-primitives.tsx +++ b/client/components/ui/app-primitives.tsx @@ -120,14 +120,18 @@ export function MetricCard({
- {Icon && } + {Icon && ( + + + + )}

{label}

{action}
-

{value}

+

{value}

{hint &&

{hint}

}
); diff --git a/client/index.css b/client/index.css index 3a1c4f3..26c3dbc 100644 --- a/client/index.css +++ b/client/index.css @@ -162,16 +162,16 @@ } .metric-card { - @apply relative overflow-hidden rounded-xl border border-border/75 bg-card/95 px-5 py-4 shadow-sm shadow-black/10; + @apply relative min-h-[7.75rem] overflow-hidden rounded-xl border border-border/75 bg-card/95 px-4 py-4 shadow-sm shadow-black/10 sm:px-5; } .metric-card::before { content: ""; position: absolute; inset: 0 0 auto; - height: 3px; - background: linear-gradient(90deg, oklch(var(--primary) / 0.85), oklch(var(--accent) / 0.68)); - opacity: 0.76; + height: 2px; + background: currentColor; + opacity: 0.24; } /* Stat cards */ @@ -194,6 +194,7 @@ .metric-value { @apply tracker-number font-bold tracking-tight text-foreground; + overflow-wrap: anywhere; } diff --git a/client/lib/trackerUtils.ts b/client/lib/trackerUtils.ts index 30ce533..fe2523a 100644 --- a/client/lib/trackerUtils.ts +++ b/client/lib/trackerUtils.ts @@ -41,20 +41,20 @@ export const TRACKER_SORT_DEFAULT_DIRS = Object.fromEntries( ); export const ROW_STATUS_CLS: Record = { - paid: 'bg-emerald-500/[0.04] dark:bg-emerald-400/[0.02]', - autodraft: 'bg-sky-500/[0.04] dark:bg-sky-400/[0.018]', - upcoming: '', - due_soon: 'bg-amber-400/[0.07] dark:bg-amber-300/[0.016]', - late: 'border-l-4 border-l-orange-400 bg-orange-500/[0.16] ring-1 ring-inset ring-orange-400/25 dark:bg-orange-400/[0.11] dark:ring-orange-300/25', - missed: 'border-l-4 border-l-rose-400 bg-rose-500/[0.18] ring-1 ring-inset ring-rose-400/30 dark:bg-rose-400/[0.13] dark:ring-rose-300/30', + paid: 'border-l-2 border-l-emerald-500/45 bg-emerald-500/[0.025] dark:bg-emerald-400/[0.018] [&>td:first-child]:border-l-2 [&>td:first-child]:border-l-emerald-500/45', + autodraft: 'border-l-2 border-l-teal-500/45 bg-teal-500/[0.025] dark:bg-teal-400/[0.018] [&>td:first-child]:border-l-2 [&>td:first-child]:border-l-teal-500/45', + upcoming: 'border-l-2 border-l-transparent [&>td:first-child]:border-l-2 [&>td:first-child]:border-l-transparent', + due_soon: 'border-l-2 border-l-amber-400/65 bg-amber-400/[0.055] dark:bg-amber-300/[0.02] [&>td:first-child]:border-l-2 [&>td:first-child]:border-l-amber-400/65', + late: 'border-l-2 border-l-orange-400/80 bg-orange-500/[0.09] ring-1 ring-inset ring-orange-400/20 dark:bg-orange-400/[0.07] dark:ring-orange-300/20 [&>td:first-child]:border-l-2 [&>td:first-child]:border-l-orange-400/80', + missed: 'border-l-2 border-l-rose-400/80 bg-rose-500/[0.1] ring-1 ring-inset ring-rose-400/20 dark:bg-rose-400/[0.075] dark:ring-rose-300/20 [&>td:first-child]:border-l-2 [&>td:first-child]:border-l-rose-400/80', }; export const STATUS_META = { 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-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' }, + late: { label: 'Late', cls: 'bg-orange-500/15 text-orange-700 border border-orange-500/45 shadow-sm shadow-orange-950/10 dark:bg-orange-400/20 dark:text-orange-100 dark:border-orange-300/50' }, + missed: { label: 'Missed', cls: 'bg-rose-500/15 text-rose-700 border border-rose-500/45 shadow-sm shadow-rose-950/10 dark:bg-rose-400/20 dark:text-rose-100 dark:border-rose-300/50' }, 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/pages/TrackerPage.tsx b/client/pages/TrackerPage.tsx index 19429f0..398fc71 100644 --- a/client/pages/TrackerPage.tsx +++ b/client/pages/TrackerPage.tsx @@ -1135,7 +1135,7 @@ export default function TrackerPage() { {/* ── Summary cards (backend already excludes skipped from totals) ── */} {showSummaryCards && loading ? ( -
+
@@ -1144,7 +1144,7 @@ export default function TrackerPage() { {summary.trend ? : null}
) : showSummaryCards ? ( -
+
{bankTracking?.enabled ? (