Skip to content

Commit af0e123

Browse files
authored
chore(clerk-js,types,localizations): Refactor statement page and payment attempt page (#6420)
1 parent a34bad4 commit af0e123

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+211
-63
lines changed

.changeset/slow-foxes-lay.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+
Refactor billing statement page and payment attempt page data loading

packages/clerk-js/bundlewatch.config.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
{ "path": "./dist/clerk.js", "maxSize": "618KB" },
44
{ "path": "./dist/clerk.browser.js", "maxSize": "74KB" },
55
{ "path": "./dist/clerk.legacy.browser.js", "maxSize": "115.08KB" },
6-
{ "path": "./dist/clerk.headless*.js", "maxSize": "55KB" },
6+
{ "path": "./dist/clerk.headless*.js", "maxSize": "55.2KB" },
77
{ "path": "./dist/ui-common*.js", "maxSize": "113KB" },
88
{ "path": "./dist/ui-common*.legacy.*.js", "maxSize": "118KB" },
99
{ "path": "./dist/vendors*.js", "maxSize": "40.2KB" },
@@ -23,7 +23,7 @@
2323
{ "path": "./dist/waitlist*.js", "maxSize": "1.5KB" },
2424
{ "path": "./dist/keylessPrompt*.js", "maxSize": "6.5KB" },
2525
{ "path": "./dist/pricingTable*.js", "maxSize": "4.02KB" },
26-
{ "path": "./dist/checkout*.js", "maxSize": "8.45KB" },
26+
{ "path": "./dist/checkout*.js", "maxSize": "8.5KB" },
2727
{ "path": "./dist/up-billing-page*.js", "maxSize": "3.0KB" },
2828
{ "path": "./dist/op-billing-page*.js", "maxSize": "3.0KB" },
2929
{ "path": "./dist/up-plans-page*.js", "maxSize": "1.0KB" },

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,18 @@ export class CommerceBilling implements CommerceBillingNamespace {
103103
});
104104
};
105105

106+
getStatement = async (params: { id: string; orgId?: string }): Promise<CommerceStatementResource> => {
107+
const statement = (
108+
await BaseResource._fetch({
109+
path: params.orgId
110+
? `/organizations/${params.orgId}/commerce/statements/${params.id}`
111+
: `/me/commerce/statements/${params.id}`,
112+
method: 'GET',
113+
})
114+
)?.response as unknown as CommerceStatementJSON;
115+
return new CommerceStatement(statement);
116+
};
117+
106118
getPaymentAttempts = async (
107119
params: GetPaymentAttemptsParams,
108120
): Promise<ClerkPaginatedResponse<CommercePaymentResource>> => {
@@ -122,6 +134,16 @@ export class CommerceBilling implements CommerceBillingNamespace {
122134
});
123135
};
124136

