diff --git a/web/src/pages/DashboardPage.tsx b/web/src/pages/DashboardPage.tsx index 18f9765..008d619 100644 --- a/web/src/pages/DashboardPage.tsx +++ b/web/src/pages/DashboardPage.tsx @@ -354,33 +354,32 @@ export default function DashboardPage() { return dateStringToUTCMidnight(nextDateStr, userTimezone); } - // Detect if any fixed plan is due today; show overlay to confirm due date and pay-now + // Detect if any fixed plan is due/overdue and needs user payment confirmation. + // Include fully funded overdue plans so missed-day confirmations still surface. useEffect(() => { let cancelled = false; async function checkDueToday() { if (!data || !shouldLoadDashboard || hasCheckedDueToday) return; try { const res = await fixedPlansApi.due({ daysAhead: 0 }); - const items = (res.items || []).filter((x) => x.isDue && !x.isOverdue); + const items = (res.items || []) + .filter((x) => x.isDue && (!x.isOverdue || x.remainingCents <= 0)) + .filter((x) => { + const dismissedUntilStr = localStorage.getItem(`overdue-dismissed-${x.id}`); + if (!dismissedUntilStr) return true; + const dismissedUntil = parseInt(dismissedUntilStr, 10); + if (!Number.isFinite(dismissedUntil) || Date.now() >= dismissedUntil) { + localStorage.removeItem(`overdue-dismissed-${x.id}`); + return true; + } + return false; + }); if (!cancelled && items.length > 0) { setHasCheckedDueToday(true); const first = items[0]; - - // Check if user has dismissed this overdue prompt recently - const dismissedUntilStr = localStorage.getItem(`overdue-dismissed-${first.id}`); - if (dismissedUntilStr) { - const dismissedUntil = parseInt(dismissedUntilStr, 10); - if (Date.now() < dismissedUntil) { - // Still within the "remind me later" window - skip this prompt - return; - } else { - // Expired - remove it - localStorage.removeItem(`overdue-dismissed-${first.id}`); - } - } - + await openDueItem(first); - + // Store queue for potential future bills setDueQueue(items.map((i) => ({ id: i.id,