[PULSE-57] Billing UX: renewal display, design fixes, React crash fix #32

Merged
uz1mani merged 16 commits from staging into main 2026-02-20 17:32:33 +00:00
uz1mani commented 2026-02-20 17:24:49 +00:00 (Migrated from github.com)

Work Item

PULSE-57

Summary

  • Show "Renews [date] for [amount]" on dashboard and billing tab; add Change Plan invoice preview with error fallback
  • Apply billing/pricing design and a11y fixes; add Pay now CTA for open invoices; use mailto for Enterprise Contact us
  • Fix React #310 crash when toggling theme and navigating to org-settings

Changes

  • app/page.tsx: Show "Renews [date] for [amount]" in Plan & usage card when next_invoice_* fields and active subscription exist
  • components/settings/OrganizationSettings.tsx: Past-due banner and status badge; usage stats padding and pageview progress bar; recent invoices heading and Pay now CTA for open invoices; Change Plan modal updates (3-column plan selector, Current badge, close button a11y, billing toggle, preview box, preview error fallback); move hasActiveSubscription and previewInvoice useEffect above early return to fix React #310; focus states on billing links
  • components/PricingSection.tsx: Container/toolbar/card padding; section heading and subtitle; slider aria-label/aria-valuetext/focus; billing toggle role/aria-checked/focus; Enterprise "Contact us" as mailto:business@ciphera.net?subject=Enterprise%20Plan%20Inquiry
  • lib/api/billing.ts: previewInvoice and SubscriptionDetails types for next_invoice_* fields

Test Plan

  • Dashboard Plan & usage card shows "Renews [date] for [amount]" when subscription is active
  • Billing tab shows renewal info, past-due banner when applicable, pageview progress bar
  • Change Plan modal shows prorated preview and fallback message on preview failure
  • Open invoices show "Pay now" (orange); paid invoices show "View invoice"
  • Enterprise "Contact us" opens mailto client
  • Pricing page renders as designed; slider and billing toggle have focus states
  • Toggle theme on pricing, then navigate to org-settings — no React crash
## Work Item PULSE-57 ## Summary - Show "Renews [date] for [amount]" on dashboard and billing tab; add Change Plan invoice preview with error fallback - Apply billing/pricing design and a11y fixes; add Pay now CTA for open invoices; use mailto for Enterprise Contact us - Fix React #310 crash when toggling theme and navigating to org-settings ## Changes - **app/page.tsx**: Show "Renews [date] for [amount]" in Plan & usage card when `next_invoice_*` fields and active subscription exist - **components/settings/OrganizationSettings.tsx**: Past-due banner and status badge; usage stats padding and pageview progress bar; recent invoices heading and Pay now CTA for open invoices; Change Plan modal updates (3-column plan selector, Current badge, close button a11y, billing toggle, preview box, preview error fallback); move `hasActiveSubscription` and `previewInvoice` useEffect above early return to fix React #310; focus states on billing links - **components/PricingSection.tsx**: Container/toolbar/card padding; section heading and subtitle; slider `aria-label`/`aria-valuetext`/focus; billing toggle `role`/`aria-checked`/focus; Enterprise "Contact us" as `mailto:business@ciphera.net?subject=Enterprise%20Plan%20Inquiry` - **lib/api/billing.ts**: `previewInvoice` and `SubscriptionDetails` types for `next_invoice_*` fields ## Test Plan - [x] Dashboard Plan & usage card shows "Renews [date] for [amount]" when subscription is active - [x] Billing tab shows renewal info, past-due banner when applicable, pageview progress bar - [x] Change Plan modal shows prorated preview and fallback message on preview failure - [x] Open invoices show "Pay now" (orange); paid invoices show "View invoice" - [x] Enterprise "Contact us" opens mailto client - [x] Pricing page renders as designed; slider and billing toggle have focus states - [x] Toggle theme on pricing, then navigate to org-settings — no React crash
greptile-apps[bot] commented 2026-02-20 17:27:29 +00:00 (Migrated from github.com)

Greptile Summary

This PR enhances the billing UX by adding subscription renewal information, multi-plan support (Solo/Team/Business), and fixes a React crash issue. The changes include displaying "Renews [date] for [amount]" on the dashboard and billing tab, implementing invoice preview with error fallback for plan changes, and adding various design and accessibility improvements.

Key changes:

  • Fixed React #310 crash by moving hasActiveSubscription and previewInvoice useEffect hooks above the early return in OrganizationSettings
  • Added support for Team and Business plans with proper site limits (1/5/10 sites)
  • Implemented invoice preview when changing plans with error handling fallback
  • Added "Keep my subscription" button for canceled subscriptions and past-due banner
  • Enhanced accessibility with ARIA labels, focus states, and improved keyboard navigation
  • Changed Enterprise "Contact us" to mailto: link
  • Added pageview usage progress bar with color-coded indicators

Confidence Score: 4/5

  • This PR is safe to merge with minimal risk after verifying backend API endpoints exist
  • The implementation is well-structured with proper error handling and null checks. The React crash fix correctly addresses hook ordering rules. Minor uncertainty around new backend endpoints (/api/billing/preview-invoice, /api/billing/resume) that should be verified to exist before merge.
  • Verify that backend endpoints for previewInvoice and resumeSubscription are implemented and match the expected request/response format