137+
getPaymentAttempt = async (params: { id: string; orgId?: string }): Promise<CommercePaymentResource> => {
138+
const paymentAttempt = (await BaseResource._fetch({
139+
path: params.orgId
140+
? `/organizations/${params.orgId}/commerce/payment_attempts/${params.id}`
141+
: `/me/commerce/payment_attempts/${params.id}`,
142+
method: 'GET',
143+
})) as unknown as CommercePaymentJSON;
144+
return new CommercePayment(paymentAttempt);
145+
};
146+
125147
startCheckout = async (params: CreateCheckoutParams) => {
126148
const { orgId, ...rest } = params;
127149
const json = (

packages/clerk-js/src/ui/components/PaymentAttempts/PaymentAttemptPage.tsx

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
import { useClerk, useOrganization } from '@clerk/shared/react';
2+
import useSWR from 'swr';
3+
4+
import { Alert } from '@/ui/elements/Alert';
15
import { Header } from '@/ui/elements/Header';
26
import { LineItems } from '@/ui/elements/LineItems';
37
import { formatDate } from '@/ui/utils/formatDate';
48
import { truncateWithEndVisible } from '@/ui/utils/truncateTextWithEndVisible';
59

6-
import { usePaymentAttemptsContext, useStatements } from '../../contexts';
7-
import { useSubscriberTypeLocalizationRoot } from '../../contexts/components';
10+
import { useSubscriberTypeContext, useSubscriberTypeLocalizationRoot } from '../../contexts/components';
811
import {
912
Badge,
1013
Box,
@@ -16,18 +19,39 @@ import {
1619
Span,
1720
Spinner,
1821
Text,
22+
useLocalizations,
1923
} from '../../customizables';
2024
import { useClipboard } from '../../hooks';
2125
import { Check, Copy } from '../../icons';
2226
import { useRouter } from '../../router';
2327

2428
export const PaymentAttemptPage = () => {
2529
const { params, navigate } = useRouter();
26-
const { isLoading } = useStatements();
27-
const { getPaymentAttemptById } = usePaymentAttemptsContext();
30+
const subscriberType = useSubscriberTypeContext();
31+
const { organization } = useOrganization();
2832
const localizationRoot = useSubscriberTypeLocalizationRoot();
33+
const { t, translateError } = useLocalizations();
34+
const clerk = useClerk();
35+
36+
const {
37+
data: paymentAttempt,
38+
isLoading,
39+
error,
40+
} = useSWR(
41+
params.paymentAttemptId
42+
? {
43+
type: 'payment-attempt',
44+
id: params.paymentAttemptId,
45+
orgId: subscriberType === 'organization' ? organization?.id : undefined,
46+
}
47+
: null,
48+
() =>
49+
clerk.billing.getPaymentAttempt({
50+
id: params.paymentAttemptId,
51+
orgId: subscriberType === 'organization' ? organization?.id : undefined,
52+
}),
53+
);
2954

30-
const paymentAttempt = params.paymentAttemptId ? getPaymentAttemptById(params.paymentAttemptId) : null;
3155
const subscriptionItem = paymentAttempt?.subscriptionItem;
3256

3357
if (isLoading) {
@@ -61,10 +85,15 @@ export const PaymentAttemptPage = () => {
6185
</Header.BackLink>
6286
</Header.Root>
6387
{!paymentAttempt ? (
64-
<Text
65-
localizationKey={localizationKeys(`${localizationRoot}.billingPage.paymentHistorySection.notFound`)}
66-
sx={{ textAlign: 'center' }}
67-
/>
88+
<Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>
89+
<Alert
90+
variant='danger'
91+
colorScheme='danger'
92+
>
93+
{translateError(error.errors[0]) ||
94+
t(localizationKeys(`${localizationRoot}.billingPage.paymentHistorySection.notFound`))}
95+
</Alert>
96+
</Box>
6897
) : (
6998
<Box
7099
elementDescriptor={descriptors.paymentAttemptRoot}

packages/clerk-js/src/ui/components/Statements/Statement.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import React from 'react';
2+
13
import type { LocalizationKey } from '../../customizables';
24
import { Badge, Box, Button, descriptors, Heading, Icon, Span, Text } from '../../customizables';
35
import { useClipboard } from '../../hooks';
@@ -279,7 +281,7 @@ function SectionContentDetailsListItem({
279281
icon?: React.ReactNode;
280282
label: string | LocalizationKey;
281283
labelIcon?: React.ComponentType;
282-
value: string | LocalizationKey;
284+
value: string | LocalizationKey | React.ReactElement;
283285
valueTruncated?: boolean;
284286
valueCopyable?: boolean;
285287
}) {
@@ -348,12 +350,14 @@ function SectionContentDetailsListItem({
348350
{valueTruncated ? truncateWithEndVisible(value) : value}
349351
</Text>
350352
</>
353+
) : React.isValidElement(value) ? (
354+
value
351355
) : (
352356
<Text
353357
elementDescriptor={descriptors.statementSectionContentDetailsListItemValue}
354358
colorScheme='secondary'
355359
variant='caption'
356-
localizationKey={value}
360+
localizationKey={value as LocalizationKey}
357361
/>
358362
)}
359363
</Span>

packages/clerk-js/src/ui/components/Statements/StatementPage.tsx

Lines changed: 66 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,51 @@
1+
import { useClerk, useOrganization } from '@clerk/shared/react';
2+
import useSWR from 'swr';
3+
4+
import { Alert } from '@/ui/elements/Alert';
15
import { Header } from '@/ui/elements/Header';
26
import { formatDate } from '@/ui/utils/formatDate';
37

4-
import { useStatements, useStatementsContext, useSubscriberTypeLocalizationRoot } from '../../contexts';
5-
import { Box, descriptors, localizationKeys, Spinner, Text, useLocalizations } from '../../customizables';
6-
import { Plus, RotateLeftRight } from '../../icons';
8+
import { useSubscriberTypeContext, useSubscriberTypeLocalizationRoot } from '../../contexts/components';
9+
import {
10+
Box,
11+
descriptors,
12+
Icon,
13+
localizationKeys,
14+
SimpleButton,
15+
Span,
16+
Spinner,
17+
useLocalizations,
18+
} from '../../customizables';
19+
import { ArrowRightIcon, Plus, RotateLeftRight } from '../../icons';
720
import { useRouter } from '../../router';
821
import { Statement } from './Statement';
922

1023
export const StatementPage = () => {
1124
const { params, navigate } = useRouter();
12-
const { isLoading } = useStatements();
13-
const { getStatementById } = useStatementsContext();
25+
const subscriberType = useSubscriberTypeContext();
26+
const { organization } = useOrganization();
1427
const localizationRoot = useSubscriberTypeLocalizationRoot();
15-
const { t } = useLocalizations();
16-
const statement = params.statementId ? getStatementById(params.statementId) : null;
28+
const { t, translateError } = useLocalizations();
29+
const clerk = useClerk();
30+
31+
const {
32+
data: statement,
33+
isLoading,
34+
error,
35+
} = useSWR(
36+
params.statementId
37+
? {
38+
type: 'statement',
39+
id: params.statementId,
40+
orgId: subscriberType === 'organization' ? organization?.id : undefined,
41+
}
42+
: null,
43+
() =>
44+
clerk.billing.getStatement({
45+
id: params.statementId,
46+
orgId: subscriberType === 'organization' ? organization?.id : undefined,
47+
}),
48+
);
1749

1850
if (isLoading) {
1951
return (
@@ -48,10 +80,15 @@ export const StatementPage = () => {
4880
</Header.BackLink>
4981
</Header.Root>
5082
{!statement ? (
51-
<Text
52-
localizationKey={localizationKeys(`${localizationRoot}.billingPage.statementsSection.notFound`)}
53-
sx={{ textAlign: 'center' }}
54-
/>
83+
<Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>
84+
<Alert
85+
variant='danger'
86+
colorScheme='danger'
87+
>
88+
{translateError(error.errors[0]) ||
89+
t(localizationKeys(`${localizationRoot}.billingPage.statementsSection.notFound`))}
90+
</Alert>
91+
</Box>
5592
) : (
5693
<Statement.Root>
5794
<Statement.Header
@@ -91,9 +128,24 @@ export const StatementPage = () => {
91128
)
92129
}
93130
labelIcon={item.chargeType === 'recurring' ? RotateLeftRight : Plus}
94-
value={item.id}
95-
valueTruncated
96-
valueCopyable
131+
value={
132+
<SimpleButton
133+
onClick={() => void navigate(`../../payment-attempt/${item.id}`)}
134+
variant='link'
135+
colorScheme='primary'
136+
textVariant='buttonSmall'
137+
sx={t => ({
138+
gap: t.space.$1,
139+
})}
140+
>
141+
<Span localizationKey={localizationKeys('commerce.viewPayment')} />
142+
<Icon
143+
icon={ArrowRightIcon}
144+
size='sm'
145+
aria-hidden
146+
/>
147+
</SimpleButton>
148+
}
97149
/>
98150
{item.subscriptionItem.credit && item.subscriptionItem.credit.amount.amount > 0 ? (
99151
<Statement.SectionContentDetailsListItem

packages/clerk-js/src/ui/contexts/components/PaymentAttempts.tsx

Lines changed: 0 additions & 17 deletions
This file was deleted.

packages/clerk-js/src/ui/contexts/components/Statements.tsx

Lines changed: 0 additions & 17 deletions
This file was deleted.

packages/clerk-js/src/ui/contexts/components/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ export * from './GoogleOneTap';
1313
export * from './Waitlist';
1414
export * from './PricingTable';
1515
export * from './Checkout';
16-
export * from './Statements';
17-
export * from './PaymentAttempts';
1816
export * from './Plans';
1917
export * from './ApiKeys';
2018
export * from './OAuthConsent';

packages/localizations/src/ar-SA.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ export const arSA: LocalizationResource = {
154154
totalDue: undefined,
155155
totalDueToday: undefined,
156156
viewFeatures: undefined,
157+
viewPayment: undefined,
157158
year: undefined,
158159
},
159160
createOrganization: {

0 commit comments

Comments
 (0)