Skip to content

Low-balance push notifications + Safari payment history pagination fix - #716

Merged
Dev-AdeTutu merged 2 commits into
Dev-AdeTutu:mainfrom
Onomebello:feat/low-balance-push-and-pagination
Aug 25, 2026
Merged

Low-balance push notifications + Safari payment history pagination fix#716
Dev-AdeTutu merged 2 commits into
Dev-AdeTutu:mainfrom
Onomebello:feat/low-balance-push-and-pagination

Conversation

@Onomebello

@Onomebello Onomebello commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR delivers two user-facing improvements:

  1. Proactive low-balance browser push notifications for meter owners.
  2. A pagination reliability fix for payment history (including Safari behavior where paging could stop responding after deep scroll).

Problem

Users only discovered low balances after manually checking dashboards, causing avoidable service interruptions. In addition, payment history pagination could become non-functional after scrolling in Safari, with no API request fired and URL page state not updating consistently.

What Changed

Frontend

  • Added Web Push client setup service:
    • Requests notification permission on first dashboard visit.
    • Registers service worker and subscribes browser via PushManager.
    • Persists subscription endpoint in localStorage to avoid duplicate registration calls.
  • Added service worker to:
    • Render push notifications.
    • Handle notification click/action and route users to top-up flow.
  • Added push notification icons.
  • Updated User Dashboard polling flow to trigger subscription registration once low-balance condition is observed.
  • Fixed payment history pagination flow:
    • Uses URL page param as the source of truth.
    • Uses explicit page-change handler for next/prev.
    • Scrolls to top of history section on page change.
    • Prevents stale disabled-state behavior on pagination buttons.
  • Fixed a pre-existing production build failure:
    • /history and /dashboard/provider used useSearchParams() without a Suspense boundary, which made next build fail with a prerender/export error (unrelated to this PR's business logic, but blocking any build that touches these routes). Wrapped both pages' bodies in Suspense so the build succeeds again.

Backend

  • Added push subscription persistence layer (SQLite-backed table):
    • Upsert subscriptions by endpoint.
    • Delete stale/unsubscribed endpoints.
  • Added Web Push delivery module using VAPID configuration.
  • Added new push API endpoints:
    • GET /api/push/config
    • POST /api/push/subscribe
    • POST /api/push/unsubscribe
  • Integrated low-balance push send in IoT bridge low-balance pipeline.
  • Upgraded low-balance threshold logic to requested rule:
    • threshold = 10% of typical weekly usage (last 7 days)
    • Falls back to LOW_BALANCE_THRESHOLD when insufficient history exists.
  • Exposed low-balance metadata in meter balance responses for frontend gating.

Docs / Config

  • Updated backend API docs to include push endpoints and dynamic threshold behavior.
  • Added required/optional Web Push env vars to backend .env.example.
  • Added frontend backend URL env example for push API usage.

Files of Interest

  • Frontend:
    • src/app/history/page.tsx
    • src/app/dashboard/user/page.tsx
    • src/services/pushService.ts
    • public/sw.js
    • public/icons/push-warning.svg
    • public/icons/push-badge.svg
  • Backend:
    • ../backend/src/routes/pushSubscriptions.ts
    • ../backend/src/lib/pushNotifications.ts
    • ../backend/src/lib/pushSubscriptions.ts
    • ../backend/src/iot/bridge.ts
    • ../backend/src/lib/usageEvents.ts
    • ../backend/src/routes/meters.ts
    • ../backend/src/index.ts

Testing / Validation

  • Backend TypeScript build passes: cd backend && npm run build.
  • Backend dependencies verified installed and loadable (web-push).
  • Frontend type check passes for all application source (cd frontend && npx tsc --noEmit, excluding pre-existing test-file type errors from missing Jest type defs, unrelated to this change).
  • Frontend production build passes end-to-end (cd frontend && npm run build, exit code 0) after the Suspense fix.
  • frontend/npm test run: pre-existing failures in OfflinePaymentModal.test.tsx and AllowlistPanel.test.tsx (missing unrelated modules @/hooks/useOffline, @/services/allowlistService) are unaffected by this change; all other suites pass (19/19 tests).

Operational Notes

  • To enable push notifications in deployed environments, set:
    • WEB_PUSH_VAPID_SUBJECT
    • WEB_PUSH_VAPID_PUBLIC_KEY
    • WEB_PUSH_VAPID_PRIVATE_KEY
  • Without these vars, push endpoints remain available but sending is effectively disabled (safe no-op behavior with warning logs).

Risk Assessment

  • Low-to-medium risk due to new notification pipeline and persistence table.
  • Mitigations:
    • Invalid/stale subscriptions are removed on 404/410 push responses.
    • Existing webhook path remains intact.
    • Fallback threshold preserves behavior when history data is unavailable.

Follow-ups

Add browser push notifications for low meter balance and fix payment
history pagination breaking after scroll in Safari.

- Backend: SQLite-backed push subscription store, VAPID-based Web Push
  sender, and /api/push/{config,subscribe,unsubscribe} endpoints.
- Backend: dynamic low-balance threshold (10% of trailing 7-day typical
  weekly usage, falling back to LOW_BALANCE_THRESHOLD when no history
  exists), wired into the IoT bridge's low-balance check and exposed on
  the meter balance endpoint.
- Frontend: service worker (public/sw.js) that renders push
  notifications with a "Top Up" action routing to /pay, and a
  pushService that requests notification permission on first dashboard
  visit and subscribes once a meter's balance crosses the low-balance
  threshold.
- Frontend: rewired payment history pagination to use the URL page
  param as the source of truth with explicit Prev/Next handlers
  instead of scroll/IntersectionObserver-driven state, fixing Safari
  pagination becoming unresponsive after scrolling past 50 rows.
- Fixed a pre-existing build failure on /history and
  /dashboard/provider (useSearchParams used without a Suspense
  boundary) that was breaking `next build`.
@drips-wave

drips-wave Bot commented Aug 25, 2026

Copy link
Copy Markdown

@Onomebello Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Dev-AdeTutu
Dev-AdeTutu merged commit 91c6974 into Dev-AdeTutu:main Aug 25, 2026
0 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Payment history pagination breaks with infinite scroll [Feature] Add browser push notifications for low balance alerts

2 participants