Skip to content

Commit 92c44dd

Browse files
authored
feat(clerk-js,types): Update logic for showing Billing nav within profiles (#6315)
1 parent fecc99d commit 92c44dd

File tree

9 files changed

+102
-44
lines changed

9 files changed

+102
-44
lines changed

.changeset/public-bags-stay.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@clerk/clerk-js': patch
3+
'@clerk/types': patch
4+
---
5+
6+
Adjust the cases in which the Billing item shows within the `UserProfile` and `OrgProfile` components

packages/clerk-js/src/core/clerk.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ import {
9494
createAllowedRedirectOrigins,
9595
createBeforeUnloadTracker,
9696
createPageLifecycle,
97+
disabledAllBillingFeatures,
9798
disabledAPIKeysFeature,
98-
disabledBillingFeature,
9999
disabledOrganizationsFeature,
100100
errorThrower,
101101
generateSignatureWithCoinbaseWallet,
@@ -576,7 +576,7 @@ export class Clerk implements ClerkInterface {
576576

577577
public __internal_openCheckout = (props?: __internal_CheckoutProps): void => {
578578
this.assertComponentsReady(this.#componentControls);
579-
if (disabledBillingFeature(this, this.environment)) {
579+
if (disabledAllBillingFeatures(this, this.environment)) {
580580
if (this.#instanceType === 'development') {
581581
throw new ClerkRuntimeError(warnings.cannotRenderAnyCommerceComponent('Checkout'), {
582582
code: CANNOT_RENDER_BILLING_DISABLED_ERROR_CODE,
@@ -605,7 +605,7 @@ export class Clerk implements ClerkInterface {
605605

606606
public __internal_openPlanDetails = (props: __internal_PlanDetailsProps): void => {
607607
this.assertComponentsReady(this.#componentControls);
608-
if (disabledBillingFeature(this, this.environment)) {
608+
if (disabledAllBillingFeatures(this, this.environment)) {
609609
if (this.#instanceType === 'development') {
610610
throw new ClerkRuntimeError(warnings.cannotRenderAnyCommerceComponent('PlanDetails'), {
611611
code: CANNOT_RENDER_BILLING_DISABLED_ERROR_CODE,
@@ -1060,7 +1060,7 @@ export class Clerk implements ClerkInterface {
10601060

10611061
public mountPricingTable = (node: HTMLDivElement, props?: PricingTableProps): void => {
10621062
this.assertComponentsReady(this.#componentControls);
1063-
if (disabledBillingFeature(this, this.environment)) {
1063+
if (disabledAllBillingFeatures(this, this.environment)) {
10641064
if (this.#instanceType === 'development') {
10651065
throw new ClerkRuntimeError(warnings.cannotRenderAnyCommerceComponent('PricingTable'), {
10661066
code: CANNOT_RENDER_BILLING_DISABLED_ERROR_CODE,

packages/clerk-js/src/core/resources/CommerceSettings.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ export class CommerceSettings extends BaseResource implements CommerceSettingsRe
1111
enabled: false,
1212
hasPaidUserPlans: false,
1313
hasPaidOrgPlans: false,
14+
organization: {
15+
enabled: false,
16+
hasPaidPlans: false,
17+
},
18+
user: {
19+
enabled: false,
20+
hasPaidPlans: false,
21+
},
1422
};
1523

1624
public constructor(data: CommerceSettingsJSON | CommerceSettingsJSONSnapshot | null = null) {
@@ -27,6 +35,10 @@ export class CommerceSettings extends BaseResource implements CommerceSettingsRe
2735
this.billing.enabled = data.billing.enabled || false;
2836
this.billing.hasPaidUserPlans = data.billing.has_paid_user_plans || false;
2937
this.billing.hasPaidOrgPlans = data.billing.has_paid_org_plans || false;
38+
this.billing.organization.enabled = data.billing.organization.enabled || false;
39+
this.billing.organization.hasPaidPlans = data.billing.organization.has_paid_plans || false;
40+
this.billing.user.enabled = data.billing.user.enabled || false;
41+
this.billing.user.hasPaidPlans = data.billing.user.has_paid_plans || false;
3042

3143
return this;
3244
}
@@ -38,6 +50,14 @@ export class CommerceSettings extends BaseResource implements CommerceSettingsRe
3850
enabled: this.billing.enabled,
3951
has_paid_user_plans: this.billing.hasPaidUserPlans,
4052
has_paid_org_plans: this.billing.hasPaidOrgPlans,
53+
organization: {
54+
enabled: this.billing.organization.enabled,
55+
has_paid_plans: this.billing.organization.hasPaidPlans,
56+
},
57+
user: {
58+
enabled: this.billing.user.enabled,
59+
has_paid_plans: this.billing.user.hasPaidPlans,
60+
},
4161
},
4262
} as unknown as CommerceSettingsJSONSnapshot;
4363
}

packages/clerk-js/src/ui/components/OrganizationProfile/OrganizationProfileRoutes.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export const OrganizationProfileRoutes = () => {
8383
</Route>
8484
</Switch>
8585
</Route>
86-
{commerceSettings.billing.enabled && commerceSettings.billing.hasPaidOrgPlans && (
86+
{commerceSettings.billing.organization.enabled ? (
8787
<Protect
8888
condition={has =>
8989
has({ permission: 'org:sys_billing:read' }) || has({ permission: 'org:sys_billing:manage' })
@@ -96,11 +96,13 @@ export const OrganizationProfileRoutes = () => {
9696
<OrganizationBillingPage />
9797
</Suspense>
9898
</Route>
99-
<Route path='plans'>
100-
<Suspense fallback={''}>
101-
<OrganizationPlansPage />
102-
</Suspense>
103-
</Route>
99+
{commerceSettings.billing.organization.hasPaidPlans ? (
100+
<Route path='plans'>
101+
<Suspense fallback={''}>
102+
<OrganizationPlansPage />
103+
</Suspense>
104+
</Route>
105+
) : null}
104106
<Route path='statement/:statementId'>
105107
<Suspense fallback={''}>
106108
<OrganizationStatementPage />
@@ -114,7 +116,7 @@ export const OrganizationProfileRoutes = () => {
114116
</Switch>
115117
</Route>
116118
</Protect>
117-
)}
119+
) : null}
118120
{apiKeysSettings.enabled && (
119121
<Protect
120122
condition={has =>

packages/clerk-js/src/ui/components/Subscriptions/SubscriptionsList.tsx

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { ProfileSection } from '@/ui/elements/Section';
22

33
import { useProtect } from '../../common';
44
import {
5+
useEnvironment,
56
usePlansContext,
67
useSubscriberTypeContext,
78
useSubscriberTypeLocalizationRoot,
@@ -44,6 +45,7 @@ export function SubscriptionsList({
4445
has => has({ permission: 'org:sys_billing:manage' }) || subscriberType === 'user',
4546
);
4647
const { navigate } = useRouter();
48+
const { commerceSettings } = useEnvironment();
4749

4850
const sortedSubscriptions = subscriptions.sort((a, b) => {
4951
// alway put active subscriptions first
@@ -188,22 +190,25 @@ export function SubscriptionsList({
188190
</Table>
189191
)}
190192

191-
<ProfileSection.ArrowButton
192-
id='subscriptionsList'
193-
textLocalizationKey={subscriptions.length > 0 ? arrowButtonText : arrowButtonEmptyText}
194-
sx={[
195-
t => ({
196-
justifyContent: 'start',
197-
height: t.sizes.$8,
198-
}),
199-
]}
200-
leftIcon={subscriptions.length > 0 ? ArrowsUpDown : Plus}
201-
leftIconSx={t => ({
202-
width: t.sizes.$4,
203-
height: t.sizes.$4,
204-
})}
205-
onClick={() => void navigate('plans')}
206-
/>
193+
{(commerceSettings.billing.user.hasPaidPlans && subscriberType === 'user') ||
194+
(commerceSettings.billing.organization.hasPaidPlans && subscriberType === 'org') ? (
195+
<ProfileSection.ArrowButton
196+
id='subscriptionsList'
197+
textLocalizationKey={subscriptions.length > 0 ? arrowButtonText : arrowButtonEmptyText}
198+
sx={[
199+
t => ({
200+
justifyContent: 'start',
201+
height: t.sizes.$8,
202+
}),
203+
]}
204+
leftIcon={subscriptions.length > 0 ? ArrowsUpDown : Plus}
205+
leftIconSx={t => ({
206+
width: t.sizes.$4,
207+
height: t.sizes.$4,
208+
})}
209+
onClick={() => void navigate('plans')}
210+
/>
211+
) : null}
207212
</ProfileSection.Root>
208213
);
209214
}

packages/clerk-js/src/ui/components/UserProfile/UserProfileRoutes.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,19 +80,21 @@ export const UserProfileRoutes = () => {
8080
</Route>
8181
</Switch>
8282
</Route>
83-
{commerceSettings.billing.enabled && commerceSettings.billing.hasPaidUserPlans && (
83+
{commerceSettings.billing.user.enabled ? (
8484
<Route path={isBillingPageRoot ? undefined : 'billing'}>
8585
<Switch>
8686
<Route index>
8787
<Suspense fallback={''}>
8888
<BillingPage />
8989
</Suspense>
9090
</Route>
91-
<Route path='plans'>
92-
<Suspense fallback={''}>
93-
<PlansPage />
94-
</Suspense>
95-
</Route>
91+
{commerceSettings.billing.user.hasPaidPlans ? (
92+
<Route path='plans'>
93+
<Suspense fallback={''}>
94+
<PlansPage />
95+
</Suspense>
96+
</Route>
97+
) : null}
9698
<Route path='statement/:statementId'>
9799
<Suspense fallback={''}>
98100
<StatementPage />
@@ -105,7 +107,7 @@ export const UserProfileRoutes = () => {
105107
</Route>
106108
</Switch>
107109
</Route>
108-
)}
110+
) : null}
109111
{apiKeysSettings.enabled && (
110112
<Route path={isAPIKeysPageRoot ? undefined : 'api-keys'}>
111113
<Switch>

packages/clerk-js/src/ui/utils/createCustomPages.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@ import type { CustomPage, EnvironmentResource, LoadedClerk } from '@clerk/types'
33
import {
44
canViewOrManageAPIKeys,
55
disabledAPIKeysFeature,
6-
disabledBillingFeature,
7-
hasPaidOrgPlans,
8-
hasPaidUserPlans,
6+
disabledOrganizationBillingFeature,
7+
disabledUserBillingFeature,
98
isValidUrl,
109
} from '../../utils';
1110
import { ORGANIZATION_PROFILE_NAVBAR_ROUTE_ID, USER_PROFILE_NAVBAR_ROUTE_ID } from '../constants';
@@ -97,9 +96,9 @@ const createCustomPages = (
9796
organization?: boolean,
9897
) => {
9998
const { INITIAL_ROUTES, pageToRootNavbarRouteMap, validReorderItemLabels } = getDefaultRoutes({
100-
commerce:
101-
!disabledBillingFeature(clerk, environment) &&
102-
(organization ? hasPaidOrgPlans(clerk, environment) : hasPaidUserPlans(clerk, environment)),
99+
commerce: organization
100+
? !disabledOrganizationBillingFeature(clerk, environment)
101+
: !disabledUserBillingFeature(clerk, environment),
103102
apiKeys: !disabledAPIKeysFeature(clerk, environment) && (organization ? canViewOrManageAPIKeys(clerk) : true),
104103
});
105104

packages/clerk-js/src/utils/componentGuards.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,24 @@ export const disabledOrganizationsFeature: ComponentGuard = (_, environment) =>
2222
return !environment?.organizationSettings.enabled;
2323
};
2424

25-
export const disabledBillingFeature: ComponentGuard = (_, environment) => {
26-
return !environment?.commerceSettings.billing.enabled;
25+
export const disabledUserBillingFeature: ComponentGuard = (_, environment) => {
26+
return !environment?.commerceSettings.billing.user.enabled;
27+
};
28+
29+
export const disabledOrganizationBillingFeature: ComponentGuard = (_, environment) => {
30+
return !environment?.commerceSettings.billing.organization.enabled;
31+
};
32+
33+
export const disabledAllBillingFeatures: ComponentGuard = (_, environment) => {
34+
return disabledUserBillingFeature(_, environment) && disabledOrganizationBillingFeature(_, environment);
2735
};
2836

2937
export const hasPaidOrgPlans: ComponentGuard = (_, environment) => {
30-
return environment?.commerceSettings.billing.hasPaidOrgPlans || false;
38+
return environment?.commerceSettings.billing.organization.hasPaidPlans || false;
3139
};
3240

3341
export const hasPaidUserPlans: ComponentGuard = (_, environment) => {
34-
return environment?.commerceSettings.billing.hasPaidUserPlans || false;
42+
return environment?.commerceSettings.billing.user.hasPaidPlans || false;
3543
};
3644

3745
export const disabledAPIKeysFeature: ComponentGuard = (_, environment) => {

packages/types/src/commerceSettings.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ export interface CommerceSettingsJSON extends ClerkResourceJSON {
99
stripe_publishable_key: string;
1010
has_paid_user_plans: boolean;
1111
has_paid_org_plans: boolean;
12+
organization: {
13+
enabled: boolean;
14+
has_paid_plans: boolean;
15+
};
16+
user: {
17+
enabled: boolean;
18+
has_paid_plans: boolean;
19+
};
1220
};
1321
}
1422

@@ -18,6 +26,14 @@ export interface CommerceSettingsResource extends ClerkResource {
1826
stripePublishableKey: string;
1927
hasPaidUserPlans: boolean;
2028
hasPaidOrgPlans: boolean;
29+
organization: {
30+
enabled: boolean;
31+
hasPaidPlans: boolean;
32+
};
33+
user: {
34+
enabled: boolean;
35+
hasPaidPlans: boolean;
36+
};
2137
};
2238

2339
__internal_toSnapshot: () => CommerceSettingsJSONSnapshot;

0 commit comments

Comments
 (0)