diff --git a/client/pages/TrackerPage.tsx b/client/pages/TrackerPage.tsx index d532f27..5d03bf1 100644 --- a/client/pages/TrackerPage.tsx +++ b/client/pages/TrackerPage.tsx @@ -622,8 +622,11 @@ export default function TrackerPage() { ? sortTrackerRows(filteredRows, sortKey, sortDir) : pinUpcoming ? [...filteredRows].sort((a, b) => { - const ua = URGENCY_ORDER[a.status] ?? 99; - const ub = URGENCY_ORDER[b.status] ?? 99; + // Rank on the reconciled status (same source the overdue filter uses), + // so a bill that's paid-by-threshold but still carries a stale raw + // 'late'/'missed' status sorts to the bottom instead of being pinned up. + const ua = URGENCY_ORDER[rowEffectiveStatus(a)] ?? 99; + const ub = URGENCY_ORDER[rowEffectiveStatus(b)] ?? 99; if (ua !== ub) return ua - ub; return (a.due_day ?? 99) - (b.due_day ?? 99); }) @@ -1060,6 +1063,23 @@ export default function TrackerPage() { )} + {/* ── Filtered-to-empty state — bills exist this month but none match the active filters/search ── */} + {!isError && !loading && rows.length > 0 && first.length === 0 && second.length === 0 && ( +
+
+ +
+

No bills match your filters

+

{rows.length} bill{rows.length === 1 ? '' : 's'} this month are hidden by the current search or filters.

+ {hasFilters && ( + + )} +
+ )} + {!isError && (first.length > 0 || second.length > 0) && (
{first.length > 0 && handleReorderBucket('1st', next)} driftedIds={driftedIds} visibleColumns={visibleTableColumns} />}