Skip to content

feat(billing): meter UX refonte — drop drawer + subscriptions tab#4059

Merged
PierreBrisorgueil merged 4 commits into
masterfrom
feat/meter-ux-refonte
May 1, 2026
Merged

feat(billing): meter UX refonte — drop drawer + subscriptions tab#4059
PierreBrisorgueil merged 4 commits into
masterfrom
feat/meter-ux-refonte

Conversation

@PierreBrisorgueil
Copy link
Copy Markdown
Collaborator

@PierreBrisorgueil PierreBrisorgueil commented May 1, 2026

Summary

Refonte the meter UX so the compute bar is no longer mounted globally and lives inside the user account "Subscriptions" tab. All meter-specific UI is gated by serverConfig.billing.meterMode === true. Bundled in ONE PR to minimise downstream /update-stack runs.

Changes (D1…D7)

  • D1 — Drop drawer: deleted billing.meterDrawer.component.vue; billing.usageBar.component.vue now informational only (no @open-drawer, no role=button, no cursor:pointer).
  • D2 — Extract subscriptions component: new billing.subscriptions.component.vue (plan card + meter widget + extras + ledger + Stripe portal).
  • D3 — Subscriptions tab in account: users/views/user.view.vue gets a 3rd tab visible to org owners/admins on billing-enabled servers; auto-switches when route has ?tab=subscriptions or #subscriptions.
  • D4 — Pricing tabs glass + packs cards: new billing.packs.component.vue (purchase cards mapping config.billing.packs[]), and the pricing view wraps content in glass tabs (Plans | Units) when meter mode is on. Legacy mode unchanged.
  • D5 — Redirect /billing: /billing now redirects to /users?tab=subscriptions. The standalone billing.billing.view.vue is deleted.
  • D6 — i18n: billing.subscriptions.*, billing.pricing.tabs.*, billing.packs.* (en + fr) and new users/lang/{en,fr}.js with users.tabs.{profile,organizations,subscriptions}.
  • D7 — Meter threshold alerts in devkit app.vue: ports the 80% / 100% snackbar logic from trawl_vue/src/modules/app/app.vue, gated on isLoggedIn && meterMode. The bar/drawer are NOT mounted globally — only the alerts.

BREAKING UI

  • The drawer is removed.
  • /billing is no longer a stand-alone page; it redirects.
  • Downstream projects must remove direct global mounts of BillingUsageBarComponent / BillingMeterDrawerComponent from their app.vue (handled by /update-stack).

Test plan

  • npm run lint — clean
  • npm run test:unit1278 / 1278 passed, no failures
  • Coverage thresholds met (per-file 70/60/70/70)
  • CI green on this PR
  • CodeRabbit pass
  • Manual smoke after /update-stack propagation: trawl_vue landing on /users?tab=subscriptions after hitting /billing, glass tabs on pricing, no global meter bar.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added automatic meter threshold toast notifications when usage reaches 80% and 100% of your weekly limit.
    • Introduced Subscriptions tab in your user profile, consolidating billing management and meter tracking.
    • Added Units purchasing interface with available packs displayed in Pricing page.
    • Added meter progress visualization with weekly breakdown and extras ledger with pagination support.
  • Changes

    • Usage bar is now informational only; no longer opens a drawer on interaction.
    • Billing page now redirects to Subscriptions tab in your user profile.
  • Documentation

    • Added English and French translations for new billing and subscription features.

Refonte of the meter UX so the compute bar is no longer mounted globally
and lives inside the user account "Subscriptions" tab. All meter-specific
UI is gated by `serverConfig.billing.meterMode === true`.

D1 — Drop drawer
  - Delete `billing.meterDrawer.component.vue` and its test.
  - `billing.usageBar.component.vue` is now informational only: drop
    `@open-drawer` emit, click handler, role=button, cursor:pointer.

D2 — Extract subscriptions component
  - New `billing.subscriptions.component.vue` containing plan card,
    meter widget (gated), extras balance, ledger, Stripe portal button.
  - Replaces the standalone billing view UI.

D3 — Subscriptions tab in account
  - Add 3rd tab in `users/views/user.view.vue`, visible to org
    owners/admins on billing-enabled servers (meterMode OR active sub).
  - Tab content renders `<BillingSubscriptionsComponent />`.
  - Auto-select the tab when ?tab=subscriptions / #subscriptions is on
    the route (used by the /billing redirect).

