Skip to content

fix(frontend): clarify expired trial plans state - #2927

Open
WcaleNieWolny wants to merge 15 commits into
mainfrom
wolny/expired-trial-plans-state
Open

fix(frontend): clarify expired trial plans state#2927
WcaleNieWolny wants to merge 15 commits into
mainfrom
wolny/expired-trial-plans-state

Conversation

@WcaleNieWolny

@WcaleNieWolny WcaleNieWolny commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Summary

  • show neutral expired-trial heading and subtext only for organizations that never paid
  • suppress the failed-payment banner until billing history resolves, while preserving the existing fallback on lookup errors
  • remove selected and recommended plan styling from the expired-trial state
  • preserve existing behavior and CTA order for previously paid, canceled, and ended subscriptions
  • fix current main-branch type and CLI test-fixture regressions that blocked CI

Test Plan

  • bun lint
  • bun test:unit (200 files, 1,446 tests)
  • bun run typecheck:frontend
  • CHOKIDAR_USEPOLLING=true bun run build

Summary by CodeRabbit

  • New Features

    • Added clearer plan-selection messaging for expired trials.
    • Expired, never-paid trials now receive neutral plan presentation and plan-specific actions.
    • Added English translations for choosing plans and continuing after a trial ends.
    • Improved payment-status handling across the plans page and payment-required dialog.
  • Bug Fixes

    • Prevented outdated billing responses from overwriting current organization state.
    • Improved payment-failure banner behavior when billing information is unavailable.
    • Preserved existing behavior for paid, canceled, native, and unresolved billing states.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds shared billing-history lookup state and expired-trial predicates. Updates the plans page and payment-required modal to use this state. Adds expired-trial copy, plan actions, neutral card styling, failure-banner handling, and focused tests.

Changes

Expired trial plans

Layer / File(s) Summary
Billing state resolution and predicates
src/services/paymentRequired.ts, src/composables/useBillingPaidAt.ts, tests/payment-required-copy.unit.test.ts, docs/superpowers/...
Adds billing-date resolution, expired-trial predicates, stale-response protection, lookup failure state, and focused resolver tests.
Shared composable integration
src/components/PaymentRequiredModal.vue, src/auto-imports.d.ts, docs/superpowers/...
Replaces the modal’s local billing lookup with useBillingPaidAt and adds its auto-import declarations.
Plans page expired-trial presentation
src/pages/settings/organization/Plans.vue, messages/en.json, tests/plans-expired-trial-layout.unit.test.ts, docs/superpowers/...
Updates expired-trial headings, descriptions, actions, card styling, failure banners, CTA placement, translations, and layout coverage.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Organization
  participant PlansPage
  participant useBillingPaidAt
  participant Supabase
  Organization->>PlansPage: select organization
  PlansPage->>useBillingPaidAt: provide organization GID
  useBillingPaidAt->>Supabase: request stripe_info(paid_at)
  Supabase-->>useBillingPaidAt: paidAt or lookup failure
  useBillingPaidAt-->>PlansPage: update billing state
  PlansPage->>Organization: render expired-trial plans state
Loading

Possibly related PRs

  • Cap-go/capgo.app#2909: Adds related expired-trial billing lookup, modal behavior, translations, and tests that this change extends to the plans page and shared composable.
  • Cap-go/capgo.app#2942: Also changes Plans.vue to position credits and premium-support CTAs relative to the plans grid.

Suggested labels: codex

Suggested reviewers: riderx

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the primary change: clarifying the frontend state for expired trial plans.
Description check ✅ Passed The description provides a relevant summary and test plan with reported lint, unit-test, typecheck, and build results.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands.

@codspeed-hq

codspeed-hq Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 43 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing wolny/expired-trial-plans-state (8e5343c) with main (a06de19)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed against the latest diff

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/pages/settings/organization/Plans.vue Outdated
Comment thread docs/superpowers/plans/2026-08-07-expired-trial-plans-state.md Outdated
Comment thread src/pages/settings/organization/Plans.vue Outdated
Comment thread src/pages/settings/organization/Plans.vue Outdated
@WcaleNieWolny

Copy link
Copy Markdown
Contributor Author

Addressed all four Cubic findings in c542524: the red banner is suppressed while billing history is unresolved, lookup failures are logged and retain the existing failure fallback, Plans now uses resolveBillingPaidAt, and Credits/Expert CTAs render once with state-dependent ordering. Added banner-state coverage; lint, frontend typecheck, 200 unit files / 1,446 tests, and production build pass locally.

@WcaleNieWolny

Copy link
Copy Markdown
Contributor Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Aug 7, 2026

Copy link
Copy Markdown

@cubic-dev-ai review this PR

@WcaleNieWolny I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 8 files

Confidence score: 5/5

  • In src/pages/settings/organization/Plans.vue, the new billing-history watcher duplicates the Supabase fetch and billingLookupRun stale-response guard, which raises maintenance risk: future fixes could land in one path but not the other and cause inconsistent billing timestamps or race-handling behavior — extract this logic into a shared helper/composable and call it from both watchers.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/pages/settings/organization/Plans.vue">

<violation number="1" location="src/pages/settings/organization/Plans.vue:68">
P3: This new billing-history watcher duplicates the exact Supabase query and stale-response guard (`.from('orgs').select('stripe_info(paid_at)').eq('id', orgId).maybeSingle()` plus the `billingLookupRun` token) that already exists inline in `src/components/PaymentRequiredModal.vue` (lines ~21-38). The PR adds a second copy of the same lookup rather than sharing it, so any future change to the query (e.g., RLS shape, added fields, or the never-paid/missing-relation semantics) has to be applied in two places and can drift. Consider extracting the lookup into a small shared helper (or composable) alongside the pure predicates in `src/services/paymentRequired.ts`, which is exactly what the implementation plan describes as "shared billing-history predicates used by dashboard and plans-page presentation."</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread docs/superpowers/plans/2026-08-07-expired-trial-plans-state.md Outdated
Comment thread src/pages/settings/organization/Plans.vue Outdated
@WcaleNieWolny

