@growth-operations/ui-shared 1.6.3 → 1.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/billing/BillingTab.jsx +32 -0
- package/src/billing/PlanGrid.jsx +27 -9
package/package.json
CHANGED
|
@@ -180,6 +180,22 @@ function TrialSubscriptionBilling({ context, state, appKey }) {
|
|
|
180
180
|
`&return_url=${encodeURIComponent(returnUrl)}`
|
|
181
181
|
: null;
|
|
182
182
|
|
|
183
|
+
// Upgrade-only tier picker — shown ONLY while trialing (the lifecycle: trial
|
|
184
|
+
// starts on the entry tier at install; while trialing the customer may upgrade
|
|
185
|
+
// to a higher tier; once active, plan changes go through support, so no picker).
|
|
186
|
+
// The cards target /v1/billing/upgrade/start (swap the trialing sub's item, no
|
|
187
|
+
// new sub). "Higher tiers" = plans ranked above the current tier by tier_order;
|
|
188
|
+
// the backend stamps Plan.current on the account's tier.
|
|
189
|
+
const isTrialing = ent.status === "trialing";
|
|
190
|
+
const plans = state?.plans ?? [];
|
|
191
|
+
const currentOrder = plans.find((p) => p.current)?.tier_order;
|
|
192
|
+
const upgradePlans =
|
|
193
|
+
isTrialing && currentOrder != null
|
|
194
|
+
? plans.filter(
|
|
195
|
+
(p) => !p.talk_to_sales && p.tier_order != null && p.tier_order > currentOrder
|
|
196
|
+
)
|
|
197
|
+
: [];
|
|
198
|
+
|
|
183
199
|
return (
|
|
184
200
|
<Flex direction="column" gap="medium">
|
|
185
201
|
{/* PRIMARY CTA at the top. Direct external link to the billing-service
|
|
@@ -198,6 +214,22 @@ function TrialSubscriptionBilling({ context, state, appKey }) {
|
|
|
198
214
|
Billing is managed in Stripe across all Growth Operations apps. Use the
|
|
199
215
|
link above to update your plan, payment method, or view invoices.
|
|
200
216
|
</Text>
|
|
217
|
+
|
|
218
|
+
{/* Trial-only upgrade path. Hidden once active (no plans pass the filter
|
|
219
|
+
when not trialing). Upgrading swaps the trialing sub onto the higher
|
|
220
|
+
tier, keeping the trial end date. */}
|
|
221
|
+
{upgradePlans.length > 0 && (
|
|
222
|
+
<PlanGrid
|
|
223
|
+
context={context}
|
|
224
|
+
state={state}
|
|
225
|
+
appKey={appKey}
|
|
226
|
+
plans={upgradePlans}
|
|
227
|
+
endpoint="upgrade/start"
|
|
228
|
+
ctaLabel="Upgrade to"
|
|
229
|
+
heading="Upgrade your plan"
|
|
230
|
+
footnote="Upgrade any time during your trial — your trial end date stays the same, and the new tier applies when it converts."
|
|
231
|
+
/>
|
|
232
|
+
)}
|
|
201
233
|
</Flex>
|
|
202
234
|
);
|
|
203
235
|
}
|
package/src/billing/PlanGrid.jsx
CHANGED
|
@@ -48,6 +48,12 @@ function PlanCard({
|
|
|
48
48
|
returnUrl,
|
|
49
49
|
supportUrl,
|
|
50
50
|
maxFeatures = 0,
|
|
51
|
+
// Billing-service redirect the "Choose" button targets. "checkout/start" (the
|
|
52
|
+
// default) starts a NEW subscription via hosted Checkout — for free/credit
|
|
53
|
+
// first purchase. "upgrade/start" swaps the EXISTING trialing/active sub's item
|
|
54
|
+
// to this tier (the trial-archetype in-app upgrade) — no new sub.
|
|
55
|
+
endpoint = "checkout/start",
|
|
56
|
+
ctaLabel = "Choose",
|
|
51
57
|
}) {
|
|
52
58
|
// Default this card to annual when it offers annual (cheaper-per-month story);
|
|
53
59
|
// monthly-only tiers default to monthly. Both legs → show the toggle.
|
|
@@ -80,7 +86,7 @@ function PlanCard({
|
|
|
80
86
|
// price) — the button is disabled until then.
|
|
81
87
|
const startUrl =
|
|
82
88
|
billingBaseUrl && appKey && portalId && leg?.price_id
|
|
83
|
-
? `${billingBaseUrl}/v1/billing
|
|
89
|
+
? `${billingBaseUrl}/v1/billing/${endpoint}` +
|
|
84
90
|
`?app_key=${encodeURIComponent(appKey)}` +
|
|
85
91
|
`&portal_id=${encodeURIComponent(portalId)}` +
|
|
86
92
|
`&price_id=${encodeURIComponent(leg.price_id)}` +
|
|
@@ -175,7 +181,7 @@ function PlanCard({
|
|
|
175
181
|
disabled={!startUrl}
|
|
176
182
|
variant="primary"
|
|
177
183
|
>
|
|
178
|
-
|
|
184
|
+
{ctaLabel} {plan.name ?? plan.tier}
|
|
179
185
|
</Button>
|
|
180
186
|
)}
|
|
181
187
|
</Flex>
|
|
@@ -183,8 +189,21 @@ function PlanCard({
|
|
|
183
189
|
);
|
|
184
190
|
}
|
|
185
191
|
|
|
186
|
-
export function PlanGrid({
|
|
187
|
-
|
|
192
|
+
export function PlanGrid({
|
|
193
|
+
context,
|
|
194
|
+
state,
|
|
195
|
+
appKey,
|
|
196
|
+
// Customization for non-default uses. The credit-app first-purchase grid uses
|
|
197
|
+
// all defaults; the trial-archetype in-app UPGRADE picker passes:
|
|
198
|
+
// plans={higherTiersOnly} endpoint="upgrade/start" ctaLabel="Upgrade to"
|
|
199
|
+
// heading="Upgrade your plan" footnote={trial copy}
|
|
200
|
+
plans: plansOverride,
|
|
201
|
+
endpoint = "checkout/start",
|
|
202
|
+
ctaLabel = "Choose",
|
|
203
|
+
heading = "Plans",
|
|
204
|
+
footnote = "Billing is managed in Stripe across all Growth Operations apps. Your new credits are added as soon as payment completes.",
|
|
205
|
+
}) {
|
|
206
|
+
const plans = plansOverride ?? state?.plans ?? [];
|
|
188
207
|
|
|
189
208
|
if (plans.length === 0) return null;
|
|
190
209
|
|
|
@@ -205,7 +224,7 @@ export function PlanGrid({ context, state, appKey }) {
|
|
|
205
224
|
|
|
206
225
|
return (
|
|
207
226
|
<Flex direction="column" gap="medium">
|
|
208
|
-
<Heading>
|
|
227
|
+
<Heading>{heading}</Heading>
|
|
209
228
|
|
|
210
229
|
{/* AutoGrid(flexible): equal-width columns that wrap responsively. Card
|
|
211
230
|
height is equalized via the maxFeatures padding in PlanCard. Each card
|
|
@@ -221,14 +240,13 @@ export function PlanGrid({ context, state, appKey }) {
|
|
|
221
240
|
returnUrl={returnUrl}
|
|
222
241
|
supportUrl={supportUrl}
|
|
223
242
|
maxFeatures={maxFeatures}
|
|
243
|
+
endpoint={endpoint}
|
|
244
|
+
ctaLabel={ctaLabel}
|
|
224
245
|
/>
|
|
225
246
|
))}
|
|
226
247
|
</AutoGrid>
|
|
227
248
|
|
|
228
|
-
<Text format={{ fontStyle: "italic" }}>
|
|
229
|
-
Billing is managed in Stripe across all Growth Operations apps. Your new
|
|
230
|
-
credits are added as soon as payment completes.
|
|
231
|
-
</Text>
|
|
249
|
+
<Text format={{ fontStyle: "italic" }}>{footnote}</Text>
|
|
232
250
|
</Flex>
|
|
233
251
|
);
|
|
234
252
|
}
|