D4 — Pricing tabs glass + packs cards
  - New `billing.packs.component.vue` rendering `config.billing.packs[]`
    as clickable purchase cards (calls `createExtrasCheckout(packId)`).
  - In meter mode, wrap pricing in glass tabs (Plans | Units) using the
    existing `home.tabs.component.vue`. Legacy mode unchanged.

D5 — Redirect /billing
  - `/billing` route is now a redirect to `/users?tab=subscriptions`.
  - `billing.billing.view.vue` is deleted (superseded by the component).

D6 — i18n
  - Add `billing.subscriptions.*`, `billing.pricing.tabs.*`,
    `billing.packs.*` keys (en + fr).
  - New `users/lang/{en,fr}.js` with `users.tabs.{profile,organizations,subscriptions}`.

D7 — Meter threshold alerts in devkit app.vue
  - Port the 80% / 100% snackbar logic from trawl_vue into devkit
    `app/app.vue`, gated on `isLoggedIn && meterMode`. The bar/drawer
    are NOT mounted globally — only the alerts.

Tests
  - 1278 / 1278 passed (lint + vitest), coverage thresholds met.
  - New `billing.subscriptions.component.unit.tests.js` covers meter +
    legacy mode rendering, ledger pagination, manage-subscription flow.
  - `user.view.unit.tests.js` rewritten for showSubscriptionsTab + tab
    routing from query/hash.
  - `app.router.unit.tests.js` updated for the /billing → /users
    redirect.
  - `billing.e2e.tests.js` updated to assert /users?tab=subscriptions
    landing instead of the retired Billing heading.

BREAKING UI: drawer removed, /billing redirected, the page-level
Billing view is gone. Downstream projects must remove any direct global
mount of `BillingUsageBarComponent` / `BillingMeterDrawerComponent`
from their `app.vue` (handled by /update-stack).
Copilot AI review requested due to automatic review settings May 1, 2026 13:27
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 1, 2026

Warning

Rate limit exceeded

@PierreBrisorgueil has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 43 minutes and 27 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: f7963f68-11ba-4ed8-81ee-d51a8f98e9fa

📥 Commits

Reviewing files that changed from the base of the PR and between facf2fc and 1b9a4fc.

📒 Files selected for processing (9)
  • src/modules/app/app.vue
  • src/modules/billing/components/billing.packs.component.vue
  • src/modules/billing/components/billing.subscriptions.component.vue
  • src/modules/billing/config/billing.development.config.js
  • src/modules/billing/config/billing.static-content.js
  • src/modules/billing/tests/billing.packs.component.unit.tests.js
  • src/modules/billing/views/billing.pricing.view.vue
  • src/modules/users/tests/user.view.unit.tests.js
  • src/modules/users/views/user.view.vue

Walkthrough

This PR consolidates billing UI from a dedicated page into the user profile as a "Subscriptions" tab. The /billing route now redirects to /users?tab=subscriptions. New components handle subscription display and unit pack purchases. Meter usage alerts are added to the app shell, and tests are updated to reflect the new routing and component structure.

Changes

Cohort / File(s) Summary
App Shell Meter Alerts
src/modules/app/app.vue
Adds reactive meter-threshold toast notifications triggered by a watcher on meterProgress. Fires one-time warnings at 80% and errors at 100% within a billing week using a deduplicated Set keyed by ${weekKey}:${level}.
Billing Router Redirect
src/modules/billing/router/billing.router.js
Replaces /billing route component with a redirect to /users?tab=subscriptions, preserving backwards compatibility for old billing links.
Deleted Components
src/modules/billing/components/billing.meterDrawer.component.vue, src/modules/billing/views/billing.billing.view.vue
Removes dedicated meter drawer and billing view components, consolidating their functionality into the new BillingSubscriptionsComponent.
New Billing Components
src/modules/billing/components/billing.subscriptions.component.vue, src/modules/billing/components/billing.packs.component.vue
Introduces BillingSubscriptionsComponent for displaying subscription status and meter-mode UI (usage bar, ledger pagination), and BillingPacksComponent for rendering purchasable unit packs with error handling.
Updated Billing Components
src/modules/billing/components/billing.usageBar.component.vue, src/modules/billing/views/billing.pricing.view.vue
Removes interactive event handlers from usage bar (no longer emits open-drawer), and adds tabbed UI to pricing view with "Plans" and "Units" tabs using new BillingPacksComponent.
User Profile Integration
src/modules/users/views/user.view.vue
Replaces /billing link with in-page "Subscriptions" tab. Adds route-driven tab selection via $route.query.tab and $route.hash watchers. Registers new BillingSubscriptionsComponent.
Internationalization
src/modules/billing/lang/en.js, src/modules/billing/lang/fr.js, src/modules/users/lang/en.js, src/modules/users/lang/fr.js
Adds English and French i18n strings for subscriptions, unit packs, pricing tabs, and user tabs (profile, organizations, subscriptions).
Updated Tests
src/modules/app/tests/app.router.unit.tests.js, src/modules/billing/tests/billing.e2e.tests.js, src/modules/billing/tests/billing.usageBar.component.unit.tests.js, src/modules/billing/tests/billing.subscriptions.component.unit.tests.js, src/modules/users/tests/user.view.unit.tests.js
Updates router tests to reflect /billing/users?tab=subscriptions redirect, adjusts E2E assertions, removes interactive expectations from usage bar tests, adds comprehensive tests for new subscriptions component, and refactors user view tests to validate new tab routing.
Deleted Tests
src/modules/billing/tests/billing.billing.view.unit.tests.js, src/modules/billing/tests/billing.compute.integration.unit.tests.js, src/modules/billing/tests/billing.meterDrawer.component.unit.tests.js
Removes test suites for deleted billing view and meter drawer components, and removes extensive compute/integration tests for meter-mode rendering and checkout flows.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Possibly related PRs

Suggested labels

Feat, Tests

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description covers the summary, detailed changes (D1–D7), breaking UI changes, and test results; however, it lacks required sections from the template: Scope (modules impacted, risk level), Validation checklist completion, Guardrails checks, and Notes for reviewers. Complete missing template sections: add Scope details (risk level: medium/high), check all Validation items, document Guardrails (no secrets, no risky renames, merge-friendliness, tests updated), and add reviewer notes on security/mergeability.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main changes: dropping the drawer UI component and adding a subscriptions tab within the user account view.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/meter-ux-refonte

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 43 minutes and 27 seconds.

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

@codacy-production
Copy link
Copy Markdown

codacy-production Bot commented May 1, 2026

Not up to standards ⛔

🔴 Issues 10 high

Alerts:
⚠ 10 issues (≤ 0 issues of at least minor severity)

Results:
10 new issues

Category Results
ErrorProne 10 high

View in Codacy

🟢 Metrics 117 complexity · 18 duplication

Metric Results
Complexity 117
Duplication 18

View in Codacy

AI Reviewer: first review requested successfully. AI can make mistakes. Always validate suggestions.

Run reviewer

TIP This summary will be updated as you push new changes.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 1, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.51%. Comparing base (7d494af) to head (1b9a4fc).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #4059   +/-   ##
=======================================
  Coverage   99.51%   99.51%           
=======================================
  Files          31       31           
  Lines        1034     1034           
  Branches      278      278           
=======================================
  Hits         1029     1029           
  Misses          5        5           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown

@codacy-production codacy-production Bot left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR is currently not up to standards. While the structural migration of the billing UX is largely complete, there are critical architectural and safety issues that prevent merging. Most notably, a development-specific configuration is imported directly into a production module, and the core app.vue logic for billing alerts contains both a potential race condition and an inefficient Pinia usage pattern that has significantly increased cyclomatic complexity. Furthermore, although the PR intent explicitly lists i18n support, multiple components remain dependent on hardcoded English strings. There is also a notable absence of automated tests for the new threshold alert logic and pricing tab functionality.

About this PR

  • Systemic issue: New UI components and alert logic are using hardcoded strings despite the PR's stated objective to support i18n and the presence of new keys in 'en.js' and 'fr.js'.

Test suggestions

  • Verify /billing redirects to /users?tab=subscriptions for authenticated users
  • Verify the Subscriptions tab in User Account is only visible to owners or admins
  • Verify compute threshold alerts (80%/100%) fire once per week key
  • Verify tab switching logic in Pricing view between Plans and Units
  • Verify the usage bar is no longer interactive in meter mode
Prompt proposal for missing tests
Consider implementing these tests if applicable:
1. Verify compute threshold alerts (80%/100%) fire once per week key
2. Verify tab switching logic in Pricing view between Plans and Units
Low confidence findings
  • The 'meterProgress' watch in 'app.vue' may fire duplicate alerts if the 'meterWeekKey' is initially null ('unknown') and subsequently updates to a valid week key after the first alert fires. Consider adding a check to ensure both values are resolved before triggering the snackbar.

