@blocklet/payment-react 1.14.21 → 1.14.22
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/es/checkout/donate.d.ts +2 -1
- package/es/checkout/donate.js +9 -10
- package/es/checkout/form.d.ts +1 -1
- package/es/checkout/form.js +23 -1
- package/es/checkout/table.d.ts +1 -1
- package/es/checkout/table.js +8 -1
- package/es/components/blockchain/tx.js +2 -1
- package/es/components/country-select.d.ts +16 -0
- package/es/components/country-select.js +82 -0
- package/es/components/input.d.ts +21 -21
- package/es/components/input.js +43 -42
- package/es/components/livemode.js +1 -0
- package/es/components/pricing-table.js +0 -2
- package/es/components/status.js +2 -3
- package/es/components/table.d.ts +2 -0
- package/es/components/table.js +186 -0
- package/es/contexts/payment.d.ts +2 -0
- package/es/contexts/payment.js +5 -2
- package/es/history/invoice/list.d.ts +3 -1
- package/es/history/invoice/list.js +215 -48
- package/es/hooks/mobile.d.ts +4 -0
- package/es/hooks/mobile.js +10 -0
- package/es/index.d.ts +5 -1
- package/es/index.js +7 -1
- package/es/libs/util.d.ts +15 -2
- package/es/libs/util.js +92 -28
- package/es/locales/en.js +22 -7
- package/es/locales/index.d.ts +0 -1
- package/es/locales/index.js +10 -1
- package/es/locales/zh.js +21 -6
- package/es/payment/error.js +2 -2
- package/es/payment/footer.js +1 -1
- package/es/payment/form/address.d.ts +9 -2
- package/es/payment/form/address.js +69 -69
- package/es/payment/form/currency.js +39 -25
- package/es/payment/form/index.d.ts +1 -1
- package/es/payment/form/index.js +83 -81
- package/es/payment/form/phone.js +15 -51
- package/es/payment/index.d.ts +1 -10
- package/es/payment/index.js +274 -219
- package/es/payment/product-card.js +4 -4
- package/es/payment/product-donation.js +7 -2
- package/es/payment/product-item.d.ts +2 -2
- package/es/payment/product-item.js +120 -81
- package/es/payment/summary.js +188 -118
- package/es/theme/index.css +240 -0
- package/es/theme/index.d.ts +9 -0
- package/es/theme/index.js +243 -0
- package/es/theme/typography.d.ts +2 -0
- package/es/theme/typography.js +53 -0
- package/es/types/index.d.ts +11 -0
- package/lib/checkout/donate.d.ts +2 -1
- package/lib/checkout/donate.js +14 -2
- package/lib/checkout/form.d.ts +1 -1
- package/lib/checkout/form.js +22 -1
- package/lib/checkout/table.d.ts +1 -1
- package/lib/checkout/table.js +14 -1
- package/lib/components/blockchain/tx.js +4 -1
- package/lib/components/country-select.d.ts +16 -0
- package/lib/components/country-select.js +115 -0
- package/lib/components/input.d.ts +21 -21
- package/lib/components/input.js +21 -12
- package/lib/components/livemode.js +1 -0
- package/lib/components/pricing-table.js +0 -2
- package/lib/components/status.js +2 -3
- package/lib/components/table.d.ts +2 -0
- package/lib/components/table.js +220 -0
- package/lib/contexts/payment.d.ts +2 -0
- package/lib/contexts/payment.js +4 -1
- package/lib/history/invoice/list.d.ts +3 -1
- package/lib/history/invoice/list.js +290 -62
- package/lib/hooks/mobile.d.ts +4 -0
- package/lib/hooks/mobile.js +17 -0
- package/lib/index.d.ts +5 -1
- package/lib/index.js +36 -0
- package/lib/libs/util.d.ts +15 -2
- package/lib/libs/util.js +115 -37
- package/lib/locales/en.js +22 -7
- package/lib/locales/index.d.ts +0 -1
- package/lib/locales/index.js +14 -3
- package/lib/locales/zh.js +21 -6
- package/lib/payment/error.js +5 -1
- package/lib/payment/footer.js +1 -1
- package/lib/payment/form/address.d.ts +9 -2
- package/lib/payment/form/address.js +67 -59
- package/lib/payment/form/currency.js +31 -24
- package/lib/payment/form/index.d.ts +1 -1
- package/lib/payment/form/index.js +92 -93
- package/lib/payment/form/phone.js +11 -59
- package/lib/payment/index.d.ts +1 -10
- package/lib/payment/index.js +291 -219
- package/lib/payment/product-card.js +5 -4
- package/lib/payment/product-donation.js +9 -2
- package/lib/payment/product-item.d.ts +2 -2
- package/lib/payment/product-item.js +38 -19
- package/lib/payment/summary.js +219 -127
- package/lib/theme/index.css +240 -0
- package/lib/theme/index.d.ts +9 -0
- package/lib/theme/index.js +259 -0
- package/lib/theme/typography.d.ts +2 -0
- package/lib/theme/typography.js +59 -0
- package/lib/types/index.d.ts +11 -0
- package/package.json +14 -11
- package/src/checkout/donate.tsx +16 -10
- package/src/checkout/form.tsx +23 -0
- package/src/checkout/table.tsx +13 -1
- package/src/components/blockchain/tx.tsx +2 -1
- package/src/components/country-select.tsx +93 -0
- package/src/components/input.tsx +49 -46
- package/src/components/livemode.tsx +1 -0
- package/src/components/pricing-table.tsx +0 -2
- package/src/components/status.tsx +1 -2
- package/src/components/table.tsx +200 -0
- package/src/contexts/payment.tsx +6 -1
- package/src/history/invoice/list.tsx +254 -49
- package/src/hooks/mobile.ts +13 -0
- package/src/index.ts +7 -0
- package/src/libs/util.ts +120 -31
- package/src/locales/en.tsx +18 -4
- package/src/locales/index.tsx +10 -3
- package/src/locales/zh.tsx +17 -3
- package/src/payment/error.tsx +2 -2
- package/src/payment/footer.tsx +1 -1
- package/src/payment/form/address.tsx +56 -47
- package/src/payment/form/currency.tsx +29 -23
- package/src/payment/form/index.tsx +89 -76
- package/src/payment/form/phone.tsx +14 -51
- package/src/payment/index.tsx +294 -242
- package/src/payment/product-card.tsx +4 -4
- package/src/payment/product-donation.tsx +7 -3
- package/src/payment/product-item.tsx +49 -20
- package/src/payment/summary.tsx +191 -108
- package/src/theme/index.css +240 -0
- package/src/theme/index.tsx +250 -0
- package/src/theme/typography.ts +56 -0
- package/src/types/index.ts +12 -0
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/indent */
|
|
2
|
+
/* eslint-disable react/require-default-props */
|
|
3
|
+
/* eslint-disable react/no-unused-prop-types */
|
|
4
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
1
5
|
/* eslint-disable no-nested-ternary */
|
|
2
6
|
/* eslint-disable react/no-unstable-nested-components */
|
|
3
7
|
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
@@ -6,8 +10,8 @@ import type { Paginated, TInvoiceExpanded, TSubscription } from '@blocklet/payme
|
|
|
6
10
|
import { OpenInNewOutlined } from '@mui/icons-material';
|
|
7
11
|
import { Box, Button, CircularProgress, Hidden, Stack, Typography } from '@mui/material';
|
|
8
12
|
import { styled } from '@mui/system';
|
|
9
|
-
import { useInfiniteScroll, useSetState } from 'ahooks';
|
|
10
|
-
import { useEffect } from 'react';
|
|
13
|
+
import { useInfiniteScroll, useRequest, useSetState } from 'ahooks';
|
|
14
|
+
import React, { useEffect, useState } from 'react';
|
|
11
15
|
import { joinURL } from 'ufo';
|
|
12
16
|
|
|
13
17
|
import Status from '../../components/status';
|
|
@@ -23,6 +27,7 @@ import {
|
|
|
23
27
|
getPrefix,
|
|
24
28
|
getTxLink,
|
|
25
29
|
} from '../../libs/util';
|
|
30
|
+
import Table from '../../components/table';
|
|
26
31
|
|
|
27
32
|
type Result = Paginated<TInvoiceExpanded> & { subscription: TSubscription };
|
|
28
33
|
|
|
@@ -58,6 +63,7 @@ type Props = {
|
|
|
58
63
|
pageSize?: number;
|
|
59
64
|
target?: string;
|
|
60
65
|
action?: string;
|
|
66
|
+
type?: 'list' | 'table';
|
|
61
67
|
};
|
|
62
68
|
|
|
63
69
|
const getInvoiceLink = (invoice: TInvoiceExpanded, action?: string) => {
|
|
@@ -79,23 +85,210 @@ const getInvoiceLink = (invoice: TInvoiceExpanded, action?: string) => {
|
|
|
79
85
|
};
|
|
80
86
|
};
|
|
81
87
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
const InvoiceTable = React.memo((props: Props & { onPay: (invoiceId: string) => void }) => {
|
|
89
|
+
const {
|
|
90
|
+
pageSize,
|
|
91
|
+
target,
|
|
92
|
+
action,
|
|
93
|
+
onPay,
|
|
94
|
+
status,
|
|
95
|
+
customer_id,
|
|
96
|
+
currency_id,
|
|
97
|
+
subscription_id,
|
|
98
|
+
include_staking,
|
|
99
|
+
include_recovered_from,
|
|
100
|
+
} = props;
|
|
101
|
+
const listKey = 'invoice-table';
|
|
102
|
+
const { t, locale } = useLocaleContext();
|
|
103
|
+
|
|
104
|
+
const [search, setSearch] = useState<{ pageSize: number; page: number }>({
|
|
105
|
+
pageSize: pageSize || 10,
|
|
106
|
+
page: 1,
|
|
107
|
+
});
|
|
108
|
+
const { loading, data = { list: [], count: 0 } } = useRequest(
|
|
109
|
+
() =>
|
|
110
|
+
fetchData({
|
|
111
|
+
...search,
|
|
112
|
+
status,
|
|
113
|
+
customer_id,
|
|
114
|
+
currency_id,
|
|
115
|
+
subscription_id,
|
|
116
|
+
include_staking,
|
|
117
|
+
include_recovered_from,
|
|
118
|
+
ignore_zero: true,
|
|
119
|
+
}),
|
|
120
|
+
{
|
|
121
|
+
refreshDeps: [search],
|
|
122
|
+
}
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
const columns = [
|
|
126
|
+
{
|
|
127
|
+
label: t('payment.customer.invoice.invoiceNumber'),
|
|
128
|
+
name: 'number',
|
|
129
|
+
options: {
|
|
130
|
+
customBodyRenderLite: (_: string, index: number) => {
|
|
131
|
+
const invoice = data?.list[index] as TInvoiceExpanded;
|
|
132
|
+
const link = getInvoiceLink(invoice, action);
|
|
133
|
+
return (
|
|
134
|
+
<a href={link.url} target={link.external ? '_blank' : target} rel="noreferrer">
|
|
135
|
+
{invoice?.number}
|
|
136
|
+
</a>
|
|
137
|
+
);
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
label: t('common.amount'),
|
|
143
|
+
name: 'total',
|
|
144
|
+
options: {
|
|
145
|
+
customBodyRenderLite: (_: string, index: number) => {
|
|
146
|
+
const invoice = data?.list[index] as TInvoiceExpanded;
|
|
147
|
+
const link = getInvoiceLink(invoice, action);
|
|
148
|
+
return (
|
|
149
|
+
<a href={link.url} target={link.external ? '_blank' : target} rel="noreferrer">
|
|
150
|
+
<Typography>
|
|
151
|
+
{formatBNStr(invoice.total, invoice.paymentCurrency.decimal)}
|
|
152
|
+
{invoice.paymentCurrency.symbol}
|
|
153
|
+
</Typography>
|
|
154
|
+
</a>
|
|
155
|
+
);
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
{
|
|
161
|
+
label: t('common.updatedAt'),
|
|
162
|
+
name: 'name',
|
|
163
|
+
options: {
|
|
164
|
+
customBodyRenderLite: (val: string, index: number) => {
|
|
165
|
+
const invoice = data?.list[index] as TInvoiceExpanded;
|
|
166
|
+
const link = getInvoiceLink(invoice, action);
|
|
167
|
+
return (
|
|
168
|
+
<a href={link.url} target={link.external ? '_blank' : target} rel="noreferrer">
|
|
169
|
+
{formatToDate(invoice.created_at, locale, 'YYYY-MM-DD HH:mm:ss')}
|
|
170
|
+
</a>
|
|
171
|
+
);
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
label: t('common.description'),
|
|
177
|
+
name: '',
|
|
178
|
+
options: {
|
|
179
|
+
sort: false,
|
|
180
|
+
customBodyRenderLite: (val: string, index: number) => {
|
|
181
|
+
const invoice = data?.list[index] as TInvoiceExpanded;
|
|
182
|
+
const link = getInvoiceLink(invoice, action);
|
|
183
|
+
return (
|
|
184
|
+
<a href={link.url} target={link.external ? '_blank' : target} rel="noreferrer">
|
|
185
|
+
{invoice.description || invoice.id}
|
|
186
|
+
</a>
|
|
187
|
+
);
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
label: t('common.status'),
|
|
193
|
+
name: 'created_at',
|
|
194
|
+
options: {
|
|
195
|
+
sort: true,
|
|
196
|
+
customBodyRenderLite: (val: string, index: number) => {
|
|
197
|
+
const invoice = data?.list[index] as TInvoiceExpanded;
|
|
198
|
+
const link = getInvoiceLink(invoice, action);
|
|
199
|
+
if (action) {
|
|
200
|
+
return link.connect ? (
|
|
201
|
+
<Button variant="text" size="small" onClick={() => onPay(invoice.id)} sx={{ color: 'text.link' }}>
|
|
202
|
+
{t('payment.customer.invoice.pay')}
|
|
203
|
+
</Button>
|
|
204
|
+
) : (
|
|
205
|
+
<Button
|
|
206
|
+
component="a"
|
|
207
|
+
variant="text"
|
|
208
|
+
size="small"
|
|
209
|
+
href={link.url}
|
|
210
|
+
target={link.external ? '_blank' : target}
|
|
211
|
+
sx={{ color: 'var(--foregrounds-fg-interactive, #0086FF) !important' }}
|
|
212
|
+
rel="noreferrer">
|
|
213
|
+
{t('payment.customer.invoice.pay')}
|
|
214
|
+
</Button>
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
return (
|
|
218
|
+
<a href={link.url} target={link.external ? '_blank' : target} rel="noreferrer">
|
|
219
|
+
<Status label={invoice.status} color={getInvoiceStatusColor(invoice.status)} />
|
|
220
|
+
</a>
|
|
221
|
+
);
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
];
|
|
226
|
+
|
|
227
|
+
const onTableChange = ({ page, rowsPerPage }: any) => {
|
|
228
|
+
if (search.pageSize !== rowsPerPage) {
|
|
229
|
+
setSearch((x) => ({ ...x, pageSize: rowsPerPage, page: 1 }));
|
|
230
|
+
} else if (search.page !== page + 1) {
|
|
231
|
+
setSearch((x) => ({ ...x, page: page + 1 }));
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
return (
|
|
236
|
+
<InvoiceTableRoot>
|
|
237
|
+
<Table
|
|
238
|
+
hasRowLink
|
|
239
|
+
durable={`__${listKey}__`}
|
|
240
|
+
durableKeys={['page', 'rowsPerPage', 'searchText']}
|
|
241
|
+
data={data.list}
|
|
242
|
+
columns={columns}
|
|
243
|
+
options={{
|
|
244
|
+
count: data.count,
|
|
245
|
+
page: search.page - 1,
|
|
246
|
+
rowsPerPage: search.pageSize,
|
|
247
|
+
}}
|
|
248
|
+
loading={loading}
|
|
249
|
+
onChange={onTableChange}
|
|
250
|
+
toolbar={false}
|
|
251
|
+
sx={{ mt: 2 }}
|
|
252
|
+
showMobile={false}
|
|
253
|
+
mobileTDFlexDirection="row"
|
|
254
|
+
emptyNodeText={t('payment.customer.invoice.emptyList')}
|
|
255
|
+
/>
|
|
256
|
+
</InvoiceTableRoot>
|
|
257
|
+
);
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
const InvoiceTableRoot = styled(Box)`
|
|
261
|
+
@media (max-width: ${({ theme }) => theme.breakpoints.values.md}px) {
|
|
262
|
+
.MuiTable-root > .MuiTableBody-root > .MuiTableRow-root > td.MuiTableCell-root {
|
|
263
|
+
> div {
|
|
264
|
+
width: fit-content;
|
|
265
|
+
flex: inherit;
|
|
266
|
+
font-size: 14px;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
.invoice-summary {
|
|
270
|
+
padding-right: 20px;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
`;
|
|
274
|
+
|
|
275
|
+
const InvoiceList = React.memo((props: Props & { onPay: (invoiceId: string) => void }) => {
|
|
276
|
+
const {
|
|
277
|
+
customer_id,
|
|
278
|
+
subscription_id,
|
|
279
|
+
include_recovered_from,
|
|
280
|
+
currency_id,
|
|
281
|
+
include_staking,
|
|
282
|
+
status,
|
|
283
|
+
pageSize,
|
|
284
|
+
target,
|
|
285
|
+
action,
|
|
286
|
+
onPay,
|
|
287
|
+
} = props;
|
|
93
288
|
const size = pageSize || 10;
|
|
94
289
|
|
|
95
290
|
const subscription = useSubscription('events');
|
|
96
291
|
const { t, locale } = useLocaleContext();
|
|
97
|
-
const { connect } = usePaymentContext();
|
|
98
|
-
const [state, setState] = useSetState({ paying: '' });
|
|
99
292
|
|
|
100
293
|
const { data, loadMore, loadingMore, loading, reloadAsync } = useInfiniteScroll<Result>(
|
|
101
294
|
(d) => {
|
|
@@ -128,38 +321,6 @@ export default function CustomerInvoiceList({
|
|
|
128
321
|
}
|
|
129
322
|
}, [subscription]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
130
323
|
|
|
131
|
-
const onPay = (invoiceId: string) => {
|
|
132
|
-
if (state.paying) {
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
setState({ paying: invoiceId });
|
|
137
|
-
connect.open({
|
|
138
|
-
action: 'collect',
|
|
139
|
-
saveConnect: false,
|
|
140
|
-
messages: {
|
|
141
|
-
scan: '',
|
|
142
|
-
title: t(`payment.customer.invoice.${action || 'pay'}`),
|
|
143
|
-
success: t(`payment.customer.invoice.${action || 'pay'}Success`),
|
|
144
|
-
error: t(`payment.customer.invoice.${action || 'pay'}Error`),
|
|
145
|
-
confirm: '',
|
|
146
|
-
} as any,
|
|
147
|
-
extraParams: { invoiceId, action },
|
|
148
|
-
onSuccess: () => {
|
|
149
|
-
connect.close();
|
|
150
|
-
setState({ paying: '' });
|
|
151
|
-
},
|
|
152
|
-
onClose: () => {
|
|
153
|
-
connect.close();
|
|
154
|
-
setState({ paying: '' });
|
|
155
|
-
},
|
|
156
|
-
onError: (err: any) => {
|
|
157
|
-
setState({ paying: '' });
|
|
158
|
-
Toast.error(formatError(err));
|
|
159
|
-
},
|
|
160
|
-
});
|
|
161
|
-
};
|
|
162
|
-
|
|
163
324
|
if (loading || !data) {
|
|
164
325
|
return <CircularProgress />;
|
|
165
326
|
}
|
|
@@ -241,7 +402,6 @@ export default function CustomerInvoiceList({
|
|
|
241
402
|
<Button
|
|
242
403
|
component="a"
|
|
243
404
|
variant="contained"
|
|
244
|
-
color="primary"
|
|
245
405
|
size="small"
|
|
246
406
|
href={link.url}
|
|
247
407
|
target={link.external ? '_blank' : target}
|
|
@@ -274,6 +434,50 @@ export default function CustomerInvoiceList({
|
|
|
274
434
|
</Box>
|
|
275
435
|
</Root>
|
|
276
436
|
);
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
export default function CustomerInvoiceList(props: Props) {
|
|
440
|
+
const { action, type } = props;
|
|
441
|
+
const { t } = useLocaleContext();
|
|
442
|
+
const { connect } = usePaymentContext();
|
|
443
|
+
const [state, setState] = useSetState({ paying: '' });
|
|
444
|
+
|
|
445
|
+
const onPay = (invoiceId: string) => {
|
|
446
|
+
if (state.paying) {
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
setState({ paying: invoiceId });
|
|
451
|
+
connect.open({
|
|
452
|
+
action: 'collect',
|
|
453
|
+
saveConnect: false,
|
|
454
|
+
messages: {
|
|
455
|
+
scan: '',
|
|
456
|
+
title: t(`payment.customer.invoice.${action || 'pay'}`),
|
|
457
|
+
success: t(`payment.customer.invoice.${action || 'pay'}Success`),
|
|
458
|
+
error: t(`payment.customer.invoice.${action || 'pay'}Error`),
|
|
459
|
+
confirm: '',
|
|
460
|
+
} as any,
|
|
461
|
+
extraParams: { invoiceId, action },
|
|
462
|
+
onSuccess: () => {
|
|
463
|
+
connect.close();
|
|
464
|
+
setState({ paying: '' });
|
|
465
|
+
},
|
|
466
|
+
onClose: () => {
|
|
467
|
+
connect.close();
|
|
468
|
+
setState({ paying: '' });
|
|
469
|
+
},
|
|
470
|
+
onError: (err: any) => {
|
|
471
|
+
setState({ paying: '' });
|
|
472
|
+
Toast.error(formatError(err));
|
|
473
|
+
},
|
|
474
|
+
});
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
if (type === 'table') {
|
|
478
|
+
return <InvoiceTable {...props} onPay={onPay} />;
|
|
479
|
+
}
|
|
480
|
+
return <InvoiceList {...props} onPay={onPay} />;
|
|
277
481
|
}
|
|
278
482
|
|
|
279
483
|
CustomerInvoiceList.defaultProps = {
|
|
@@ -286,10 +490,11 @@ CustomerInvoiceList.defaultProps = {
|
|
|
286
490
|
pageSize: 10,
|
|
287
491
|
target: '_self',
|
|
288
492
|
action: '',
|
|
493
|
+
type: 'list',
|
|
289
494
|
};
|
|
290
495
|
|
|
291
496
|
const Root = styled(Stack)`
|
|
292
|
-
@media (max-width:
|
|
497
|
+
@media (max-width: ${({ theme }) => theme.breakpoints.values.md}px) {
|
|
293
498
|
.invoice-description {
|
|
294
499
|
display: none !important;
|
|
295
500
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useTheme } from '@mui/material/styles';
|
|
2
|
+
import useMediaQuery from '@mui/material/useMediaQuery';
|
|
3
|
+
|
|
4
|
+
const MOBILE_POINT = 'md';
|
|
5
|
+
|
|
6
|
+
export function useMobile(mobilePoint: 'md' | 'sm' | 'lg' | 'xl' | 'xs' = MOBILE_POINT) {
|
|
7
|
+
const theme = useTheme();
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
isMobile: useMediaQuery(theme.breakpoints.down(mobilePoint)),
|
|
11
|
+
mobileSize: `${theme.breakpoints.values[mobilePoint]}px`,
|
|
12
|
+
};
|
|
13
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -7,6 +7,7 @@ import ConfirmDialog from './components/confirm';
|
|
|
7
7
|
import FormInput from './components/input';
|
|
8
8
|
import Livemode from './components/livemode';
|
|
9
9
|
import PricingTable from './components/pricing-table';
|
|
10
|
+
import Table from './components/table';
|
|
10
11
|
import SafeGuard from './components/safe-guard';
|
|
11
12
|
import Status from './components/status';
|
|
12
13
|
import Switch from './components/switch-button';
|
|
@@ -23,11 +24,15 @@ import Payment from './payment/index';
|
|
|
23
24
|
import ProductSkeleton from './payment/product-skeleton';
|
|
24
25
|
import PaymentSummary from './payment/summary';
|
|
25
26
|
import PricingItem from './components/pricing-item';
|
|
27
|
+
import CountrySelect from './components/country-select';
|
|
28
|
+
|
|
29
|
+
export { PaymentThemeProvider } from './theme';
|
|
26
30
|
|
|
27
31
|
export * from './libs/util';
|
|
28
32
|
export * from './libs/connect';
|
|
29
33
|
export * from './contexts/payment';
|
|
30
34
|
export * from './hooks/subscription';
|
|
35
|
+
export * from './hooks/mobile';
|
|
31
36
|
|
|
32
37
|
export { translations, createTranslator } from './locales';
|
|
33
38
|
|
|
@@ -57,4 +62,6 @@ export {
|
|
|
57
62
|
TxGas,
|
|
58
63
|
SafeGuard,
|
|
59
64
|
PricingItem,
|
|
65
|
+
CountrySelect,
|
|
66
|
+
Table,
|
|
60
67
|
};
|
package/src/libs/util.ts
CHANGED
|
@@ -24,7 +24,7 @@ import { joinURL } from 'ufo';
|
|
|
24
24
|
|
|
25
25
|
import { t } from '../locales';
|
|
26
26
|
import dayjs from './dayjs';
|
|
27
|
-
import { PricingRenderProps } from '../types';
|
|
27
|
+
import { ActionProps, PricingRenderProps } from '../types';
|
|
28
28
|
|
|
29
29
|
export const PAYMENT_KIT_DID = 'z2qaCNvKMv5GjouKdcDWexv6WqtHbpNPQDnAk';
|
|
30
30
|
|
|
@@ -533,6 +533,32 @@ export function formatUpsellSaving(items: TLineItemExpanded[], currency: TPaymen
|
|
|
533
533
|
return Number(before.sub(after).mul(new BN(100)).div(before).toString()).toFixed(0);
|
|
534
534
|
}
|
|
535
535
|
|
|
536
|
+
export function formatMeteredThen(
|
|
537
|
+
subscription: string,
|
|
538
|
+
recurring: string,
|
|
539
|
+
hasMetered: boolean,
|
|
540
|
+
locale: string = 'en'
|
|
541
|
+
): string {
|
|
542
|
+
if (hasMetered) {
|
|
543
|
+
return t('payment.checkout.meteredThen', locale, { subscription, recurring });
|
|
544
|
+
}
|
|
545
|
+
return t('payment.checkout.then', locale, { subscription, recurring });
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
export function formatPriceDisplay(
|
|
549
|
+
{ amount, then, actualAmount, showThen }: { amount: string; then?: string; actualAmount: string; showThen?: boolean },
|
|
550
|
+
recurring: string,
|
|
551
|
+
hasMetered: boolean,
|
|
552
|
+
locale: string = 'en'
|
|
553
|
+
) {
|
|
554
|
+
if (Number(actualAmount) === 0 && hasMetered) {
|
|
555
|
+
return t('payment.checkout.metered', locale, { recurring });
|
|
556
|
+
}
|
|
557
|
+
if (showThen) {
|
|
558
|
+
return [amount, then].filter(Boolean).join(', ');
|
|
559
|
+
}
|
|
560
|
+
return [amount, then].filter(Boolean).join(' ');
|
|
561
|
+
}
|
|
536
562
|
export function formatCheckoutHeadlines(
|
|
537
563
|
items: TLineItemExpanded[],
|
|
538
564
|
currency: TPaymentCurrency,
|
|
@@ -543,9 +569,13 @@ export function formatCheckoutHeadlines(
|
|
|
543
569
|
amount: string;
|
|
544
570
|
then?: string;
|
|
545
571
|
secondary?: string;
|
|
572
|
+
showThen?: boolean;
|
|
573
|
+
actualAmount: string;
|
|
574
|
+
priceDisplay: string;
|
|
546
575
|
} {
|
|
547
576
|
const brand = getStatementDescriptor(items);
|
|
548
577
|
const { total } = getCheckoutAmount(items, currency, trialInDays > 0);
|
|
578
|
+
const actualAmount = fromUnitToToken(total, currency.decimal);
|
|
549
579
|
const amount = `${fromUnitToToken(total, currency.decimal)} ${currency.symbol}`;
|
|
550
580
|
|
|
551
581
|
// empty
|
|
@@ -554,6 +584,8 @@ export function formatCheckoutHeadlines(
|
|
|
554
584
|
action: t('payment.checkout.empty', locale),
|
|
555
585
|
amount: '0',
|
|
556
586
|
then: '',
|
|
587
|
+
actualAmount: '0',
|
|
588
|
+
priceDisplay: '0',
|
|
557
589
|
};
|
|
558
590
|
}
|
|
559
591
|
|
|
@@ -563,10 +595,10 @@ export function formatCheckoutHeadlines(
|
|
|
563
595
|
if (items.every((x) => x.price.type === 'one_time')) {
|
|
564
596
|
const action = t('payment.checkout.pay', locale, { payee: brand });
|
|
565
597
|
if (items.length > 1) {
|
|
566
|
-
return { action, amount };
|
|
598
|
+
return { action, amount, actualAmount, priceDisplay: amount };
|
|
567
599
|
}
|
|
568
600
|
|
|
569
|
-
return { action, amount, then: '' };
|
|
601
|
+
return { action, amount, then: '', actualAmount, priceDisplay: amount };
|
|
570
602
|
}
|
|
571
603
|
|
|
572
604
|
const item = items.find((x) => x.price.type === 'recurring');
|
|
@@ -576,10 +608,9 @@ export function formatCheckoutHeadlines(
|
|
|
576
608
|
'per',
|
|
577
609
|
locale
|
|
578
610
|
);
|
|
579
|
-
|
|
611
|
+
const hasMetered = items.some((x) => x.price.type === 'recurring' && x.price.recurring?.usage_type === 'metered');
|
|
580
612
|
// all recurring
|
|
581
613
|
if (items.every((x) => x.price.type === 'recurring')) {
|
|
582
|
-
const hasMetered = items.some((x) => x.price.type === 'recurring' && x.price.recurring?.usage_type === 'metered');
|
|
583
614
|
const subscription = [
|
|
584
615
|
hasMetered ? t('payment.checkout.least', locale) : '',
|
|
585
616
|
fromUnitToToken(
|
|
@@ -597,32 +628,54 @@ export function formatCheckoutHeadlines(
|
|
|
597
628
|
.join(' ');
|
|
598
629
|
if (items.length > 1) {
|
|
599
630
|
if (trialInDays > 0) {
|
|
600
|
-
|
|
631
|
+
const result = {
|
|
601
632
|
action: t('payment.checkout.try2', locale, { name, count: items.length - 1 }),
|
|
602
633
|
amount: t('payment.checkout.free', locale, { count: trialInDays }),
|
|
603
|
-
then:
|
|
634
|
+
then: formatMeteredThen(subscription, recurring, hasMetered && Number(subscription) === 0, locale),
|
|
635
|
+
showThen: true,
|
|
636
|
+
actualAmount: '0',
|
|
637
|
+
};
|
|
638
|
+
return {
|
|
639
|
+
...result,
|
|
640
|
+
priceDisplay: formatPriceDisplay(result, recurring, hasMetered, locale),
|
|
604
641
|
};
|
|
605
642
|
}
|
|
606
|
-
|
|
607
|
-
return {
|
|
643
|
+
const result = {
|
|
608
644
|
action: t('payment.checkout.sub2', locale, { name, count: items.length - 1 }),
|
|
609
645
|
amount,
|
|
610
|
-
then: recurring,
|
|
646
|
+
then: hasMetered ? t('payment.checkout.meteredThen', locale, { recurring }) : recurring,
|
|
647
|
+
showThen: hasMetered,
|
|
648
|
+
actualAmount,
|
|
649
|
+
};
|
|
650
|
+
return {
|
|
651
|
+
...result,
|
|
652
|
+
priceDisplay: formatPriceDisplay(result, recurring, hasMetered, locale),
|
|
611
653
|
};
|
|
612
654
|
}
|
|
613
655
|
|
|
614
656
|
if (trialInDays > 0) {
|
|
615
|
-
|
|
657
|
+
const result = {
|
|
616
658
|
action: t('payment.checkout.try1', locale, { name }),
|
|
617
659
|
amount: t('payment.checkout.free', locale, { count: trialInDays }),
|
|
618
|
-
then:
|
|
660
|
+
then: formatMeteredThen(subscription, recurring, hasMetered && Number(subscription) === 0, locale),
|
|
661
|
+
showThen: true,
|
|
662
|
+
actualAmount: '0',
|
|
663
|
+
};
|
|
664
|
+
return {
|
|
665
|
+
...result,
|
|
666
|
+
priceDisplay: formatPriceDisplay(result, recurring, hasMetered, locale),
|
|
619
667
|
};
|
|
620
668
|
}
|
|
621
|
-
|
|
622
|
-
return {
|
|
669
|
+
const result = {
|
|
623
670
|
action: t('payment.checkout.sub1', locale, { name }),
|
|
624
671
|
amount,
|
|
625
|
-
then: recurring,
|
|
672
|
+
then: hasMetered ? t('payment.checkout.meteredThen', locale, { recurring }) : recurring,
|
|
673
|
+
showThen: hasMetered,
|
|
674
|
+
actualAmount,
|
|
675
|
+
};
|
|
676
|
+
return {
|
|
677
|
+
...result,
|
|
678
|
+
priceDisplay: formatPriceDisplay(result, recurring, hasMetered, locale),
|
|
626
679
|
};
|
|
627
680
|
}
|
|
628
681
|
|
|
@@ -639,10 +692,22 @@ export function formatCheckoutHeadlines(
|
|
|
639
692
|
currency.decimal
|
|
640
693
|
);
|
|
641
694
|
|
|
642
|
-
|
|
695
|
+
const result = {
|
|
643
696
|
action: t('payment.checkout.pay', locale, { payee: brand }),
|
|
644
697
|
amount,
|
|
645
|
-
then:
|
|
698
|
+
then: formatMeteredThen(
|
|
699
|
+
`${subscription} ${currency.symbol}`,
|
|
700
|
+
recurring,
|
|
701
|
+
hasMetered && Number(subscription) === 0,
|
|
702
|
+
locale
|
|
703
|
+
),
|
|
704
|
+
showThen: true,
|
|
705
|
+
actualAmount,
|
|
706
|
+
};
|
|
707
|
+
|
|
708
|
+
return {
|
|
709
|
+
...result,
|
|
710
|
+
priceDisplay: formatPriceDisplay(result, recurring, hasMetered, locale),
|
|
646
711
|
};
|
|
647
712
|
}
|
|
648
713
|
|
|
@@ -690,48 +755,65 @@ export function formatSubscriptionProduct(items: TSubscriptionItemExpanded[], ma
|
|
|
690
755
|
}
|
|
691
756
|
|
|
692
757
|
export const getSubscriptionTimeSummary = (subscription: TSubscriptionExpanded) => {
|
|
693
|
-
const lines = [`
|
|
758
|
+
const lines = [`Start on ${formatToDate(subscription.start_date * 1000, 'en', 'YYYY-MM-DD')}`];
|
|
759
|
+
|
|
760
|
+
const getLineTimeMessage = (time: number) => {
|
|
761
|
+
const curDay = dayjs().isSame(dayjs(time), 'day');
|
|
762
|
+
const timeFormat = curDay ? 'HH:mm:ss' : 'YYYY-MM-DD';
|
|
763
|
+
return `${curDay ? 'in' : 'on'} ${formatToDate(time, 'en', timeFormat)}`;
|
|
764
|
+
};
|
|
765
|
+
|
|
694
766
|
if (subscription.status === 'active' || subscription.status === 'trialing') {
|
|
695
767
|
if (subscription.cancel_at) {
|
|
696
|
-
lines.push(`
|
|
768
|
+
lines.push(`Ended ${getLineTimeMessage(subscription.cancel_at * 1000)}`);
|
|
697
769
|
} else if (subscription.cancel_at_period_end) {
|
|
698
|
-
lines.push(`
|
|
770
|
+
lines.push(`Ended ${getLineTimeMessage(subscription.current_period_end * 1000)}`);
|
|
699
771
|
} else {
|
|
700
|
-
lines.push(`
|
|
772
|
+
lines.push(`Renew ${getLineTimeMessage(subscription.current_period_end * 1000)}`);
|
|
701
773
|
}
|
|
702
774
|
} else if (subscription.status === 'past_due') {
|
|
703
|
-
lines.push(`
|
|
775
|
+
lines.push(`Ended ${getLineTimeMessage((subscription.cancel_at || subscription.current_period_end) * 1000)}`);
|
|
704
776
|
} else if (subscription.status === 'canceled') {
|
|
705
|
-
lines.push(`
|
|
777
|
+
lines.push(`Ended ${getLineTimeMessage(subscription.canceled_at * 1000)}`);
|
|
706
778
|
}
|
|
707
779
|
|
|
708
|
-
return lines.join(',
|
|
780
|
+
return lines.join(',');
|
|
709
781
|
};
|
|
710
782
|
|
|
711
|
-
export const getSubscriptionAction = (
|
|
783
|
+
export const getSubscriptionAction = (
|
|
784
|
+
subscription: TSubscriptionExpanded,
|
|
785
|
+
actionProps: ActionProps
|
|
786
|
+
): {
|
|
787
|
+
action: string;
|
|
788
|
+
variant: string;
|
|
789
|
+
color: string;
|
|
790
|
+
canRenew: boolean;
|
|
791
|
+
text?: string;
|
|
792
|
+
sx?: any;
|
|
793
|
+
} | null => {
|
|
712
794
|
if (subscription.status === 'active' || subscription.status === 'trialing') {
|
|
713
795
|
if (subscription.cancel_at_period_end) {
|
|
714
796
|
if (subscription.cancelation_details?.reason === 'payment_failed') {
|
|
715
797
|
return null;
|
|
716
798
|
}
|
|
717
799
|
|
|
718
|
-
return { action: 'recover', variant: 'contained', color: 'primary', canRenew: false };
|
|
800
|
+
return { action: 'recover', variant: 'contained', color: 'primary', canRenew: false, ...actionProps?.recover };
|
|
719
801
|
}
|
|
720
802
|
|
|
721
803
|
if (subscription.cancel_at && subscription.cancel_at !== subscription.current_period_end) {
|
|
722
804
|
return null;
|
|
723
805
|
}
|
|
724
806
|
|
|
725
|
-
return { action: 'cancel', variant: 'outlined', color: 'inherit', canRenew: false };
|
|
807
|
+
return { action: 'cancel', variant: 'outlined', color: 'inherit', canRenew: false, ...actionProps?.cancel };
|
|
726
808
|
}
|
|
727
809
|
|
|
728
810
|
if (subscription.status === 'past_due') {
|
|
729
811
|
const canRenew = subscription.cancel_at && subscription.cancel_at !== subscription.current_period_end;
|
|
730
|
-
return { action: 'pastDue', variant: 'contained', color: 'primary', canRenew };
|
|
812
|
+
return { action: 'pastDue', variant: 'contained', color: 'primary', canRenew, ...actionProps?.pastDue };
|
|
731
813
|
}
|
|
732
814
|
|
|
733
815
|
if (subscription.status !== 'canceled' && subscription.cancel_at_period_end) {
|
|
734
|
-
return { action: 'recover', variant: 'contained', color: 'primary', canRenew: false };
|
|
816
|
+
return { action: 'recover', variant: 'contained', color: 'primary', canRenew: false, ...actionProps?.recover };
|
|
735
817
|
}
|
|
736
818
|
|
|
737
819
|
return null;
|
|
@@ -855,9 +937,9 @@ export function formatTotalPrice({
|
|
|
855
937
|
const unitValue = new BN(price.custom_unit_amount || price.unit_amount);
|
|
856
938
|
const currency: TPaymentCurrency = price?.currency ?? {};
|
|
857
939
|
|
|
858
|
-
const total = `${fromUnitToToken(unitValue.mul(new BN(quantity)), currency.decimal)} ${currency.symbol}`;
|
|
940
|
+
const total = `${fromUnitToToken(unitValue.mul(new BN(quantity)), currency.decimal)} ${currency.symbol} `;
|
|
859
941
|
|
|
860
|
-
const unit = `${fromUnitToToken(unitValue, currency.decimal)} ${currency.symbol}`;
|
|
942
|
+
const unit = `${fromUnitToToken(unitValue, currency.decimal)} ${currency.symbol} `;
|
|
861
943
|
|
|
862
944
|
const appendUnit = (v: string, alt: string) => {
|
|
863
945
|
if (product.unit_label) {
|
|
@@ -893,6 +975,13 @@ export function formatQuantityInventory(price: TPrice, quantity: string | number
|
|
|
893
975
|
return '';
|
|
894
976
|
}
|
|
895
977
|
|
|
978
|
+
export function formatSubscriptionStatus(status: string) {
|
|
979
|
+
if (status === 'canceled') {
|
|
980
|
+
return 'Ended';
|
|
981
|
+
}
|
|
982
|
+
return status;
|
|
983
|
+
}
|
|
984
|
+
|
|
896
985
|
export function formatAmountPrecisionLimit(amount: string, locale = 'en', precision: number = 6) {
|
|
897
986
|
if (!amount) {
|
|
898
987
|
return '';
|