Skip to content

Commit 9c68678

Browse files
authored
feat(clerk-js): Add payment source tab to UserProfile (#5492)
1 parent 7535f38 commit 9c68678

19 files changed

Lines changed: 649 additions & 215 deletions

File tree

.changeset/spicy-taxes-kick.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@clerk/localizations': patch
3+
'@clerk/clerk-js': patch
4+
'@clerk/types': patch
5+
---
6+
7+
Add payment source section to `UserProfile`

packages/clerk-js/bundlewatch.config.json

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"files": [
3-
{ "path": "./dist/clerk.js", "maxSize": "582.6kB" },
4-
{ "path": "./dist/clerk.browser.js", "maxSize": "81kB" },
3+
{ "path": "./dist/clerk.js", "maxSize": "584.6kB" },
4+
{ "path": "./dist/clerk.browser.js", "maxSize": "81KB" },
55
{ "path": "./dist/clerk.headless*.js", "maxSize": "55KB" },
66
{ "path": "./dist/ui-common*.js", "maxSize": "96KB" },
77
{ "path": "./dist/vendors*.js", "maxSize": "30KB" },
@@ -19,9 +19,11 @@
1919
{ "path": "./dist/onetap*.js", "maxSize": "1KB" },
2020
{ "path": "./dist/waitlist*.js", "maxSize": "1.3KB" },
2121
{ "path": "./dist/keylessPrompt*.js", "maxSize": "5.9KB" },
22-
{ "path": "./dist/pricingTable*.js", "maxSize": "5.5KB" },
23-
{ "path": "./dist/checkout*.js", "maxSize": "9KB" },
22+
{ "path": "./dist/pricingTable*.js", "maxSize": "5KB" },
23+
{ "path": "./dist/checkout*.js", "maxSize": "3KB" },
24+
{ "path": "./dist/paymentSources*.js", "maxSize": "8KB" },
2425
{ "path": "./dist/up-billing-page*.js", "maxSize": "1KB" },
26+
{ "path": "./dist/op-billing-page*.js", "maxSize": "1KB" },
2527
{ "path": "./dist/sessionTasks*.js", "maxSize": "1KB" }
2628
]
2729
}

packages/clerk-js/rspack.config.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,12 @@ const common = ({ mode, disableRHC = false }) => {
9393
name: 'signup',
9494
test: module => module.resource && module.resource.includes('/ui/components/SignUp'),
9595
},
96-
checkout: {
96+
paymentSources: {
9797
minChunks: 1,
98-
name: 'checkout',
98+
name: 'paymentSources',
9999
test: module =>
100100
module.resource &&
101-
(module.resource.includes('/ui/components/Checkout') ||
101+
(module.resource.includes('/ui/components/PaymentSources') ||
102102
// Include `@stripe/react-stripe-js` and `@stripe/stripe-js` in the checkout chunk
103103
module.resource.includes('/node_modules/@stripe')),
104104
},

packages/clerk-js/src/core/modules/commerce/Commerce.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
import type {
22
__experimental_AddPaymentSourceParams,
33
__experimental_CommerceBillingNamespace,
4+
__experimental_CommerceInitializedPaymentSourceJSON,
45
__experimental_CommerceNamespace,
56
__experimental_CommercePaymentSourceJSON,
7+
__experimental_GetPaymentSourcesParams,
8+
__experimental_InitializePaymentSourceParams,
69
ClerkPaginatedResponse,
710
} from '@clerk/types';
811

9-
import { __experimental_CommercePaymentSource, BaseResource } from '../../resources/internal';
12+
import {
13+
__experimental_CommerceInitializedPaymentSource,
14+
__experimental_CommercePaymentSource,
15+
BaseResource,
16+
} from '../../resources/internal';
1017
import { __experimental_CommerceBilling } from './CommerceBilling';
1118

1219
export class __experimental_Commerce implements __experimental_CommerceNamespace {
@@ -19,6 +26,17 @@ export class __experimental_Commerce implements __experimental_CommerceNamespace
1926
return __experimental_Commerce._billing;
2027
}
2128

29+
initializePaymentSource = async (params: __experimental_InitializePaymentSourceParams) => {
30+
const json = (
31+
await BaseResource._fetch({
32+
path: `/me/commerce/payment_sources/initialize`,
33+
method: 'POST',
34+
body: params as any,
35+
})
36+
)?.response as unknown as __experimental_CommerceInitializedPaymentSourceJSON;
37+
return new __experimental_CommerceInitializedPaymentSource(json);
38+
};
39+
2240
addPaymentSource = async (params: __experimental_AddPaymentSourceParams) => {
2341
const json = (
2442
await BaseResource._fetch({
@@ -30,10 +48,11 @@ export class __experimental_Commerce implements __experimental_CommerceNamespace
3048
return new __experimental_CommercePaymentSource(json);
3149
};
3250

33-
getPaymentSources = async () => {
51+
getPaymentSources = async (params: __experimental_GetPaymentSourcesParams) => {
3452
return await BaseResource._fetch({
3553
path: `/me/commerce/payment_sources`,
3654
method: 'GET',
55+
search: { orgId: params.orgId || '' },
3756
}).then(res => {
3857
const { data: paymentSources, total_count } =
3958
res as unknown as ClerkPaginatedResponse<__experimental_CommercePaymentSourceJSON>;

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

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import type {
2+
__experimental_CommerceInitializedPaymentSourceJSON,
3+
__experimental_CommerceInitializedPaymentSourceResource,
24
__experimental_CommercePaymentSourceJSON,
35
__experimental_CommercePaymentSourceResource,
6+
__experimental_CommercePaymentSourceStatus,
7+
DeletedObjectJSON,
48
} from '@clerk/types';
59

6-
import { BaseResource } from './internal';
10+
import { BaseResource, DeletedObject } from './internal';
711

812
export class __experimental_CommercePaymentSource
913
extends BaseResource
@@ -13,6 +17,8 @@ export class __experimental_CommercePaymentSource
1317
last4!: string;
1418
paymentMethod!: string;
1519
cardType!: string;
20+
isDefault!: boolean;
21+
status!: __experimental_CommercePaymentSourceStatus;
1622

1723
constructor(data: __experimental_CommercePaymentSourceJSON) {
1824
super();
@@ -28,6 +34,42 @@ export class __experimental_CommercePaymentSource
2834
this.last4 = data.last4;
2935
this.paymentMethod = data.payment_method;
3036
this.cardType = data.card_type;
37+
this.isDefault = false;
38+
this.status = data.status;
39+
return this;
40+
}
41+
42+
public async remove() {
43+
const json = (
44+
await BaseResource._fetch({
45+
path: `/me/commerce/payment_sources/${this.id}`,
46+
method: 'DELETE',
47+
})
48+
)?.response as unknown as DeletedObjectJSON;
49+
50+
return new DeletedObject(json);
51+
}
52+
}
53+
54+
export class __experimental_CommerceInitializedPaymentSource
55+
extends BaseResource
56+
implements __experimental_CommerceInitializedPaymentSourceResource
57+
{
58+
externalClientSecret!: string;
59+
externalGatewayId!: string;
60+
61+
constructor(data: __experimental_CommerceInitializedPaymentSourceJSON) {
62+
super();
63+
this.fromJSON(data);
64+
}
65+
66+
protected fromJSON(data: __experimental_CommerceInitializedPaymentSourceJSON | null): this {
67+
if (!data) {
68+
return this;
69+
}
70+
71+
this.externalClientSecret = data.external_client_secret;
72+
this.externalGatewayId = data.external_gateway_id;
3173

3274
return this;
3375
}

packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { Box, Button, descriptors, Heading, Icon, localizationKeys, Span, Text }
55
import { Drawer, LineItems } from '../../elements';
66
import { Check } from '../../icons';
77

8+
const capitalize = (name: string) => name[0].toUpperCase() + name.slice(1);
9+
810
export const CheckoutComplete = ({ checkout }: { checkout: __experimental_CommerceCheckoutResource }) => {
911
const { setIsOpen } = useCheckoutContext();
1012

@@ -77,6 +79,7 @@ export const CheckoutComplete = ({ checkout }: { checkout: __experimental_Commer
7779
as='h2'
7880
textVariant='h2'
7981
>
82+
{/* TODO(@COMMERCE): needs localization */}
8083
Payment was successful!
8184
</Heading>
8285
<Text
@@ -113,7 +116,9 @@ export const CheckoutComplete = ({ checkout }: { checkout: __experimental_Commer
113116
<LineItems.Title title='Payment method' />
114117
<LineItems.Description
115118
text={
116-
checkout.paymentSource ? `${checkout.paymentSource.cardType}${checkout.paymentSource.last4}` : '–'
119+
checkout.paymentSource
120+
? `${capitalize(checkout.paymentSource.cardType)}${checkout.paymentSource.last4}`
121+
: '–'
117122
}
118123
/>
119124
</LineItems.Group>

0 commit comments

Comments
 (0)