feat(billing): paid-seat paywall UI + i18n - #5167
Open
rafavalls wants to merge 1 commit into
Open
Conversation
When a free seat attempts a paid action the backend returns a `[PAID_SEAT_REQUIRED]` 403. This turns that into a role-aware paywall instead of a generic error toast. Frontend only (UI + i18n). The checkout/seat wiring is left as a single seam in SubscribeCta for a follow-up. - is-paid-seat-error: pure `[PAID_SEAT_REQUIRED]` prefix detector (mirrors is-credit-error) + unit tests - paid-seat-store: tiny external store so the global MutationCache can open the paywall from outside React - Triggers: global MutationCache.onError (connection/agent creation etc.) → root-mounted PaidSeatPaywallHost; and chat streaming errors inline via the chat highlight stack - PaidSeatDialog: dark branded surface (deco-green spotlight), role-aware — owner/admin see Subscribe (placeholder), members are pointed at an admin; responsive/mobile-safe, design-system tokens + Button - SubscribeCta: standalone slot for the billing follow-up - i18n: new `paywall` domain, en + pt-BR mirrored Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When a free seat attempts a paid action, the backend returns a
[PAID_SEAT_REQUIRED]403 (same convention as[CREDITS]). This PR turns that into a role-aware paywall experience instead of a generic error toast.Scope: frontend only (UI + i18n). The checkout / seat wiring is intentionally left as a single seam (
SubscribeCta) for a billing follow-up.What's included
is-paid-seat-error.ts— pure[PAID_SEAT_REQUIRED]prefix detector mirroringis-credit-error.ts, with unit tests.paid-seat-store.ts— tinyuseSyncExternalStoreso the globalMutationCachecan open the paywall from outside React.MutationCache.onError→ root-mountedPaidSeatPaywallHost.PaidSeatDialog— dark, branded surface (deco-green spotlight), role-aware:@deco/uiButton.SubscribeCta— standalone component, the single seam for the billing follow-up.paywalldomain, en + pt-BR mirrored (typecheck enforces completeness).Left for follow-up (dev to wire)
The Subscribe button currently shows a "coming soon" toast. Wire
SubscribeCta.onClickto:ORGANIZATION_BILLING_CHECKOUT_STARTwhen the org has no subscription (first paid seat), orORGANIZATION_SEATS_SET, members page) when the org is already subscribed (2nd+ seat).Read
ORGANIZATION_SEATS_GETto pick between the two and swap the CTA label accordingly.Testing
bun test(paywall + chat highlight): green.bun run check(typecheck, incl. i18n en/pt-BR mirror): green.bun run fmt/bun run lint: clean (no new findings in touched files).Screenshots
Owner (dark) and mobile were verified locally; the surface is a dark spotlight card with the deco-green badge, a capability list, and a white Subscribe CTA.
🤖 Generated with Claude Code
Summary by cubic
Adds a role-aware paid-seat paywall shown when the backend returns
[PAID_SEAT_REQUIRED], replacing the generic error with a clear dialog. Frontend-only (UI + i18n); checkout wiring is left to a singleSubscribeCtaseam.New Features
[PAID_SEAT_REQUIRED]and opens a paywall via global@tanstack/react-queryMutationCache.onError; chat streaming errors open it inline in the highlight stack.SubscribeCta; members get guidance. Responsive, dark surface using@deco/ui.is-paid-seat-error, a tiny external store +PaidSeatPaywallHost, and a newpaywalli18n domain (en,pt-BR) with tests.Migration
SubscribeCta.onClicktoORGANIZATION_BILLING_CHECKOUT_START(no subscription) or to the seat-add flow when already subscribed.Written for commit 6b56eef. Summary will update on new commits.