Copy link
Copy Markdown
Contributor Author

Addressed both follow-up Cubic findings in c046ffd: the implementation plan now defines every referenced predicate and the shared composable workflow, and PaymentRequiredModal plus Plans now consume one useBillingPaidAt implementation for the Supabase query, lookup-error state, and stale-response guard. Local lint, frontend typecheck, 200 unit files / 1,446 tests, and production build pass.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/cli-app-permission-helper.test.ts`:
- Line 6: Remove the earlier duplicate appAddHintMessage property from the test
fixture, keeping the later definition that intentionally overwrites it so Biome
no longer reports a duplicate key.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 94d0e6b4-b345-44b1-bd66-cee9d5a6b367

📥 Commits

Reviewing files that changed from the base of the PR and between e82dd01 and 479c1a8.

📒 Files selected for processing (10)
  • docs/superpowers/plans/2026-08-07-expired-trial-plans-state.md
  • docs/superpowers/specs/2026-08-07-expired-trial-plans-state-design.md
  • messages/en.json
  • src/auto-imports.d.ts
  • src/components/PaymentRequiredModal.vue
  • src/composables/useBillingPaidAt.ts
  • src/pages/settings/organization/Plans.vue
  • src/services/paymentRequired.ts
  • tests/cli-app-permission-helper.test.ts
  • tests/payment-required-copy.unit.test.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Cap-go/capacitor-updater (manual)

Comment thread tests/cli-app-permission-helper.test.ts Outdated
@WcaleNieWolny

Copy link
Copy Markdown
Contributor Author

Addressed the post-merge CodeRabbit finding in 5b34c65 by removing the earlier duplicate appAddHintMessage mock and retaining main’s complete hint implementation. The focused CLI permission-helper test passes (2/2), and the repository lint/typecheck/unit gates had passed on the merged head.

posthog-eu Bot added a commit that referenced this pull request Aug 8, 2026
Unpaid organizations that land on a gated app page (devices, bundles,
channels, builds, notifications) saw a blurred empty table behind the
payment modal, with no page-level reason and no visible route to the
plans page. Add a shared UnpaidState empty state that explains why the
list is hidden and links to the plans page, and stop the layout overlay
from covering those pages so the explanation is visible.

The block itself is unchanged: the pages still render no data when the
organization has no active subscription. The payment-modal copy flip is
handled separately by PR #2927 and is left untouched.

Generated-By: PostHog Code
Task-Id: 21fb1bad-b78a-4701-803d-0571de027a1f

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/plans-expired-trial-layout.unit.test.ts`:
- Around line 7-10: Update the test case “keeps the credits and premium support
banners ahead of the plans” to assert ordering directly: verify the <CreditsCta>
and expert-support content appear before the “<!-- Plans Grid -->” marker in
plansSource. Keep or replace the existing class-removal assertions as
appropriate, but ensure the test fails if the plans grid precedes either CTA.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: cdeedd1d-29a4-4753-94b1-8093d8b20ad2

📥 Commits

Reviewing files that changed from the base of the PR and between 479c1a8 and 5b355f9.

📒 Files selected for processing (2)
  • src/pages/settings/organization/Plans.vue
  • tests/plans-expired-trial-layout.unit.test.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Cap-go/capacitor-updater (manual)

Comment thread tests/plans-expired-trial-layout.unit.test.ts Outdated
…lans-state

# Conflicts:
#	src/pages/settings/organization/Plans.vue

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/pages/settings/organization/Plans.vue (1)

638-662: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep CTA placement state-dependent.

CreditsCta and the expert-support CTA now appear after the plans grid for every billing state. This changes the existing layout for previously paid, canceled, and ended subscriptions, although the PR requires their CTA order and behavior to remain unchanged.

Restore the showExpiredTrialState-dependent ordering, or use a state-specific wrapper, so only expired-trial pages place these CTAs below the plans. Add a regression test for a non-expired state.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/settings/organization/Plans.vue` around lines 638 - 662, Update the
CTA layout around CreditsCta and the Expert as a Service block to preserve the
existing showExpiredTrialState-dependent ordering: render them below the plans
only for expired-trial pages, while keeping the established placement and
behavior for paid, canceled, and ended subscriptions. Use the existing
state-specific wrapper or condition, and add a regression test covering a
non-expired state.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/pages/settings/organization/Plans.vue`:
- Around line 638-662: Update the CTA layout around CreditsCta and the Expert as
a Service block to preserve the existing showExpiredTrialState-dependent
ordering: render them below the plans only for expired-trial pages, while
keeping the established placement and behavior for paid, canceled, and ended
subscriptions. Use the existing state-specific wrapper or condition, and add a
regression test covering a non-expired state.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 894235af-d0a0-4bd8-ab49-4e85014aee9e

📥 Commits

Reviewing files that changed from the base of the PR and between 12ad9a8 and 8e5343c.

📒 Files selected for processing (3)
  • messages/en.json
  • src/pages/settings/organization/Plans.vue
  • tests/plans-expired-trial-layout.unit.test.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Cap-go/capacitor-updater (manual)

@sonarqubecloud

sonarqubecloud Bot commented Aug 9, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant