Skip to content

feat(payment): unified /payment hub with realtime PaymentHistory + Subscriptions#147

Merged
TortoiseWolfe merged 1 commit into
mainfrom
feat/unified-payment-hub-realtime
Jun 8, 2026
Merged

feat(payment): unified /payment hub with realtime PaymentHistory + Subscriptions#147
TortoiseWolfe merged 1 commit into
mainfrom
feat/unified-payment-hub-realtime

Conversation

@TortoiseWolfe

Copy link
Copy Markdown
Owner

What

Consolidates the scattered payment pages into one tabbed hub at /payment and makes the surfaces live via Supabase Realtime. Replaces /payment/dashboard + /account/subscriptions (both deleted).

Hub (src/app/payment/)

page.tsx + PaymentHubContent.tsx + SearchParamsReader.tsxProtectedRoute + DaisyUI tabs (Overview / Subscriptions), ?tab= deep-linking, per-tab <h1> (Payments / Subscriptions), activeTab initialized synchronously from the URL so the right heading paints on first render. Absorbs the former dashboard (PaymentQueuePanel + PaymentHistory) and subscriptions (SubscriptionManager) content verbatim; gating (ProtectedRoute, feature flags, not-configured alert) intact. /account nav buttons now point at /payment[?tab=subscriptions].

Realtime (src/hooks/, reuses the useConnections debounced-channel pattern)

  • usePaymentResultsRealtime + useSubscriptionsRealtime — subscribe to postgres_changes, debounce 1s, return 'connecting' | 'live' | 'error', fully inert when enabled=false (tests/stories). Unit-tested (mock channel, status callback, debounce, cleanup, disabled path).
  • PaymentHistory + SubscriptionManager gain an optional realtime prop (default true): a stable refetch wired to the hook, a realtime-status connection badge, and a live transaction-count.

Migration (root-cause fix)

Adds payment_results + subscriptions to the supabase_realtime publication (idempotent-guarded, mirroring the messaging tables). Without this the channel subscribes but never receives events — I verified this live: the tables were missing from the publication; after adding them, the counter updated 2 → 3 on a service-role insert with no reload. Applied to prod via the Management API.

Tests

  • Retargeted the 3 green tests to the hub (openSubscriptionsAs/payment?tab=subscriptions; 02 route-render + 05 queue-panel gotos/headings). Per-tab h1 keeps their level: 1 heading anchors valid.
  • Un-skipped 4 06-realtime tests (live transaction counter, payment-list live update, subscription status change, connection-status indicator) using new seedIsolatedPayment / openPaymentHubAs fixtures; guarded on getAdminClient().
  • Regenerated docs/payment-e2e-skip-index.md (27 → 23 skips, reclassified).

Verification

  • type-check ✅, lint ✅, validate:structure 110/110 ✅, 132 unit tests
  • Live Playwright-MCP realtime check: opened /payment, service-role inserted a payment → counter + list updated 2 → 3 with no reload; confirmed realtime-status reads "Live". (Surfaced + fixed the missing publication membership; also noted the PWA service worker caches the initial history fetch — the realtime in-memory refetch path is unaffected.)

🤖 Generated with Claude Code

…bscriptions

Consolidates the scattered payment pages into ONE tabbed hub at /payment and
makes the surfaces live via Supabase Realtime.

Hub (src/app/payment/):
- page.tsx + PaymentHubContent.tsx + SearchParamsReader.tsx — ProtectedRoute +
  DaisyUI tabs (Overview / Subscriptions), ?tab= deep-link, per-tab <h1>
  (Payments / Subscriptions), activeTab initialized synchronously from the URL
  so the correct heading paints on first render. Absorbs the former
  /payment/dashboard (PaymentQueuePanel + PaymentHistory) and
  /account/subscriptions (SubscriptionManager) content verbatim, gating intact.
- Deletes the 4 old route files; /account nav buttons → /payment[?tab=subscriptions].

Realtime (src/hooks/, reuses the useConnections debounced-channel pattern):
- usePaymentResultsRealtime + useSubscriptionsRealtime — subscribe to
  postgres_changes, debounce 1s, return 'connecting'|'live'|'error' for a
  status badge, inert when enabled=false (tests/stories). Unit-tested.
- PaymentHistory + SubscriptionManager gain an optional `realtime` prop
  (default true): a stable refetch callback wired to the hook, a
  `realtime-status` connection badge, and a live `transaction-count`.

Migration: adds payment_results + subscriptions to the supabase_realtime
publication (idempotent-guarded, mirroring the messaging tables). WITHOUT this
the channel subscribes but never receives events — verified live: the table was
missing from the publication, added it, and the counter then updated 2→3 on a
service-role insert with no reload. Applied to prod via the Management API.

Tests:
- Retargeted the 3 green tests to the hub: openSubscriptionsAs →
  /payment?tab=subscriptions; 02 route-render + 05 queue-panel gotos/headings.
- Un-skipped 4 06-realtime tests (live transaction counter, payment-list live
  update, subscription status change, connection-status indicator) using new
  seedIsolatedPayment / openPaymentHubAs fixtures; guarded on getAdminClient().
- Regenerated docs/payment-e2e-skip-index.md (27 → 23 skips, reclassified).

Verified: type-check, lint, validate:structure (110/110), 132 unit tests, and a
live Playwright-MCP realtime check (counter 2→3 via a service-role insert).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@TortoiseWolfe TortoiseWolfe merged commit 89ff7f5 into main Jun 8, 2026
18 checks passed
@TortoiseWolfe TortoiseWolfe deleted the feat/unified-payment-hub-realtime branch June 8, 2026 22:32
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.

2 participants