TIP Improve review quality by adding custom instructions
TIP How was this review? Give us feedback

Comment thread src/modules/billing/components/billing.packs.component.vue Outdated
Comment thread src/modules/billing/views/billing.pricing.view.vue
Comment thread src/modules/app/app.vue Outdated
Comment thread src/modules/app/app.vue Outdated
Comment thread src/modules/billing/components/billing.subscriptions.component.vue Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Refactors the billing “meter” UX by removing the global drawer/page flow and relocating subscription + meter UI into the user account “Subscriptions” tab, while keeping /billing working via redirect and adding meter-related UI guards.

Changes:

  • Moves billing/subscription UX into UserView via a new BillingSubscriptionsComponent, gated by billing config + org role.
  • Updates pricing to add “Plans | Units” glass tabs in meter mode and introduces a new packs purchase grid component.
  • Removes the legacy /billing standalone view and meter drawer, updating unit/e2e/router tests accordingly.

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/modules/users/views/user.view.vue Adds “Subscriptions” tab + route-driven tab selection and mounts BillingSubscriptionsComponent
src/modules/users/tests/user.view.unit.tests.js Updates/extends tests for tab visibility and query/hash tab routing
src/modules/users/lang/en.js Adds users tab i18n key map (EN)
src/modules/users/lang/fr.js Adds users tab i18n key map (FR)
src/modules/billing/views/billing.pricing.view.vue Adds glass tabs in meter mode and renders BillingPacksComponent as “Units” tab
src/modules/billing/views/billing.billing.view.vue Deletes standalone Billing view
src/modules/billing/router/billing.router.js Changes /billing route to redirect to /users?tab=subscriptions
src/modules/billing/components/billing.usageBar.component.vue Makes meter usage bar informational-only (drops click/keyboard emit)
src/modules/billing/tests/billing.usageBar.component.unit.tests.js Updates usage bar tests to match informational behavior
src/modules/billing/components/billing.subscriptions.component.vue New consolidated subscriptions panel with meter + extras ledger in meter mode
src/modules/billing/tests/billing.subscriptions.component.unit.tests.js Adds unit tests for BillingSubscriptionsComponent behaviors
src/modules/billing/components/billing.packs.component.vue Adds purchasable packs grid that calls createExtrasCheckout
src/modules/billing/lang/en.js Adds i18n keys for subscriptions/pricing tabs/packs (EN)
src/modules/billing/lang/fr.js Adds i18n keys for subscriptions/pricing tabs/packs (FR)
src/modules/billing/components/billing.meterDrawer.component.vue Deletes meter drawer component
src/modules/billing/tests/billing.meterDrawer.component.unit.tests.js Deletes meter drawer unit tests
src/modules/billing/tests/billing.billing.view.unit.tests.js Deletes Billing view unit tests
src/modules/billing/tests/billing.compute.integration.unit.tests.js Deletes billing compute integration unit tests
src/modules/billing/tests/billing.e2e.tests.js Updates e2e expectations for /billing redirect behavior
src/modules/app/tests/app.router.unit.tests.js Updates router tests for /billing redirect
src/modules/app/app.vue Adds global meter threshold snackbars gated by login + meterMode

Comment thread src/modules/users/views/user.view.vue
Comment thread src/modules/billing/components/billing.packs.component.vue Outdated
Comment thread src/modules/billing/components/billing.packs.component.vue Outdated
Comment thread src/modules/billing/components/billing.packs.component.vue
…setup, dedup ledger call

- Rename billing.development.config.js → billing.static-content.js (canonical source);
  keep old file as backward-compat re-export shim for downstream projects
- Move useAuthStore/useBillingStore init from computed into setup() in app.vue
  (fixes Pinia store initialised on every computed evaluation — HIGH)
- Align meterAlert texts with i18n key values in billing.alerts.threshold80/100
- Add i18n key comments to hardcoded tab labels in billing.pricing.view.vue
- Remove redundant fetchExtrasLedger() in mounted() — already handled by
  immediate watcher in setup() (billing.subscriptions.component.vue)
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

Caution

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

⚠️ Outside diff range comments (1)
src/modules/users/views/user.view.vue (1)

254-279: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Re-run the route-tab selection after organizations finish loading.

mounted() can execute before fetchOrganizations() resolves, so /users?tab=subscriptions initially fails the showSubscriptionsTab check and falls back to profile. Because only route changes call applyTabFromRoute(), the tab never self-corrects once org roles arrive.