Important Files Changed

Filename Overview
app/page.tsx Added renewal display with date and amount; improved site limit display to support multiple plans
components/settings/OrganizationSettings.tsx Fixed React crash by moving hooks above early return; added multi-plan support, past-due banner, resume subscription, invoice preview with error handling
components/PricingSection.tsx Enhanced accessibility with ARIA attributes and focus states; updated Enterprise contact to mailto link; improved design consistency
lib/api/billing.ts Added types for invoice preview, tax IDs, and next invoice fields; added resumeSubscription and previewInvoice functions
lib/plans.ts Added Team and Business plan support; added getSitesLimitForPlan helper function

Sequence Diagram

sequenceDiagram
    participant User
    participant UI as OrganizationSettings
    participant API as billing.ts
    participant Backend as Billing API

    User->>UI: Opens Change Plan modal
    UI->>UI: Set changePlanId, tier, interval
    UI->>API: previewInvoice({ plan_id, interval, limit })
    API->>Backend: POST /api/billing/preview-invoice
    Backend-->>API: { amount_due, currency, period_end }
    API-->>UI: PreviewInvoiceResult
    UI->>UI: Display prorated preview

    User->>UI: Clicks "Update plan"
    UI->>API: changePlan({ plan_id, interval, limit })
    API->>Backend: POST /api/billing/change-plan
    Backend-->>API: { ok: true }
    API-->>UI: Success
    UI->>UI: Reload subscription data
    UI->>User: Show success toast

    Note over User,Backend: Resume subscription flow
    User->>UI: Clicks "Keep my subscription"
    UI->>API: resumeSubscription()
    API->>Backend: POST /api/billing/resume
    Backend-->>API: { ok: true }
    API-->>UI: Success
    UI->>User: Show success toast

Last reviewed commit: b8cb7e1

<h3>Greptile Summary</h3> This PR enhances the billing UX by adding subscription renewal information, multi-plan support (Solo/Team/Business), and fixes a React crash issue. The changes include displaying "Renews [date] for [amount]" on the dashboard and billing tab, implementing invoice preview with error fallback for plan changes, and adding various design and accessibility improvements. **Key changes:** - Fixed React #310 crash by moving `hasActiveSubscription` and `previewInvoice` useEffect hooks above the early return in OrganizationSettings - Added support for Team and Business plans with proper site limits (1/5/10 sites) - Implemented invoice preview when changing plans with error handling fallback - Added "Keep my subscription" button for canceled subscriptions and past-due banner - Enhanced accessibility with ARIA labels, focus states, and improved keyboard navigation - Changed Enterprise "Contact us" to `mailto:` link - Added pageview usage progress bar with color-coded indicators <h3>Confidence Score: 4/5</h3> - This PR is safe to merge with minimal risk after verifying backend API endpoints exist - The implementation is well-structured with proper error handling and null checks. The React crash fix correctly addresses hook ordering rules. Minor uncertainty around new backend endpoints (`/api/billing/preview-invoice`, `/api/billing/resume`) that should be verified to exist before merge. - Verify that backend endpoints for `previewInvoice` and `resumeSubscription` are implemented and match the expected request/response format <details><summary><h3>Important Files Changed</h3></summary> | Filename | Overview | |----------|----------| | app/page.tsx | Added renewal display with date and amount; improved site limit display to support multiple plans | | components/settings/OrganizationSettings.tsx | Fixed React crash by moving hooks above early return; added multi-plan support, past-due banner, resume subscription, invoice preview with error handling | | components/PricingSection.tsx | Enhanced accessibility with ARIA attributes and focus states; updated Enterprise contact to mailto link; improved design consistency | | lib/api/billing.ts | Added types for invoice preview, tax IDs, and next invoice fields; added resumeSubscription and previewInvoice functions | | lib/plans.ts | Added Team and Business plan support; added getSitesLimitForPlan helper function | </details> </details> <h3>Sequence Diagram</h3> ```mermaid sequenceDiagram participant User participant UI as OrganizationSettings participant API as billing.ts participant Backend as Billing API User->>UI: Opens Change Plan modal UI->>UI: Set changePlanId, tier, interval UI->>API: previewInvoice({ plan_id, interval, limit }) API->>Backend: POST /api/billing/preview-invoice Backend-->>API: { amount_due, currency, period_end } API-->>UI: PreviewInvoiceResult UI->>UI: Display prorated preview User->>UI: Clicks "Update plan" UI->>API: changePlan({ plan_id, interval, limit }) API->>Backend: POST /api/billing/change-plan Backend-->>API: { ok: true } API-->>UI: Success UI->>UI: Reload subscription data UI->>User: Show success toast Note over User,Backend: Resume subscription flow User->>UI: Clicks "Keep my subscription" UI->>API: resumeSubscription() API->>Backend: POST /api/billing/resume Backend-->>API: { ok: true } API-->>UI: Success UI->>User: Show success toast ``` <sub>Last reviewed commit: b8cb7e1</sub>
Sign in to join this conversation.
No description provided.