@blocklet/payment-react 1.13.124 → 1.13.126
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/api.js +0 -1
- package/es/components/confirm.d.ts +14 -0
- package/es/components/confirm.js +31 -0
- package/es/components/pricing-table.js +14 -5
- package/es/index.d.ts +4 -1
- package/es/index.js +7 -1
- package/es/locales/en.js +5 -1
- package/es/locales/zh.js +4 -0
- package/es/payment/index.js +3 -3
- package/es/portal/invoice/list.d.ts +6 -0
- package/es/portal/invoice/list.js +84 -0
- package/es/portal/payment/list.d.ts +6 -0
- package/es/portal/payment/list.js +84 -0
- package/es/util.d.ts +4 -0
- package/es/util.js +56 -0
- package/lib/api.js +0 -1
- package/lib/components/confirm.d.ts +14 -0
- package/lib/components/confirm.js +49 -0
- package/lib/components/pricing-table.js +144 -135
- package/lib/index.d.ts +4 -1
- package/lib/index.js +24 -0
- package/lib/locales/en.js +5 -1
- package/lib/locales/zh.js +4 -0
- package/lib/payment/index.js +3 -3
- package/lib/portal/invoice/list.d.ts +6 -0
- package/lib/portal/invoice/list.js +150 -0
- package/lib/portal/payment/list.d.ts +6 -0
- package/lib/portal/payment/list.js +149 -0
- package/lib/util.d.ts +4 -0
- package/lib/util.js +62 -1
- package/package.json +3 -3
- package/src/api.ts +1 -1
- package/src/components/confirm.tsx +39 -0
- package/src/components/pricing-table.tsx +124 -113
- package/src/index.ts +6 -0
- package/src/locales/en.tsx +5 -1
- package/src/locales/zh.tsx +4 -0
- package/src/payment/index.tsx +3 -3
- package/src/portal/invoice/list.tsx +122 -0
- package/src/portal/payment/list.tsx +120 -0
- package/src/util.ts +60 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
module.exports = CustomerPaymentList;
|
|
7
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
8
|
+
var _context = require("@arcblock/ux/lib/Locale/context");
|
|
9
|
+
var _material = require("@mui/material");
|
|
10
|
+
var _util = require("@ocap/util");
|
|
11
|
+
var _ahooks = require("ahooks");
|
|
12
|
+
var _api = _interopRequireDefault(require("../../api"));
|
|
13
|
+
var _status = _interopRequireDefault(require("../../components/status"));
|
|
14
|
+
var _util2 = require("../../util");
|
|
15
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
16
|
+
const groupByDate = items => {
|
|
17
|
+
const grouped = {};
|
|
18
|
+
items.forEach(item => {
|
|
19
|
+
const date = new Date(item.created_at).toLocaleDateString();
|
|
20
|
+
if (!grouped[date]) {
|
|
21
|
+
grouped[date] = [];
|
|
22
|
+
}
|
|
23
|
+
grouped[date]?.push(item);
|
|
24
|
+
});
|
|
25
|
+
return grouped;
|
|
26
|
+
};
|
|
27
|
+
const fetchData = (params = {}) => {
|
|
28
|
+
const search = new URLSearchParams();
|
|
29
|
+
Object.keys(params).forEach(key => {
|
|
30
|
+
search.set(key, String(params[key]));
|
|
31
|
+
});
|
|
32
|
+
return _api.default.get(`/api/payment-intents?${search.toString()}`).then(res => res.data);
|
|
33
|
+
};
|
|
34
|
+
const pageSize = 10;
|
|
35
|
+
function CustomerPaymentList({
|
|
36
|
+
customer_id
|
|
37
|
+
}) {
|
|
38
|
+
const {
|
|
39
|
+
t
|
|
40
|
+
} = (0, _context.useLocaleContext)();
|
|
41
|
+
const {
|
|
42
|
+
data,
|
|
43
|
+
loadMore,
|
|
44
|
+
loadingMore,
|
|
45
|
+
loading
|
|
46
|
+
} = (0, _ahooks.useInfiniteScroll)(d => {
|
|
47
|
+
const page = d ? Math.ceil(d.list.length / pageSize) + 1 : 1;
|
|
48
|
+
return fetchData({
|
|
49
|
+
page,
|
|
50
|
+
pageSize,
|
|
51
|
+
customer_id
|
|
52
|
+
});
|
|
53
|
+
}, {
|
|
54
|
+
reloadDeps: [customer_id]
|
|
55
|
+
});
|
|
56
|
+
if (loading || !data) {
|
|
57
|
+
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.CircularProgress, {});
|
|
58
|
+
}
|
|
59
|
+
if (data && data.list.length === 0) {
|
|
60
|
+
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
61
|
+
color: "text.secondary",
|
|
62
|
+
children: t("payment.customer.payment.empty")
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
const hasMore = data && data.list.length < data.count;
|
|
66
|
+
const grouped = groupByDate(data.list);
|
|
67
|
+
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
68
|
+
direction: "column",
|
|
69
|
+
gap: 1,
|
|
70
|
+
sx: {
|
|
71
|
+
mt: 1
|
|
72
|
+
},
|
|
73
|
+
children: [Object.entries(grouped).map(([date, payments]) => /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
|
|
74
|
+
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
75
|
+
sx: {
|
|
76
|
+
fontWeight: "bold",
|
|
77
|
+
color: "text.secondary",
|
|
78
|
+
mt: 2,
|
|
79
|
+
mb: 1
|
|
80
|
+
},
|
|
81
|
+
children: date
|
|
82
|
+
}), payments.map(item => /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
83
|
+
direction: {
|
|
84
|
+
xs: "column",
|
|
85
|
+
sm: "row"
|
|
86
|
+
},
|
|
87
|
+
sx: {
|
|
88
|
+
my: 1
|
|
89
|
+
},
|
|
90
|
+
gap: {
|
|
91
|
+
xs: 0.5,
|
|
92
|
+
sm: 1.5,
|
|
93
|
+
md: 3
|
|
94
|
+
},
|
|
95
|
+
flexWrap: "nowrap",
|
|
96
|
+
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
97
|
+
flex: 3,
|
|
98
|
+
sx: {
|
|
99
|
+
minWidth: "220px"
|
|
100
|
+
},
|
|
101
|
+
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
102
|
+
component: "span",
|
|
103
|
+
children: item.id
|
|
104
|
+
})
|
|
105
|
+
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
106
|
+
flex: 3,
|
|
107
|
+
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
108
|
+
children: (0, _util2.formatToDate)(item.created_at)
|
|
109
|
+
})
|
|
110
|
+
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
111
|
+
flex: 2,
|
|
112
|
+
children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, {
|
|
113
|
+
textAlign: "right",
|
|
114
|
+
children: [(0, _util.fromUnitToToken)(item.amount, item.paymentCurrency.decimal), "\xA0", item.paymentCurrency.symbol]
|
|
115
|
+
})
|
|
116
|
+
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
117
|
+
flex: 3,
|
|
118
|
+
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_status.default, {
|
|
119
|
+
label: item.status,
|
|
120
|
+
color: (0, _util2.getPaymentIntentStatusColor)(item.status)
|
|
121
|
+
})
|
|
122
|
+
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
123
|
+
flex: 4,
|
|
124
|
+
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
125
|
+
children: item.description || item.id
|
|
126
|
+
})
|
|
127
|
+
})]
|
|
128
|
+
}, item.id))]
|
|
129
|
+
}, date)), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
|
|
130
|
+
children: [hasMore && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
|
|
131
|
+
variant: "text",
|
|
132
|
+
type: "button",
|
|
133
|
+
color: "inherit",
|
|
134
|
+
onClick: loadMore,
|
|
135
|
+
disabled: loadingMore,
|
|
136
|
+
children: loadingMore ? t("common.loadingMore", {
|
|
137
|
+
resource: t("payment.customer.payments")
|
|
138
|
+
}) : t("common.loadMore", {
|
|
139
|
+
resource: t("payment.customer.payments")
|
|
140
|
+
})
|
|
141
|
+
}), !hasMore && data.count > pageSize && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
142
|
+
color: "text.secondary",
|
|
143
|
+
children: t("common.noMore", {
|
|
144
|
+
resource: t("payment.customer.payments")
|
|
145
|
+
})
|
|
146
|
+
})]
|
|
147
|
+
})]
|
|
148
|
+
});
|
|
149
|
+
}
|
package/lib/util.d.ts
CHANGED
|
@@ -20,6 +20,10 @@ export declare function formatLineItemPricing(item: TLineItemExpanded, currency:
|
|
|
20
20
|
secondary?: string;
|
|
21
21
|
quantity: string;
|
|
22
22
|
};
|
|
23
|
+
export declare function getSubscriptionStatusColor(status: string): "success" | "primary" | "warning" | "error" | "default";
|
|
24
|
+
export declare function getPaymentIntentStatusColor(status: string): "success" | "warning" | "default";
|
|
25
|
+
export declare function getInvoiceStatusColor(status: string): "success" | "warning" | "default" | "secondary";
|
|
26
|
+
export declare function getWebhookStatusColor(status: string): "success" | "default";
|
|
23
27
|
export declare function getCheckoutAmount(items: TLineItemExpanded[], currency: TPaymentCurrency, includeFreeTrial?: boolean, upsell?: boolean): {
|
|
24
28
|
subtotal: any;
|
|
25
29
|
total: any;
|
package/lib/util.js
CHANGED
|
@@ -17,12 +17,17 @@ exports.formatToDate = formatToDate;
|
|
|
17
17
|
exports.formatToDatetime = formatToDatetime;
|
|
18
18
|
exports.formatUpsellSaving = formatUpsellSaving;
|
|
19
19
|
exports.getCheckoutAmount = getCheckoutAmount;
|
|
20
|
+
exports.getInvoiceStatusColor = getInvoiceStatusColor;
|
|
21
|
+
exports.getPaymentIntentStatusColor = getPaymentIntentStatusColor;
|
|
20
22
|
exports.getPrefix = void 0;
|
|
21
23
|
exports.getPriceCurrencyOptions = getPriceCurrencyOptions;
|
|
22
24
|
exports.getPriceUintAmountByCurrency = getPriceUintAmountByCurrency;
|
|
23
25
|
exports.getRecurringPeriod = getRecurringPeriod;
|
|
24
26
|
exports.getStatementDescriptor = getStatementDescriptor;
|
|
25
|
-
exports.
|
|
27
|
+
exports.getSubscriptionAction = void 0;
|
|
28
|
+
exports.getSubscriptionStatusColor = getSubscriptionStatusColor;
|
|
29
|
+
exports.getSubscriptionTimeSummary = void 0;
|
|
30
|
+
exports.getWebhookStatusColor = getWebhookStatusColor;
|
|
26
31
|
exports.isValidCountry = isValidCountry;
|
|
27
32
|
exports.mergeExtraParams = void 0;
|
|
28
33
|
exports.sleep = sleep;
|
|
@@ -218,6 +223,62 @@ function formatLineItemPricing(item, currency, trial, locale = "en") {
|
|
|
218
223
|
quantity
|
|
219
224
|
};
|
|
220
225
|
}
|
|
226
|
+
function getSubscriptionStatusColor(status) {
|
|
227
|
+
switch (status) {
|
|
228
|
+
case "active":
|
|
229
|
+
return "success";
|
|
230
|
+
case "trialing":
|
|
231
|
+
return "primary";
|
|
232
|
+
case "incomplete":
|
|
233
|
+
case "incomplete_expired":
|
|
234
|
+
case "paused":
|
|
235
|
+
return "warning";
|
|
236
|
+
case "past_due":
|
|
237
|
+
case "unpaid":
|
|
238
|
+
return "error";
|
|
239
|
+
case "canceled":
|
|
240
|
+
default:
|
|
241
|
+
return "default";
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
function getPaymentIntentStatusColor(status) {
|
|
245
|
+
switch (status) {
|
|
246
|
+
case "succeeded":
|
|
247
|
+
return "success";
|
|
248
|
+
case "requires_payment_method":
|
|
249
|
+
case "requires_confirmation":
|
|
250
|
+
case "requires_action":
|
|
251
|
+
case "requires_capture":
|
|
252
|
+
return "warning";
|
|
253
|
+
case "canceled":
|
|
254
|
+
case "processing":
|
|
255
|
+
default:
|
|
256
|
+
return "default";
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
function getInvoiceStatusColor(status) {
|
|
260
|
+
switch (status) {
|
|
261
|
+
case "paid":
|
|
262
|
+
return "success";
|
|
263
|
+
case "open":
|
|
264
|
+
return "secondary";
|
|
265
|
+
case "uncollectible":
|
|
266
|
+
return "warning";
|
|
267
|
+
case "draft":
|
|
268
|
+
case "void":
|
|
269
|
+
default:
|
|
270
|
+
return "default";
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
function getWebhookStatusColor(status) {
|
|
274
|
+
switch (status) {
|
|
275
|
+
case "enabled":
|
|
276
|
+
return "success";
|
|
277
|
+
case "disabled":
|
|
278
|
+
default:
|
|
279
|
+
return "default";
|
|
280
|
+
}
|
|
281
|
+
}
|
|
221
282
|
function getCheckoutAmount(items, currency, includeFreeTrial = false, upsell = true) {
|
|
222
283
|
let renew = new _util.BN(0);
|
|
223
284
|
const total = items.reduce((acc, x) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/payment-react",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.126",
|
|
4
4
|
"description": "Reusable react components for payment kit v2",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"@babel/core": "^7.19.3",
|
|
90
90
|
"@babel/preset-env": "^7.19.3",
|
|
91
91
|
"@babel/preset-react": "^7.18.6",
|
|
92
|
-
"@blocklet/payment-types": "1.13.
|
|
92
|
+
"@blocklet/payment-types": "1.13.126",
|
|
93
93
|
"@storybook/addon-essentials": "^7.6.10",
|
|
94
94
|
"@storybook/addon-interactions": "^7.6.10",
|
|
95
95
|
"@storybook/addon-links": "^7.6.10",
|
|
@@ -118,5 +118,5 @@
|
|
|
118
118
|
"vite-plugin-babel": "^1.2.0",
|
|
119
119
|
"vite-plugin-node-polyfills": "^0.19.0"
|
|
120
120
|
},
|
|
121
|
-
"gitHead": "
|
|
121
|
+
"gitHead": "efeb0d3762e61e2a6642330b86a41aa4f0847f36"
|
|
122
122
|
}
|
package/src/api.ts
CHANGED
|
@@ -9,8 +9,8 @@ const api = axios.create();
|
|
|
9
9
|
api.interceptors.request.use(
|
|
10
10
|
(config) => {
|
|
11
11
|
const prefix = getPrefix();
|
|
12
|
+
// 'https://storage.staging.abtnet.io/app/payment-kit/.well-known/service'
|
|
12
13
|
config.baseURL = prefix || '';
|
|
13
|
-
config.timeout = 8000;
|
|
14
14
|
|
|
15
15
|
const livemode = localStorage.getItem('livemode');
|
|
16
16
|
const locale = getLocale(window.blocklet?.languages);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Confirm } from '@arcblock/ux/lib/Dialog';
|
|
2
|
+
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
3
|
+
import { Typography } from '@mui/material';
|
|
4
|
+
import type { EventHandler } from 'react';
|
|
5
|
+
|
|
6
|
+
export default function ConfirmDialog({
|
|
7
|
+
onConfirm,
|
|
8
|
+
onCancel,
|
|
9
|
+
title,
|
|
10
|
+
message,
|
|
11
|
+
loading,
|
|
12
|
+
}: {
|
|
13
|
+
onConfirm: EventHandler<any>;
|
|
14
|
+
onCancel: EventHandler<any>;
|
|
15
|
+
title: string | React.ReactNode;
|
|
16
|
+
message: string | React.ReactNode;
|
|
17
|
+
loading?: boolean;
|
|
18
|
+
}) {
|
|
19
|
+
const { t } = useLocaleContext();
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<Confirm
|
|
23
|
+
open
|
|
24
|
+
title={title}
|
|
25
|
+
onConfirm={onConfirm}
|
|
26
|
+
onCancel={onCancel}
|
|
27
|
+
confirmButton={{
|
|
28
|
+
text: t('common.confirm'),
|
|
29
|
+
props: { color: 'error', size: 'small', variant: 'contained', disabled: !!loading },
|
|
30
|
+
}}
|
|
31
|
+
cancelButton={{ text: t('common.cancel'), props: { color: 'inherit', size: 'small' } }}>
|
|
32
|
+
<Typography>{message}</Typography>
|
|
33
|
+
</Confirm>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
ConfirmDialog.defaultProps = {
|
|
38
|
+
loading: false,
|
|
39
|
+
};
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
ToggleButtonGroup,
|
|
18
18
|
Typography,
|
|
19
19
|
} from '@mui/material';
|
|
20
|
+
import { styled } from '@mui/system';
|
|
20
21
|
import { useSetState } from 'ahooks';
|
|
21
22
|
import { useEffect } from 'react';
|
|
22
23
|
|
|
@@ -83,125 +84,135 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
|
|
|
83
84
|
}
|
|
84
85
|
};
|
|
85
86
|
|
|
87
|
+
const Root = styled(Box)`
|
|
88
|
+
@media (max-width: ${({ theme }) => theme.breakpoints.values.sm}px) {
|
|
89
|
+
.price-table-item {
|
|
90
|
+
width: 90% !important;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
`;
|
|
86
94
|
return (
|
|
87
|
-
<
|
|
88
|
-
direction="column"
|
|
89
|
-
alignItems={alignItems === 'center' ? 'center' : 'flex-start'}
|
|
90
|
-
sx={{
|
|
91
|
-
pt: {
|
|
92
|
-
xs: 4,
|
|
93
|
-
sm: 2,
|
|
94
|
-
},
|
|
95
|
-
gap: {
|
|
96
|
-
xs: 3,
|
|
97
|
-
sm: mode === 'select' ? 3 : 5,
|
|
98
|
-
},
|
|
99
|
-
}}>
|
|
100
|
-
{Object.keys(recurring).length > 1 && (
|
|
101
|
-
<ToggleButtonGroup
|
|
102
|
-
color="primary"
|
|
103
|
-
value={state.interval}
|
|
104
|
-
onChange={(_, value) => {
|
|
105
|
-
if (value !== null) {
|
|
106
|
-
setState({ interval: value });
|
|
107
|
-
}
|
|
108
|
-
}}
|
|
109
|
-
exclusive>
|
|
110
|
-
{Object.keys(recurring).map((x) => (
|
|
111
|
-
<ToggleButton key={x} value={x} sx={{ textTransform: 'capitalize' }}>
|
|
112
|
-
{formatRecurring(recurring[x] as PriceRecurring, true, '', locale)}
|
|
113
|
-
</ToggleButton>
|
|
114
|
-
))}
|
|
115
|
-
</ToggleButtonGroup>
|
|
116
|
-
)}
|
|
95
|
+
<Root>
|
|
117
96
|
<Stack
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
97
|
+
direction="column"
|
|
98
|
+
alignItems={alignItems === 'center' ? 'center' : 'flex-start'}
|
|
99
|
+
sx={{
|
|
100
|
+
pt: {
|
|
101
|
+
xs: 4,
|
|
102
|
+
sm: 2,
|
|
103
|
+
},
|
|
104
|
+
gap: {
|
|
105
|
+
xs: 3,
|
|
106
|
+
sm: mode === 'select' ? 3 : 5,
|
|
107
|
+
},
|
|
108
|
+
}}>
|
|
109
|
+
{Object.keys(recurring).length > 1 && (
|
|
110
|
+
<ToggleButtonGroup
|
|
111
|
+
color="primary"
|
|
112
|
+
value={state.interval}
|
|
113
|
+
onChange={(_, value) => {
|
|
114
|
+
if (value !== null) {
|
|
115
|
+
setState({ interval: value });
|
|
116
|
+
}
|
|
117
|
+
}}
|
|
118
|
+
exclusive>
|
|
119
|
+
{Object.keys(recurring).map((x) => (
|
|
120
|
+
<ToggleButton key={x} value={x} sx={{ textTransform: 'capitalize' }}>
|
|
121
|
+
{formatRecurring(recurring[x] as PriceRecurring, true, '', locale)}
|
|
122
|
+
</ToggleButton>
|
|
123
|
+
))}
|
|
124
|
+
</ToggleButtonGroup>
|
|
125
|
+
)}
|
|
126
|
+
<Stack
|
|
127
|
+
flexWrap="wrap"
|
|
128
|
+
direction="row"
|
|
129
|
+
gap="calc(10px + 3%)"
|
|
130
|
+
justifyContent={alignItems === 'center' ? 'center' : 'flex-start'}>
|
|
131
|
+
{grouped[state.interval as string]?.map(
|
|
132
|
+
(x: TPricingTableItem & { is_selected?: boolean; is_disabled?: boolean }) => {
|
|
133
|
+
let action = x.subscription_data?.trial_period_days
|
|
134
|
+
? t('payment.checkout.try')
|
|
135
|
+
: t('payment.checkout.subscription');
|
|
136
|
+
if (mode === 'select') {
|
|
137
|
+
action = x.is_selected ? t('payment.checkout.selected') : t('payment.checkout.select');
|
|
138
|
+
}
|
|
130
139
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
140
|
+
return (
|
|
141
|
+
<Fade key={x.price_id} in>
|
|
142
|
+
<Stack
|
|
143
|
+
padding={4}
|
|
144
|
+
spacing={2}
|
|
145
|
+
direction="column"
|
|
146
|
+
alignItems="center"
|
|
147
|
+
className="price-table-item"
|
|
148
|
+
justifyContent="center"
|
|
149
|
+
sx={{
|
|
150
|
+
width: 0.9 / grouped[state.interval as string].length,
|
|
151
|
+
cursor: 'pointer',
|
|
152
|
+
borderWidth: '1px',
|
|
153
|
+
borderStyle: 'solid',
|
|
154
|
+
borderColor: mode === 'select' && x.is_selected ? 'primary.main' : '#eee',
|
|
155
|
+
borderRadius: 1,
|
|
156
|
+
transition: 'border-color 0.3s ease 0s, box-shadow 0.3s ease 0s',
|
|
157
|
+
boxShadow: '0 4px 8px rgba(0, 0, 0, 20%)',
|
|
158
|
+
'&:hover': {
|
|
159
|
+
borderColor: mode === 'select' && x.is_selected ? 'primary.main' : '#ddd',
|
|
160
|
+
boxShadow: '0 8px 16px rgba(0, 0, 0, 20%)',
|
|
161
|
+
},
|
|
162
|
+
}}>
|
|
163
|
+
<Box textAlign="center">
|
|
164
|
+
<Stack direction="row" alignItems="center" spacing={1}>
|
|
165
|
+
<Typography variant="h5" color="text.primary" fontWeight={600}>
|
|
166
|
+
{x.product.name}
|
|
167
|
+
</Typography>
|
|
168
|
+
{x.is_highlight && <Chip label={x.highlight_text} color="default" size="small" />}
|
|
169
|
+
</Stack>
|
|
170
|
+
<Typography color="text.secondary">{x.product.description}</Typography>
|
|
171
|
+
</Box>
|
|
153
172
|
<Stack direction="row" alignItems="center" spacing={1}>
|
|
154
|
-
<
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
<Stack direction="column" alignItems="flex-start">
|
|
164
|
-
<Typography component="span" color="text.secondary" fontSize="0.8rem">
|
|
165
|
-
{t('payment.checkout.per')}
|
|
166
|
-
</Typography>
|
|
167
|
-
<Typography component="span" color="text.secondary" fontSize="0.8rem">
|
|
168
|
-
{formatRecurring(x.price.recurring as PriceRecurring, false, '', locale)}
|
|
169
|
-
</Typography>
|
|
173
|
+
<Amount amount={formatPriceAmount(x.price, table.currency, x.product.unit_label)} />
|
|
174
|
+
<Stack direction="column" alignItems="flex-start">
|
|
175
|
+
<Typography component="span" color="text.secondary" fontSize="0.8rem">
|
|
176
|
+
{t('payment.checkout.per')}
|
|
177
|
+
</Typography>
|
|
178
|
+
<Typography component="span" color="text.secondary" fontSize="0.8rem">
|
|
179
|
+
{formatRecurring(x.price.recurring as PriceRecurring, false, '', locale)}
|
|
180
|
+
</Typography>
|
|
181
|
+
</Stack>
|
|
170
182
|
</Stack>
|
|
183
|
+
<LoadingButton
|
|
184
|
+
fullWidth
|
|
185
|
+
size="large"
|
|
186
|
+
variant={x.is_highlight || x.is_selected ? 'contained' : 'outlined'}
|
|
187
|
+
color={x.is_highlight || x.is_selected ? 'primary' : 'info'}
|
|
188
|
+
sx={{ fontSize: '1.2rem' }}
|
|
189
|
+
loading={state.loading === x.price_id}
|
|
190
|
+
disabled={x.is_disabled}
|
|
191
|
+
onClick={() => handleSelect(x.price_id)}>
|
|
192
|
+
{action}
|
|
193
|
+
</LoadingButton>
|
|
194
|
+
{x.product.features.length > 0 && (
|
|
195
|
+
<Box>
|
|
196
|
+
<Typography>{t('payment.checkout.include')}</Typography>
|
|
197
|
+
<List dense>
|
|
198
|
+
{x.product.features.map((f: any) => (
|
|
199
|
+
<ListItem key={f.name} disableGutters disablePadding>
|
|
200
|
+
<ListItemIcon sx={{ minWidth: 25 }}>
|
|
201
|
+
<CheckOutlined color="success" fontSize="small" />
|
|
202
|
+
</ListItemIcon>
|
|
203
|
+
<ListItemText primary={f.name} />
|
|
204
|
+
</ListItem>
|
|
205
|
+
))}
|
|
206
|
+
</List>
|
|
207
|
+
</Box>
|
|
208
|
+
)}
|
|
171
209
|
</Stack>
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
color={x.is_highlight || x.is_selected ? 'primary' : 'info'}
|
|
178
|
-
sx={{ fontSize: '1.2rem' }}
|
|
179
|
-
loading={state.loading === x.price_id}
|
|
180
|
-
disabled={x.is_disabled}
|
|
181
|
-
onClick={() => handleSelect(x.price_id)}>
|
|
182
|
-
{action}
|
|
183
|
-
</LoadingButton>
|
|
184
|
-
{x.product.features.length > 0 && (
|
|
185
|
-
<Box>
|
|
186
|
-
<Typography>{t('payment.checkout.include')}</Typography>
|
|
187
|
-
<List dense>
|
|
188
|
-
{x.product.features.map((f: any) => (
|
|
189
|
-
<ListItem key={f.name} disableGutters disablePadding>
|
|
190
|
-
<ListItemIcon sx={{ minWidth: 25 }}>
|
|
191
|
-
<CheckOutlined color="success" fontSize="small" />
|
|
192
|
-
</ListItemIcon>
|
|
193
|
-
<ListItemText primary={f.name} />
|
|
194
|
-
</ListItem>
|
|
195
|
-
))}
|
|
196
|
-
</List>
|
|
197
|
-
</Box>
|
|
198
|
-
)}
|
|
199
|
-
</Stack>
|
|
200
|
-
</Fade>
|
|
201
|
-
);
|
|
202
|
-
}
|
|
203
|
-
)}
|
|
210
|
+
</Fade>
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
)}
|
|
214
|
+
</Stack>
|
|
204
215
|
</Stack>
|
|
205
|
-
</
|
|
216
|
+
</Root>
|
|
206
217
|
);
|
|
207
218
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import api from './api';
|
|
2
2
|
import CheckoutForm from './checkout/form';
|
|
3
3
|
import CheckoutTable from './checkout/table';
|
|
4
|
+
import ConfirmDialog from './components/confirm';
|
|
4
5
|
import FormInput from './components/input';
|
|
5
6
|
import Livemode from './components/livemode';
|
|
6
7
|
import PricingTable from './components/pricing-table';
|
|
@@ -11,6 +12,8 @@ import Amount from './payment/amount';
|
|
|
11
12
|
import PhoneInput from './payment/form/phone';
|
|
12
13
|
import Payment from './payment/index';
|
|
13
14
|
import ProductSkeleton from './payment/product-skeleton';
|
|
15
|
+
import CustomerInvoiceList from './portal/invoice/list';
|
|
16
|
+
import CustomerPaymentList from './portal/payment/list';
|
|
14
17
|
|
|
15
18
|
export * from './util';
|
|
16
19
|
export * from './contexts/payment';
|
|
@@ -25,10 +28,13 @@ export {
|
|
|
25
28
|
Status,
|
|
26
29
|
Livemode,
|
|
27
30
|
Switch,
|
|
31
|
+
ConfirmDialog,
|
|
28
32
|
CheckoutForm,
|
|
29
33
|
CheckoutTable,
|
|
30
34
|
Payment,
|
|
31
35
|
PricingTable,
|
|
32
36
|
ProductSkeleton,
|
|
33
37
|
Amount,
|
|
38
|
+
CustomerInvoiceList,
|
|
39
|
+
CustomerPaymentList,
|
|
34
40
|
};
|
package/src/locales/en.tsx
CHANGED
|
@@ -150,6 +150,7 @@ export default flat({
|
|
|
150
150
|
},
|
|
151
151
|
},
|
|
152
152
|
customer: {
|
|
153
|
+
payments: 'Payment History',
|
|
153
154
|
invoices: 'Invoice History',
|
|
154
155
|
details: 'Billing Details',
|
|
155
156
|
update: 'Update Information',
|
|
@@ -206,7 +207,10 @@ export default flat({
|
|
|
206
207
|
pay: 'Pay this invoice',
|
|
207
208
|
paySuccess: 'You have successfully paid the invoice',
|
|
208
209
|
payError: 'Failed to paid the invoice',
|
|
209
|
-
empty: 'Seems you do not have any
|
|
210
|
+
empty: 'Seems you do not have any invoice here',
|
|
211
|
+
},
|
|
212
|
+
payment: {
|
|
213
|
+
empty: 'Seems you do not have any payment here',
|
|
210
214
|
},
|
|
211
215
|
subscriptions: {
|
|
212
216
|
title: 'Manage subscriptions',
|
package/src/locales/zh.tsx
CHANGED
|
@@ -147,6 +147,7 @@ export default flat({
|
|
|
147
147
|
},
|
|
148
148
|
},
|
|
149
149
|
customer: {
|
|
150
|
+
payments: '支付历史',
|
|
150
151
|
invoices: '发票历史',
|
|
151
152
|
details: '计费详情',
|
|
152
153
|
update: '更新客户信息',
|
|
@@ -202,6 +203,9 @@ export default flat({
|
|
|
202
203
|
pay: '支付此发票',
|
|
203
204
|
paySuccess: '支付成功',
|
|
204
205
|
payError: '支付失败',
|
|
206
|
+
empty: '你没有任何发票',
|
|
207
|
+
},
|
|
208
|
+
payment: {
|
|
205
209
|
empty: '你没有任何支付',
|
|
206
210
|
},
|
|
207
211
|
subscriptions: {
|
package/src/payment/index.tsx
CHANGED
|
@@ -350,18 +350,18 @@ export const Root = styled(Box)<{ mode: LiteralUnion<'standalone' | 'inline' | '
|
|
|
350
350
|
}
|
|
351
351
|
|
|
352
352
|
.cko-payment-card-unselect {
|
|
353
|
-
border: 2px solid #
|
|
353
|
+
border: 2px solid #ddd;
|
|
354
354
|
padding: 5px 10px;
|
|
355
355
|
margin: 5px 0;
|
|
356
356
|
cursor: pointer;
|
|
357
357
|
}
|
|
358
358
|
|
|
359
359
|
.cko-payment-card:nth-child(odd) {
|
|
360
|
-
margin-right:
|
|
360
|
+
margin-right: 16px;
|
|
361
361
|
}
|
|
362
362
|
|
|
363
363
|
.cko-payment-card-unselect:nth-child(odd) {
|
|
364
|
-
margin-right:
|
|
364
|
+
margin-right: 16px;
|
|
365
365
|
}
|
|
366
366
|
|
|
367
367
|
.cko-payment-card::after {
|