💡 Minimal fix
   async created() {
     try {
       await this.organizationsStore.fetchOrganizations();
+      this.applyTabFromRoute();
     } catch {
       // interceptor handles snackbar
     }
   },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/modules/users/views/user.view.vue` around lines 254 - 279, The tab
selection can run before organizations finish loading, so after successfully
awaiting this.organizationsStore.fetchOrganizations() in the created() lifecycle
hook call this.applyTabFromRoute() to re-run the route-tab selection (so
showSubscriptionsTab has up-to-date org roles); keep the existing mounted() call
or remove it if redundant, and preserve the existing catch behavior for the
fetchOrganizations() call.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/modules/app/app.vue`:
- Around line 101-106: The dedupe Set meterAlertedKeys is currently keyed only
by `${weekKey}:${level}`, causing alerts to be suppressed across organizations;
update all places that build or check the dedupe key (where
meterAlertedKeys.add(...) and meterAlertedKeys.has(...) are used) to include the
active organization id (e.g., `${activeOrganizationId}:${weekKey}:${level}`),
update the JSDoc/type comment for meterAlertedKeys to reflect the new format,
and ensure any helper that constructs the key (or create a small helper like
getMeterAlertKey(orgId, weekKey, level)) is used consistently wherever the
dedupe check or insertion occurs.

In `@src/modules/billing/components/billing.packs.component.vue`:
- Around line 124-133: The onBuy method currently calls
billingStore.createExtrasCheckout(pack.packId) directly and must reuse the same
auth/org guard used by onSelectPlan: before setting this.purchasingId or calling
createExtrasCheckout, check the user's auth and current organization (the same
condition/redirect logic used in onSelectPlan) and if unauthenticated or missing
org, trigger the sign-in/org-selection redirect flow instead of initiating the
extras checkout; only proceed to call createExtrasCheckout when the guard
passes, and ensure to reference onBuy, onSelectPlan, createExtrasCheckout,
billingStore and purchasingId when making the change.

In `@src/modules/billing/components/billing.subscriptions.component.vue`:
- Around line 194-204: The watch on meterMode with { immediate: true } already
triggers billingStore.fetchExtrasLedger({ page: 1, limit: 20 }) when meterMode
is active, so remove the duplicate fetch call from mounted() (and the similar
duplicate at the other occurrence around the code referenced as lines 262-264)
to avoid sending the first ledger page twice; keep the watch as-is (or
alternatively remove the immediate flag and call fetch from mounted only) but do
not call billingStore.fetchExtrasLedger for page 1 in both places.
- Around line 251-265: The mounted() hook must detect the legacy packPurchased
query flag and surface a success state: read this.$route.query.packPurchased (or
equivalent router query) in mounted(), and if present (truthy), call a new
handler (e.g., handlePackPurchased() or
billingStore.processPackPurchaseSuccess()) or set a component flag (e.g.,
packPurchasedSuccess) that triggers the existing success UI/modal and refreshes
billing state (ensure you still call billingStore.fetchSubscription()); also
clear or replace the query param so repeated mounts don't re-show the message.
Ensure the references are to mounted(), billingStore.createExtrasCheckout(), and
billingStore.fetchSubscription() so the behavior connects to the checkout flow.

In `@src/modules/billing/tests/billing.e2e.tests.js`:
- Around line 140-145: Tests reverted to using waitForURL/toHaveURL reintroduced
a flakey race with auth-store rehydration; restore the intentional fixed delay
before asserting redirects. In the test named "redirects unauthenticated user to
signin" (and the analogous test around lines 184-189), reinsert a
page.waitForTimeout(2000) immediately after page.goto('/billing') and before the
URL assertion, so the SPA redirect has time to settle, then perform the
expect(page.url()).toContain('/signin') (and the other redirect assertions) as
before.

In `@src/modules/users/views/user.view.vue`:
- Around line 241-252: The showSubscriptionsTab() guard in the component is too
strict: instead of requiring meterMode || this.isPlanActive, change it so that
if billing is enabled (this.authStore.serverConfig?.billing?.enabled === true)
and the user has owner/admin role (this.hasOwnerOrAdminRole) the tab is shown;
i.e. remove the final meterMode || this.isPlanActive check in
showSubscriptionsTab() so BillingSubscriptionsComponent can render its free-plan
state (subscription may be null).

---

Outside diff comments:
In `@src/modules/users/views/user.view.vue`:
- Around line 254-279: The tab selection can run before organizations finish
loading, so after successfully awaiting
this.organizationsStore.fetchOrganizations() in the created() lifecycle hook
call this.applyTabFromRoute() to re-run the route-tab selection (so
showSubscriptionsTab has up-to-date org roles); keep the existing mounted() call
or remove it if redundant, and preserve the existing catch behavior for the
fetchOrganizations() call.
🪄 Autofix (Beta)

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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: fcd8a749-cbee-4a2b-879d-68e1e347e072

📥 Commits

Reviewing files that changed from the base of the PR and between 7d494af and facf2fc.

📒 Files selected for processing (21)
  • src/modules/app/app.vue
  • src/modules/app/tests/app.router.unit.tests.js
  • src/modules/billing/components/billing.meterDrawer.component.vue
  • src/modules/billing/components/billing.packs.component.vue
  • src/modules/billing/components/billing.subscriptions.component.vue
  • src/modules/billing/components/billing.usageBar.component.vue
  • src/modules/billing/lang/en.js
  • src/modules/billing/lang/fr.js
  • src/modules/billing/router/billing.router.js
  • src/modules/billing/tests/billing.billing.view.unit.tests.js
  • src/modules/billing/tests/billing.compute.integration.unit.tests.js
  • src/modules/billing/tests/billing.e2e.tests.js
  • src/modules/billing/tests/billing.meterDrawer.component.unit.tests.js
  • src/modules/billing/tests/billing.subscriptions.component.unit.tests.js
  • src/modules/billing/tests/billing.usageBar.component.unit.tests.js
  • src/modules/billing/views/billing.billing.view.vue
  • src/modules/billing/views/billing.pricing.view.vue
  • src/modules/users/lang/en.js
  • src/modules/users/lang/fr.js
  • src/modules/users/tests/user.view.unit.tests.js
  • src/modules/users/views/user.view.vue
💤 Files with no reviewable changes (5)
  • src/modules/billing/tests/billing.billing.view.unit.tests.js
  • src/modules/billing/tests/billing.meterDrawer.component.unit.tests.js
  • src/modules/billing/tests/billing.compute.integration.unit.tests.js
  • src/modules/billing/components/billing.meterDrawer.component.vue
  • src/modules/billing/views/billing.billing.view.vue

Comment thread src/modules/app/app.vue Outdated
Comment thread src/modules/billing/components/billing.packs.component.vue
Comment thread src/modules/billing/components/billing.subscriptions.component.vue
Comment thread src/modules/billing/components/billing.subscriptions.component.vue
Comment thread src/modules/billing/tests/billing.e2e.tests.js
Comment thread src/modules/users/views/user.view.vue
…t, tests

- user.view.vue: add watcher on showSubscriptionsTab to re-apply route tab
  when it becomes true; fixes async race where applyTabFromRoute() runs
  before fetchOrganizations() resolves (Copilot #1)
- billing.packs.component.vue: remove card-level @click + cursor:pointer —
  the <v-btn> inside is already keyboard accessible; avoids inaccessible
  clickable area for keyboard/screen-reader users (Copilot #2)
- billing.packs.component.vue: update component header comment to accurately
  describe the real data source (store first, static fallback) (Copilot #3)
- billing.packs.component.unit.tests.js: add focused unit test suite covering
  empty state, pack card rendering, happy-path purchase, failure banner,
  and loading/disabled state (Copilot #4)
…uard, tab gate, pack UX

- app.vue: include activeOrgId in meterAlertedKeys dedupe key
  (${orgId}:${weekKey}:${level}) so switching organizations does not suppress
  alerts for the new org within the same billing week (CR major)
- billing.packs.component.vue: add auth/org guard in onBuy() — mirrors
  onSelectPlan() pattern: guests → /signin, no-org → /organization-required;
  update tests to cover logged-in (happy/error/loading) and guest guard paths
- billing.subscriptions.component.vue: detect ?packPurchased=1 redirect param
  in mounted() and show success banner; clear the query param to prevent
  re-display on refresh (CR minor)
- user.view.vue: remove meterMode || isPlanActive restriction from
  showSubscriptionsTab — gate is now billingEnabled && hasOwnerOrAdminRole
  only; BillingSubscriptionsComponent already handles the free-plan state (CR major)
- user.view.unit.tests.js: update test expectation to match new correct behavior
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