@blocklet/payment-react 1.13.130 → 1.13.131
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/components/blockchain/tx.d.ts +13 -0
- package/es/components/blockchain/tx.js +52 -0
- package/es/history/invoice/list.js +3 -2
- package/es/history/mini-invoice/list.js +33 -29
- package/es/history/payment/list.js +10 -1
- package/es/index.d.ts +2 -1
- package/es/index.js +3 -1
- package/es/locales/en.js +3 -3
- package/es/locales/zh.js +3 -3
- package/es/util.js +5 -2
- package/lib/components/blockchain/tx.d.ts +13 -0
- package/lib/components/blockchain/tx.js +82 -0
- package/lib/history/invoice/list.js +2 -1
- package/lib/history/mini-invoice/list.js +30 -32
- package/lib/history/payment/list.js +12 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.js +8 -0
- package/lib/locales/en.js +3 -3
- package/lib/locales/zh.js +3 -3
- package/lib/util.js +5 -2
- package/package.json +3 -3
- package/src/components/blockchain/tx.tsx +77 -0
- package/src/history/invoice/list.tsx +3 -2
- package/src/history/mini-invoice/list.tsx +37 -33
- package/src/history/payment/list.tsx +11 -1
- package/src/index.ts +2 -0
- package/src/locales/en.tsx +3 -3
- package/src/locales/zh.tsx +3 -3
- package/src/util.ts +5 -2
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { PaymentDetails, TPaymentMethod } from '@blocklet/payment-types';
|
|
3
|
+
declare function TxLink(props: {
|
|
4
|
+
details: PaymentDetails;
|
|
5
|
+
method: TPaymentMethod;
|
|
6
|
+
mode?: 'customer' | 'dashboard';
|
|
7
|
+
}): import("react").JSX.Element;
|
|
8
|
+
declare namespace TxLink {
|
|
9
|
+
var defaultProps: {
|
|
10
|
+
mode: string;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export default TxLink;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { OpenInNewOutlined } from "@mui/icons-material";
|
|
3
|
+
import { Link, Stack, Typography } from "@mui/material";
|
|
4
|
+
import { joinURL } from "ufo";
|
|
5
|
+
const getTxLink = (method, details) => {
|
|
6
|
+
if (method.type === "arcblock" && details.arcblock?.tx_hash) {
|
|
7
|
+
return {
|
|
8
|
+
link: joinURL(method.settings.arcblock?.explorer_host, "/txs", details.arcblock?.tx_hash),
|
|
9
|
+
text: details.arcblock?.tx_hash
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
if (method.type === "bitcoin" && details.bitcoin?.tx_hash) {
|
|
13
|
+
return {
|
|
14
|
+
link: joinURL(method.settings.bitcoin?.explorer_host, "/tx", details.bitcoin?.tx_hash),
|
|
15
|
+
text: details.bitcoin?.tx_hash
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
if (method.type === "ethereum" && details.ethereum?.tx_hash) {
|
|
19
|
+
return {
|
|
20
|
+
link: joinURL(method.settings.ethereum?.explorer_host, "/tx", details.ethereum?.tx_hash),
|
|
21
|
+
text: details.ethereum?.tx_hash
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
if (method.type === "stripe") {
|
|
25
|
+
const dashboard = method.livemode ? "https://dashboard.stripe.com" : "https://dashboard.stripe.com/test";
|
|
26
|
+
return {
|
|
27
|
+
link: joinURL(
|
|
28
|
+
method.settings.stripe?.dashboard || dashboard,
|
|
29
|
+
"payments",
|
|
30
|
+
details.stripe?.payment_intent_id
|
|
31
|
+
),
|
|
32
|
+
text: details.stripe?.payment_intent_id
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
return { text: "N/A", link: "" };
|
|
36
|
+
};
|
|
37
|
+
TxLink.defaultProps = {
|
|
38
|
+
mode: "dashboard"
|
|
39
|
+
};
|
|
40
|
+
export default function TxLink(props) {
|
|
41
|
+
if (!props.details || props.mode === "customer" && props.method.type === "stripe") {
|
|
42
|
+
return /* @__PURE__ */ jsx(Typography, { component: "small", color: "text.secondary", children: "None" });
|
|
43
|
+
}
|
|
44
|
+
const { text, link } = getTxLink(props.method, props.details);
|
|
45
|
+
if (link) {
|
|
46
|
+
return /* @__PURE__ */ jsx(Link, { href: link, target: "_blank", rel: "noopener noreferrer", children: /* @__PURE__ */ jsxs(Stack, { component: "span", direction: "row", alignItems: "center", spacing: 1, children: [
|
|
47
|
+
/* @__PURE__ */ jsx(Typography, { component: "span", color: "primary", children: text.length > 40 ? [text.slice(0, 8), text.slice(-8)].join("...") : text }),
|
|
48
|
+
/* @__PURE__ */ jsx(OpenInNewOutlined, { fontSize: "small" })
|
|
49
|
+
] }) });
|
|
50
|
+
}
|
|
51
|
+
return /* @__PURE__ */ jsx(Typography, { component: "small", color: "text.secondary", children: "None" });
|
|
52
|
+
}
|
|
@@ -3,9 +3,10 @@ import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
|
|
|
3
3
|
import { Box, Button, CircularProgress, Stack, Typography } from "@mui/material";
|
|
4
4
|
import { fromUnitToToken } from "@ocap/util";
|
|
5
5
|
import { useInfiniteScroll } from "ahooks";
|
|
6
|
+
import { joinURL } from "ufo";
|
|
6
7
|
import api from "../../api.js";
|
|
7
8
|
import Status from "../../components/status.js";
|
|
8
|
-
import { formatToDate, getInvoiceStatusColor } from "../../util.js";
|
|
9
|
+
import { formatToDate, getInvoiceStatusColor, getPrefix } from "../../util.js";
|
|
9
10
|
const groupByDate = (items) => {
|
|
10
11
|
const grouped = {};
|
|
11
12
|
items.forEach((item) => {
|
|
@@ -64,7 +65,7 @@ export default function CustomerInvoiceList({ customer_id, subscription_id }) {
|
|
|
64
65
|
},
|
|
65
66
|
flexWrap: "nowrap",
|
|
66
67
|
children: [
|
|
67
|
-
/* @__PURE__ */ jsx(Box, { flex: 3, children: /* @__PURE__ */ jsx("a", { href: `/customer/invoice/${invoice.id}
|
|
68
|
+
/* @__PURE__ */ jsx(Box, { flex: 3, children: /* @__PURE__ */ jsx("a", { href: joinURL(window.location.origin, getPrefix(), `/customer/invoice/${invoice.id}`), children: /* @__PURE__ */ jsx(Typography, { component: "span", children: invoice.number }) }) }),
|
|
68
69
|
/* @__PURE__ */ jsx(Box, { flex: 3, children: /* @__PURE__ */ jsx(Typography, { children: formatToDate(invoice.created_at) }) }),
|
|
69
70
|
/* @__PURE__ */ jsx(Box, { flex: 2, children: /* @__PURE__ */ jsxs(Typography, { textAlign: "right", children: [
|
|
70
71
|
fromUnitToToken(invoice.total, invoice.paymentCurrency.decimal),
|
|
@@ -3,6 +3,7 @@ import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
|
|
|
3
3
|
import { Box, Button, CircularProgress, Divider, List, ListItem, ListSubheader, Typography } from "@mui/material";
|
|
4
4
|
import { fromUnitToToken } from "@ocap/util";
|
|
5
5
|
import { useRequest } from "ahooks";
|
|
6
|
+
import { joinURL } from "ufo";
|
|
6
7
|
import api from "../../api.js";
|
|
7
8
|
import Status from "../../components/status.js";
|
|
8
9
|
import {
|
|
@@ -10,6 +11,7 @@ import {
|
|
|
10
11
|
formatTime,
|
|
11
12
|
formatToDate,
|
|
12
13
|
getInvoiceStatusColor,
|
|
14
|
+
getPrefix,
|
|
13
15
|
getSubscriptionStatusColor
|
|
14
16
|
} from "../../util.js";
|
|
15
17
|
const fetchInvoiceData = (params = {}) => {
|
|
@@ -29,12 +31,10 @@ export default function MiniInvoiceList() {
|
|
|
29
31
|
const { data } = useRequest(
|
|
30
32
|
() => fetchInvoiceData({ page: 1, pageSize: 10, status: "open,paid,uncollectible", subscription_id: subscriptionId })
|
|
31
33
|
);
|
|
32
|
-
if (!
|
|
34
|
+
if (!subscription || !data) {
|
|
33
35
|
return /* @__PURE__ */ jsx(Position, { children: /* @__PURE__ */ jsx(CircularProgress, {}) });
|
|
34
36
|
}
|
|
35
|
-
|
|
36
|
-
return /* @__PURE__ */ jsx(Position, { children: /* @__PURE__ */ jsx(Typography, { color: "text.secondary", children: t("payment.customer.invoice.empty") }) });
|
|
37
|
-
}
|
|
37
|
+
const invoices = data.list || [];
|
|
38
38
|
const infoList = [
|
|
39
39
|
{
|
|
40
40
|
name: t("payment.customer.subscriptions.plan"),
|
|
@@ -43,8 +43,10 @@ export default function MiniInvoiceList() {
|
|
|
43
43
|
{
|
|
44
44
|
name: t("common.status"),
|
|
45
45
|
value: /* @__PURE__ */ jsx(Status, { label: subscription.status, color: getSubscriptionStatusColor(subscription.status) })
|
|
46
|
-
}
|
|
47
|
-
|
|
46
|
+
}
|
|
47
|
+
];
|
|
48
|
+
if (subscription.status === "active" || subscription.status === "trailing") {
|
|
49
|
+
infoList.push({
|
|
48
50
|
name: t("payment.customer.subscriptions.nextInvoice"),
|
|
49
51
|
value: /* @__PURE__ */ jsx(
|
|
50
52
|
Typography,
|
|
@@ -57,13 +59,14 @@ export default function MiniInvoiceList() {
|
|
|
57
59
|
children: formatTime(subscription.current_period_end * 1e3)
|
|
58
60
|
}
|
|
59
61
|
)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
+
});
|
|
63
|
+
}
|
|
62
64
|
return /* @__PURE__ */ jsxs(Position, { children: [
|
|
63
65
|
/* @__PURE__ */ jsx(Typography, { title: t("payment.checkout.subscription") }),
|
|
64
66
|
/* @__PURE__ */ jsxs(
|
|
65
67
|
Box,
|
|
66
68
|
{
|
|
69
|
+
className: "mini-invoice-wrap",
|
|
67
70
|
sx: {
|
|
68
71
|
display: "flex",
|
|
69
72
|
flexDirection: "column",
|
|
@@ -82,28 +85,30 @@ export default function MiniInvoiceList() {
|
|
|
82
85
|
] }, name);
|
|
83
86
|
}) }) }),
|
|
84
87
|
/* @__PURE__ */ jsx(Divider, {}),
|
|
85
|
-
/* @__PURE__ */ jsx(Box, { sx: { marginTop: "12px" }, children: /* @__PURE__ */ jsxs(
|
|
86
|
-
|
|
88
|
+
/* @__PURE__ */ jsx(Box, { sx: { marginTop: "12px", flex: 1 }, children: /* @__PURE__ */ jsxs(List, { sx: { overflow: "auto" }, className: "mini-invoice-list", children: [
|
|
89
|
+
/* @__PURE__ */ jsx(ListSubheader, { disableGutters: true, sx: { padding: 0 }, children: /* @__PURE__ */ jsx(Typography, { component: "h2", variant: "h6", fontSize: "16px", children: t("payment.customer.invoices") }) }),
|
|
90
|
+
invoices.length === 0 ? /* @__PURE__ */ jsx(Typography, { color: "text.secondary", children: t("payment.customer.invoice.empty") }) : invoices.map((item) => {
|
|
91
|
+
return /* @__PURE__ */ jsxs(ListItem, { disableGutters: true, sx: { display: "flex", justifyContent: "space-between" }, children: [
|
|
92
|
+
/* @__PURE__ */ jsx(Typography, { component: "span", sx: { flex: 3 }, children: formatToDate(item.created_at) }),
|
|
93
|
+
/* @__PURE__ */ jsxs(Typography, { component: "span", sx: { flex: 1, textAlign: "right" }, children: [
|
|
94
|
+
fromUnitToToken(item.total, item.paymentCurrency.decimal),
|
|
95
|
+
"\xA0",
|
|
96
|
+
item.paymentCurrency.symbol
|
|
97
|
+
] }),
|
|
98
|
+
/* @__PURE__ */ jsx(Typography, { component: "span", sx: { flex: 2, textAlign: "right" }, children: /* @__PURE__ */ jsx(Status, { label: item.status, color: getInvoiceStatusColor(item.status), sx: { flex: 2 } }) })
|
|
99
|
+
] }, item.id);
|
|
100
|
+
})
|
|
101
|
+
] }) }),
|
|
102
|
+
/* @__PURE__ */ jsx(
|
|
103
|
+
Button,
|
|
87
104
|
{
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
return /* @__PURE__ */ jsxs(ListItem, { disableGutters: true, sx: { display: "flex", justifyContent: "space-between" }, children: [
|
|
94
|
-
/* @__PURE__ */ jsx(Typography, { component: "span", sx: { flex: 3 }, children: formatToDate(item.created_at) }),
|
|
95
|
-
/* @__PURE__ */ jsxs(Typography, { component: "span", sx: { flex: 1 }, children: [
|
|
96
|
-
fromUnitToToken(item.total, item.paymentCurrency.decimal),
|
|
97
|
-
"\xA0",
|
|
98
|
-
item.paymentCurrency.symbol
|
|
99
|
-
] }),
|
|
100
|
-
/* @__PURE__ */ jsx(Typography, { component: "span", sx: { flex: 2, textAlign: "right" }, children: /* @__PURE__ */ jsx(Status, { label: item.status, color: getInvoiceStatusColor(item.status), sx: { flex: 2 } }) })
|
|
101
|
-
] }, item.id);
|
|
102
|
-
})
|
|
103
|
-
]
|
|
105
|
+
target: "_blank",
|
|
106
|
+
variant: "contained",
|
|
107
|
+
sx: { marginTop: "10px 0", width: "100%", color: "#fff!important" },
|
|
108
|
+
href: joinURL(window.location.origin, getPrefix(), `/customer/subscription/${subscription.id}`),
|
|
109
|
+
children: t("payment.customer.subscriptions.title")
|
|
104
110
|
}
|
|
105
|
-
)
|
|
106
|
-
/* @__PURE__ */ jsx(Button, { target: "_top", variant: "contained", sx: { marginTop: "10px 0", width: "100%" }, href: "", children: t("payment.customer.subscriptions.title") })
|
|
111
|
+
)
|
|
107
112
|
]
|
|
108
113
|
}
|
|
109
114
|
)
|
|
@@ -115,7 +120,6 @@ function Position({ children }) {
|
|
|
115
120
|
{
|
|
116
121
|
className: "mini-invoice-box",
|
|
117
122
|
sx: {
|
|
118
|
-
justifyContent: "center",
|
|
119
123
|
padding: "8px",
|
|
120
124
|
width: "100%",
|
|
121
125
|
maxWidth: "500px",
|
|
@@ -4,6 +4,7 @@ import { Box, Button, CircularProgress, Stack, Typography } from "@mui/material"
|
|
|
4
4
|
import { fromUnitToToken } from "@ocap/util";
|
|
5
5
|
import { useInfiniteScroll } from "ahooks";
|
|
6
6
|
import api from "../../api.js";
|
|
7
|
+
import TxLink from "../../components/blockchain/tx.js";
|
|
7
8
|
import Status from "../../components/status.js";
|
|
8
9
|
import { formatToDate, getPaymentIntentStatusColor } from "../../util.js";
|
|
9
10
|
const groupByDate = (items) => {
|
|
@@ -69,7 +70,15 @@ export default function CustomerPaymentList({ customer_id }) {
|
|
|
69
70
|
item.paymentCurrency.symbol
|
|
70
71
|
] }) }),
|
|
71
72
|
/* @__PURE__ */ jsx(Box, { flex: 3, children: /* @__PURE__ */ jsx(Status, { label: item.status, color: getPaymentIntentStatusColor(item.status) }) }),
|
|
72
|
-
/* @__PURE__ */ jsx(Box, { flex:
|
|
73
|
+
/* @__PURE__ */ jsx(Box, { flex: 3, children: /* @__PURE__ */ jsx(Typography, { children: item.description || item.id }) }),
|
|
74
|
+
/* @__PURE__ */ jsx(Box, { flex: 3, sx: { minWidth: "220px" }, children: item.payment_details?.arcblock?.tx_hash && /* @__PURE__ */ jsx(
|
|
75
|
+
TxLink,
|
|
76
|
+
{
|
|
77
|
+
details: item.payment_details,
|
|
78
|
+
method: item.paymentMethod,
|
|
79
|
+
mode: "customer"
|
|
80
|
+
}
|
|
81
|
+
) })
|
|
73
82
|
]
|
|
74
83
|
},
|
|
75
84
|
item.id
|
package/es/index.d.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 TxLink from './components/blockchain/tx';
|
|
4
5
|
import ConfirmDialog from './components/confirm';
|
|
5
6
|
import FormInput from './components/input';
|
|
6
7
|
import Livemode from './components/livemode';
|
|
@@ -18,4 +19,4 @@ import ProductSkeleton from './payment/product-skeleton';
|
|
|
18
19
|
export * from './util';
|
|
19
20
|
export * from './contexts/payment';
|
|
20
21
|
export { translations, createTranslator } from './locales';
|
|
21
|
-
export { api, dayjs, FormInput, PhoneInput, Status, Livemode, Switch, ConfirmDialog, CheckoutForm, CheckoutTable, Payment, PricingTable, ProductSkeleton, Amount, CustomerInvoiceList, CustomerPaymentList, MiniInvoiceList, };
|
|
22
|
+
export { api, dayjs, FormInput, PhoneInput, Status, Livemode, Switch, ConfirmDialog, CheckoutForm, CheckoutTable, Payment, PricingTable, ProductSkeleton, Amount, CustomerInvoiceList, CustomerPaymentList, MiniInvoiceList, TxLink, };
|
package/es/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import api from "./api.js";
|
|
2
2
|
import CheckoutForm from "./checkout/form.js";
|
|
3
3
|
import CheckoutTable from "./checkout/table.js";
|
|
4
|
+
import TxLink from "./components/blockchain/tx.js";
|
|
4
5
|
import ConfirmDialog from "./components/confirm.js";
|
|
5
6
|
import FormInput from "./components/input.js";
|
|
6
7
|
import Livemode from "./components/livemode.js";
|
|
@@ -35,5 +36,6 @@ export {
|
|
|
35
36
|
Amount,
|
|
36
37
|
CustomerInvoiceList,
|
|
37
38
|
CustomerPaymentList,
|
|
38
|
-
MiniInvoiceList
|
|
39
|
+
MiniInvoiceList,
|
|
40
|
+
TxLink
|
|
39
41
|
};
|
package/es/locales/en.js
CHANGED
|
@@ -202,17 +202,17 @@ export default flat({
|
|
|
202
202
|
pay: "Pay this invoice",
|
|
203
203
|
paySuccess: "You have successfully paid the invoice",
|
|
204
204
|
payError: "Failed to paid the invoice",
|
|
205
|
-
empty: "
|
|
205
|
+
empty: "There are no invoices here"
|
|
206
206
|
},
|
|
207
207
|
payment: {
|
|
208
|
-
empty: "
|
|
208
|
+
empty: "There are no payments here"
|
|
209
209
|
},
|
|
210
210
|
subscriptions: {
|
|
211
211
|
plan: "Plan",
|
|
212
212
|
nextInvoice: "Next Invoice",
|
|
213
213
|
title: "Manage subscriptions",
|
|
214
214
|
current: "Current subscription",
|
|
215
|
-
empty: "
|
|
215
|
+
empty: "There are no subscriptions here"
|
|
216
216
|
}
|
|
217
217
|
}
|
|
218
218
|
}
|
package/es/locales/zh.js
CHANGED
|
@@ -202,17 +202,17 @@ export default flat({
|
|
|
202
202
|
pay: "\u652F\u4ED8\u6B64\u53D1\u7968",
|
|
203
203
|
paySuccess: "\u652F\u4ED8\u6210\u529F",
|
|
204
204
|
payError: "\u652F\u4ED8\u5931\u8D25",
|
|
205
|
-
empty: "\
|
|
205
|
+
empty: "\u6CA1\u6709\u4EFB\u4F55\u53D1\u7968"
|
|
206
206
|
},
|
|
207
207
|
payment: {
|
|
208
|
-
empty: "\
|
|
208
|
+
empty: "\u6CA1\u6709\u4EFB\u4F55\u652F\u4ED8"
|
|
209
209
|
},
|
|
210
210
|
subscriptions: {
|
|
211
211
|
plan: "\u8BA2\u9605",
|
|
212
212
|
nextInvoice: "\u4E0B\u4E00\u5F20\u53D1\u7968",
|
|
213
213
|
title: "\u8BA2\u9605\u7BA1\u7406",
|
|
214
214
|
current: "\u5F53\u524D\u8BA2\u9605",
|
|
215
|
-
empty: "\
|
|
215
|
+
empty: "\u6CA1\u6709\u4EFB\u4F55\u8BA2\u9605"
|
|
216
216
|
}
|
|
217
217
|
}
|
|
218
218
|
}
|
package/es/util.js
CHANGED
|
@@ -226,9 +226,12 @@ export function getWebhookStatusColor(status) {
|
|
|
226
226
|
}
|
|
227
227
|
export function getCheckoutAmount(items, currency, includeFreeTrial = false, upsell = true) {
|
|
228
228
|
let renew = new BN(0);
|
|
229
|
-
const total = items.
|
|
229
|
+
const total = items.filter((x) => {
|
|
230
230
|
const price = upsell ? x.upsell_price || x.price : x.price;
|
|
231
|
-
|
|
231
|
+
return price != null;
|
|
232
|
+
}).reduce((acc, x) => {
|
|
233
|
+
const price = upsell ? x.upsell_price || x.price : x.price;
|
|
234
|
+
if (price?.type === "recurring") {
|
|
232
235
|
renew = renew.add(new BN(getPriceUintAmountByCurrency(price, currency)).mul(new BN(x.quantity)));
|
|
233
236
|
if (includeFreeTrial) {
|
|
234
237
|
return acc;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { PaymentDetails, TPaymentMethod } from '@blocklet/payment-types';
|
|
3
|
+
declare function TxLink(props: {
|
|
4
|
+
details: PaymentDetails;
|
|
5
|
+
method: TPaymentMethod;
|
|
6
|
+
mode?: 'customer' | 'dashboard';
|
|
7
|
+
}): import("react").JSX.Element;
|
|
8
|
+
declare namespace TxLink {
|
|
9
|
+
var defaultProps: {
|
|
10
|
+
mode: string;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export default TxLink;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
module.exports = TxLink;
|
|
7
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
8
|
+
var _iconsMaterial = require("@mui/icons-material");
|
|
9
|
+
var _material = require("@mui/material");
|
|
10
|
+
var _ufo = require("ufo");
|
|
11
|
+
const getTxLink = (method, details) => {
|
|
12
|
+
if (method.type === "arcblock" && details.arcblock?.tx_hash) {
|
|
13
|
+
return {
|
|
14
|
+
link: (0, _ufo.joinURL)(method.settings.arcblock?.explorer_host, "/txs", details.arcblock?.tx_hash),
|
|
15
|
+
text: details.arcblock?.tx_hash
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
if (method.type === "bitcoin" && details.bitcoin?.tx_hash) {
|
|
19
|
+
return {
|
|
20
|
+
link: (0, _ufo.joinURL)(method.settings.bitcoin?.explorer_host, "/tx", details.bitcoin?.tx_hash),
|
|
21
|
+
text: details.bitcoin?.tx_hash
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
if (method.type === "ethereum" && details.ethereum?.tx_hash) {
|
|
25
|
+
return {
|
|
26
|
+
link: (0, _ufo.joinURL)(method.settings.ethereum?.explorer_host, "/tx", details.ethereum?.tx_hash),
|
|
27
|
+
text: details.ethereum?.tx_hash
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
if (method.type === "stripe") {
|
|
31
|
+
const dashboard = method.livemode ? "https://dashboard.stripe.com" : "https://dashboard.stripe.com/test";
|
|
32
|
+
return {
|
|
33
|
+
link: (0, _ufo.joinURL)(method.settings.stripe?.dashboard || dashboard, "payments", details.stripe?.payment_intent_id),
|
|
34
|
+
text: details.stripe?.payment_intent_id
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
text: "N/A",
|
|
39
|
+
link: ""
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
TxLink.defaultProps = {
|
|
43
|
+
mode: "dashboard"
|
|
44
|
+
};
|
|
45
|
+
function TxLink(props) {
|
|
46
|
+
if (!props.details || props.mode === "customer" && props.method.type === "stripe") {
|
|
47
|
+
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
48
|
+
component: "small",
|
|
49
|
+
color: "text.secondary",
|
|
50
|
+
children: "None"
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
const {
|
|
54
|
+
text,
|
|
55
|
+
link
|
|
56
|
+
} = getTxLink(props.method, props.details);
|
|
57
|
+
if (link) {
|
|
58
|
+
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Link, {
|
|
59
|
+
href: link,
|
|
60
|
+
target: "_blank",
|
|
61
|
+
rel: "noopener noreferrer",
|
|
62
|
+
children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
63
|
+
component: "span",
|
|
64
|
+
direction: "row",
|
|
65
|
+
alignItems: "center",
|
|
66
|
+
spacing: 1,
|
|
67
|
+
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
68
|
+
component: "span",
|
|
69
|
+
color: "primary",
|
|
70
|
+
children: text.length > 40 ? [text.slice(0, 8), text.slice(-8)].join("...") : text
|
|
71
|
+
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_iconsMaterial.OpenInNewOutlined, {
|
|
72
|
+
fontSize: "small"
|
|
73
|
+
})]
|
|
74
|
+
})
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
78
|
+
component: "small",
|
|
79
|
+
color: "text.secondary",
|
|
80
|
+
children: "None"
|
|
81
|
+
});
|
|
82
|
+
}
|
|
@@ -9,6 +9,7 @@ var _context = require("@arcblock/ux/lib/Locale/context");
|
|
|
9
9
|
var _material = require("@mui/material");
|
|
10
10
|
var _util = require("@ocap/util");
|
|
11
11
|
var _ahooks = require("ahooks");
|
|
12
|
+
var _ufo = require("ufo");
|
|
12
13
|
var _api = _interopRequireDefault(require("../../api"));
|
|
13
14
|
var _status = _interopRequireDefault(require("../../components/status"));
|
|
14
15
|
var _util2 = require("../../util");
|
|
@@ -101,7 +102,7 @@ function CustomerInvoiceList({
|
|
|
101
102
|
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
102
103
|
flex: 3,
|
|
103
104
|
children: /* @__PURE__ */(0, _jsxRuntime.jsx)("a", {
|
|
104
|
-
href: `/customer/invoice/${invoice.id}
|
|
105
|
+
href: (0, _ufo.joinURL)(window.location.origin, (0, _util2.getPrefix)(), `/customer/invoice/${invoice.id}`),
|
|
105
106
|
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
106
107
|
component: "span",
|
|
107
108
|
children: invoice.number
|
|
@@ -9,6 +9,7 @@ var _context = require("@arcblock/ux/lib/Locale/context");
|
|
|
9
9
|
var _material = require("@mui/material");
|
|
10
10
|
var _util = require("@ocap/util");
|
|
11
11
|
var _ahooks = require("ahooks");
|
|
12
|
+
var _ufo = require("ufo");
|
|
12
13
|
var _api = _interopRequireDefault(require("../../api"));
|
|
13
14
|
var _status = _interopRequireDefault(require("../../components/status"));
|
|
14
15
|
var _util2 = require("../../util");
|
|
@@ -39,19 +40,12 @@ function MiniInvoiceList() {
|
|
|
39
40
|
status: "open,paid,uncollectible",
|
|
40
41
|
subscription_id: subscriptionId
|
|
41
42
|
}));
|
|
42
|
-
if (!
|
|
43
|
+
if (!subscription || !data) {
|
|
43
44
|
return /* @__PURE__ */(0, _jsxRuntime.jsx)(Position, {
|
|
44
45
|
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.CircularProgress, {})
|
|
45
46
|
});
|
|
46
47
|
}
|
|
47
|
-
|
|
48
|
-
return /* @__PURE__ */(0, _jsxRuntime.jsx)(Position, {
|
|
49
|
-
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
50
|
-
color: "text.secondary",
|
|
51
|
-
children: t("payment.customer.invoice.empty")
|
|
52
|
-
})
|
|
53
|
-
});
|
|
54
|
-
}
|
|
48
|
+
const invoices = data.list || [];
|
|
55
49
|
const infoList = [{
|
|
56
50
|
name: t("payment.customer.subscriptions.plan"),
|
|
57
51
|
value: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
@@ -67,21 +61,25 @@ function MiniInvoiceList() {
|
|
|
67
61
|
label: subscription.status,
|
|
68
62
|
color: (0, _util2.getSubscriptionStatusColor)(subscription.status)
|
|
69
63
|
})
|
|
70
|
-
}, {
|
|
71
|
-
name: t("payment.customer.subscriptions.nextInvoice"),
|
|
72
|
-
value: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
73
|
-
sx: {
|
|
74
|
-
color: "#34BE74",
|
|
75
|
-
fontWeight: "bold",
|
|
76
|
-
marginRight: "10px"
|
|
77
|
-
},
|
|
78
|
-
children: (0, _util2.formatTime)(subscription.current_period_end * 1e3)
|
|
79
|
-
})
|
|
80
64
|
}];
|
|
65
|
+
if (subscription.status === "active" || subscription.status === "trailing") {
|
|
66
|
+
infoList.push({
|
|
67
|
+
name: t("payment.customer.subscriptions.nextInvoice"),
|
|
68
|
+
value: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
69
|
+
sx: {
|
|
70
|
+
color: "#34BE74",
|
|
71
|
+
fontWeight: "bold",
|
|
72
|
+
marginRight: "10px"
|
|
73
|
+
},
|
|
74
|
+
children: (0, _util2.formatTime)(subscription.current_period_end * 1e3)
|
|
75
|
+
})
|
|
76
|
+
});
|
|
77
|
+
}
|
|
81
78
|
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(Position, {
|
|
82
79
|
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
83
80
|
title: t("payment.checkout.subscription")
|
|
84
81
|
}), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
|
|
82
|
+
className: "mini-invoice-wrap",
|
|
85
83
|
sx: {
|
|
86
84
|
display: "flex",
|
|
87
85
|
flexDirection: "column",
|
|
@@ -126,16 +124,12 @@ function MiniInvoiceList() {
|
|
|
126
124
|
})
|
|
127
125
|
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Divider, {}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
128
126
|
sx: {
|
|
129
|
-
marginTop: "12px"
|
|
127
|
+
marginTop: "12px",
|
|
128
|
+
flex: 1
|
|
130
129
|
},
|
|
131
130
|
children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.List, {
|
|
132
131
|
sx: {
|
|
133
|
-
overflow: "auto"
|
|
134
|
-
maxHeight: {
|
|
135
|
-
xs: "240px",
|
|
136
|
-
md: "360px",
|
|
137
|
-
padding: 0
|
|
138
|
-
}
|
|
132
|
+
overflow: "auto"
|
|
139
133
|
},
|
|
140
134
|
className: "mini-invoice-list",
|
|
141
135
|
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.ListSubheader, {
|
|
@@ -149,7 +143,10 @@ function MiniInvoiceList() {
|
|
|
149
143
|
fontSize: "16px",
|
|
150
144
|
children: t("payment.customer.invoices")
|
|
151
145
|
})
|
|
152
|
-
}),
|
|
146
|
+
}), invoices.length === 0 ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
147
|
+
color: "text.secondary",
|
|
148
|
+
children: t("payment.customer.invoice.empty")
|
|
149
|
+
}) : invoices.map(item => {
|
|
153
150
|
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.ListItem, {
|
|
154
151
|
disableGutters: true,
|
|
155
152
|
sx: {
|
|
@@ -165,7 +162,8 @@ function MiniInvoiceList() {
|
|
|
165
162
|
}), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, {
|
|
166
163
|
component: "span",
|
|
167
164
|
sx: {
|
|
168
|
-
flex: 1
|
|
165
|
+
flex: 1,
|
|
166
|
+
textAlign: "right"
|
|
169
167
|
},
|
|
170
168
|
children: [(0, _util.fromUnitToToken)(item.total, item.paymentCurrency.decimal), "\xA0", item.paymentCurrency.symbol]
|
|
171
169
|
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
@@ -186,13 +184,14 @@ function MiniInvoiceList() {
|
|
|
186
184
|
})]
|
|
187
185
|
})
|
|
188
186
|
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
|
|
189
|
-
target: "
|
|
187
|
+
target: "_blank",
|
|
190
188
|
variant: "contained",
|
|
191
189
|
sx: {
|
|
192
190
|
marginTop: "10px 0",
|
|
193
|
-
width: "100%"
|
|
191
|
+
width: "100%",
|
|
192
|
+
color: "#fff!important"
|
|
194
193
|
},
|
|
195
|
-
href:
|
|
194
|
+
href: (0, _ufo.joinURL)(window.location.origin, (0, _util2.getPrefix)(), `/customer/subscription/${subscription.id}`),
|
|
196
195
|
children: t("payment.customer.subscriptions.title")
|
|
197
196
|
})]
|
|
198
197
|
})]
|
|
@@ -204,7 +203,6 @@ function Position({
|
|
|
204
203
|
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
205
204
|
className: "mini-invoice-box",
|
|
206
205
|
sx: {
|
|
207
|
-
justifyContent: "center",
|
|
208
206
|
padding: "8px",
|
|
209
207
|
width: "100%",
|
|
210
208
|
maxWidth: "500px",
|
|
@@ -10,6 +10,7 @@ var _material = require("@mui/material");
|
|
|
10
10
|
var _util = require("@ocap/util");
|
|
11
11
|
var _ahooks = require("ahooks");
|
|
12
12
|
var _api = _interopRequireDefault(require("../../api"));
|
|
13
|
+
var _tx = _interopRequireDefault(require("../../components/blockchain/tx"));
|
|
13
14
|
var _status = _interopRequireDefault(require("../../components/status"));
|
|
14
15
|
var _util2 = require("../../util");
|
|
15
16
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -111,10 +112,20 @@ function CustomerPaymentList({
|
|
|
111
112
|
color: (0, _util2.getPaymentIntentStatusColor)(item.status)
|
|
112
113
|
})
|
|
113
114
|
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
114
|
-
flex:
|
|
115
|
+
flex: 3,
|
|
115
116
|
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
116
117
|
children: item.description || item.id
|
|
117
118
|
})
|
|
119
|
+
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
120
|
+
flex: 3,
|
|
121
|
+
sx: {
|
|
122
|
+
minWidth: "220px"
|
|
123
|
+
},
|
|
124
|
+
children: item.payment_details?.arcblock?.tx_hash && /* @__PURE__ */(0, _jsxRuntime.jsx)(_tx.default, {
|
|
125
|
+
details: item.payment_details,
|
|
126
|
+
method: item.paymentMethod,
|
|
127
|
+
mode: "customer"
|
|
128
|
+
})
|
|
118
129
|
})]
|
|
119
130
|
}, item.id))]
|
|
120
131
|
}, date)), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
|
package/lib/index.d.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 TxLink from './components/blockchain/tx';
|
|
4
5
|
import ConfirmDialog from './components/confirm';
|
|
5
6
|
import FormInput from './components/input';
|
|
6
7
|
import Livemode from './components/livemode';
|
|
@@ -18,4 +19,4 @@ import ProductSkeleton from './payment/product-skeleton';
|
|
|
18
19
|
export * from './util';
|
|
19
20
|
export * from './contexts/payment';
|
|
20
21
|
export { translations, createTranslator } from './locales';
|
|
21
|
-
export { api, dayjs, FormInput, PhoneInput, Status, Livemode, Switch, ConfirmDialog, CheckoutForm, CheckoutTable, Payment, PricingTable, ProductSkeleton, Amount, CustomerInvoiceList, CustomerPaymentList, MiniInvoiceList, };
|
|
22
|
+
export { api, dayjs, FormInput, PhoneInput, Status, Livemode, Switch, ConfirmDialog, CheckoutForm, CheckoutTable, Payment, PricingTable, ProductSkeleton, Amount, CustomerInvoiceList, CustomerPaymentList, MiniInvoiceList, TxLink, };
|
package/lib/index.js
CHANGED
|
@@ -7,6 +7,7 @@ var _exportNames = {
|
|
|
7
7
|
api: true,
|
|
8
8
|
CheckoutForm: true,
|
|
9
9
|
CheckoutTable: true,
|
|
10
|
+
TxLink: true,
|
|
10
11
|
ConfirmDialog: true,
|
|
11
12
|
FormInput: true,
|
|
12
13
|
Livemode: true,
|
|
@@ -114,6 +115,12 @@ Object.defineProperty(exports, "Switch", {
|
|
|
114
115
|
return _switchButton.default;
|
|
115
116
|
}
|
|
116
117
|
});
|
|
118
|
+
Object.defineProperty(exports, "TxLink", {
|
|
119
|
+
enumerable: true,
|
|
120
|
+
get: function () {
|
|
121
|
+
return _tx.default;
|
|
122
|
+
}
|
|
123
|
+
});
|
|
117
124
|
Object.defineProperty(exports, "api", {
|
|
118
125
|
enumerable: true,
|
|
119
126
|
get: function () {
|
|
@@ -141,6 +148,7 @@ Object.defineProperty(exports, "translations", {
|
|
|
141
148
|
var _api = _interopRequireDefault(require("./api"));
|
|
142
149
|
var _form = _interopRequireDefault(require("./checkout/form"));
|
|
143
150
|
var _table = _interopRequireDefault(require("./checkout/table"));
|
|
151
|
+
var _tx = _interopRequireDefault(require("./components/blockchain/tx"));
|
|
144
152
|
var _confirm = _interopRequireDefault(require("./components/confirm"));
|
|
145
153
|
var _input = _interopRequireDefault(require("./components/input"));
|
|
146
154
|
var _livemode = _interopRequireDefault(require("./components/livemode"));
|
package/lib/locales/en.js
CHANGED
|
@@ -209,17 +209,17 @@ module.exports = (0, _flat.default)({
|
|
|
209
209
|
pay: "Pay this invoice",
|
|
210
210
|
paySuccess: "You have successfully paid the invoice",
|
|
211
211
|
payError: "Failed to paid the invoice",
|
|
212
|
-
empty: "
|
|
212
|
+
empty: "There are no invoices here"
|
|
213
213
|
},
|
|
214
214
|
payment: {
|
|
215
|
-
empty: "
|
|
215
|
+
empty: "There are no payments here"
|
|
216
216
|
},
|
|
217
217
|
subscriptions: {
|
|
218
218
|
plan: "Plan",
|
|
219
219
|
nextInvoice: "Next Invoice",
|
|
220
220
|
title: "Manage subscriptions",
|
|
221
221
|
current: "Current subscription",
|
|
222
|
-
empty: "
|
|
222
|
+
empty: "There are no subscriptions here"
|
|
223
223
|
}
|
|
224
224
|
}
|
|
225
225
|
}
|
package/lib/locales/zh.js
CHANGED
|
@@ -209,17 +209,17 @@ module.exports = (0, _flat.default)({
|
|
|
209
209
|
pay: "\u652F\u4ED8\u6B64\u53D1\u7968",
|
|
210
210
|
paySuccess: "\u652F\u4ED8\u6210\u529F",
|
|
211
211
|
payError: "\u652F\u4ED8\u5931\u8D25",
|
|
212
|
-
empty: "\
|
|
212
|
+
empty: "\u6CA1\u6709\u4EFB\u4F55\u53D1\u7968"
|
|
213
213
|
},
|
|
214
214
|
payment: {
|
|
215
|
-
empty: "\
|
|
215
|
+
empty: "\u6CA1\u6709\u4EFB\u4F55\u652F\u4ED8"
|
|
216
216
|
},
|
|
217
217
|
subscriptions: {
|
|
218
218
|
plan: "\u8BA2\u9605",
|
|
219
219
|
nextInvoice: "\u4E0B\u4E00\u5F20\u53D1\u7968",
|
|
220
220
|
title: "\u8BA2\u9605\u7BA1\u7406",
|
|
221
221
|
current: "\u5F53\u524D\u8BA2\u9605",
|
|
222
|
-
empty: "\
|
|
222
|
+
empty: "\u6CA1\u6709\u4EFB\u4F55\u8BA2\u9605"
|
|
223
223
|
}
|
|
224
224
|
}
|
|
225
225
|
}
|
package/lib/util.js
CHANGED
|
@@ -282,9 +282,12 @@ function getWebhookStatusColor(status) {
|
|
|
282
282
|
}
|
|
283
283
|
function getCheckoutAmount(items, currency, includeFreeTrial = false, upsell = true) {
|
|
284
284
|
let renew = new _util.BN(0);
|
|
285
|
-
const total = items.
|
|
285
|
+
const total = items.filter(x => {
|
|
286
286
|
const price = upsell ? x.upsell_price || x.price : x.price;
|
|
287
|
-
|
|
287
|
+
return price != null;
|
|
288
|
+
}).reduce((acc, x) => {
|
|
289
|
+
const price = upsell ? x.upsell_price || x.price : x.price;
|
|
290
|
+
if (price?.type === "recurring") {
|
|
288
291
|
renew = renew.add(new _util.BN(getPriceUintAmountByCurrency(price, currency)).mul(new _util.BN(x.quantity)));
|
|
289
292
|
if (includeFreeTrial) {
|
|
290
293
|
return acc;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/payment-react",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.131",
|
|
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.131",
|
|
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": "a1a5072b1a0c564cce5ba4aee5fc4801cfef4a46"
|
|
122
122
|
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { PaymentDetails, TPaymentMethod } from '@blocklet/payment-types';
|
|
2
|
+
import { OpenInNewOutlined } from '@mui/icons-material';
|
|
3
|
+
import { Link, Stack, Typography } from '@mui/material';
|
|
4
|
+
import { joinURL } from 'ufo';
|
|
5
|
+
|
|
6
|
+
const getTxLink = (method: TPaymentMethod, details: PaymentDetails) => {
|
|
7
|
+
if (method.type === 'arcblock' && details.arcblock?.tx_hash) {
|
|
8
|
+
return {
|
|
9
|
+
link: joinURL(method.settings.arcblock?.explorer_host as string, '/txs', details.arcblock?.tx_hash as string),
|
|
10
|
+
text: details.arcblock?.tx_hash as string,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
if (method.type === 'bitcoin' && details.bitcoin?.tx_hash) {
|
|
14
|
+
return {
|
|
15
|
+
link: joinURL(method.settings.bitcoin?.explorer_host as string, '/tx', details.bitcoin?.tx_hash as string),
|
|
16
|
+
text: details.bitcoin?.tx_hash as string,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
if (method.type === 'ethereum' && details.ethereum?.tx_hash) {
|
|
20
|
+
return {
|
|
21
|
+
link: joinURL(method.settings.ethereum?.explorer_host as string, '/tx', details.ethereum?.tx_hash as string),
|
|
22
|
+
text: details.ethereum?.tx_hash as string,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
if (method.type === 'stripe') {
|
|
26
|
+
const dashboard = method.livemode ? 'https://dashboard.stripe.com' : 'https://dashboard.stripe.com/test';
|
|
27
|
+
return {
|
|
28
|
+
link: joinURL(
|
|
29
|
+
method.settings.stripe?.dashboard || dashboard,
|
|
30
|
+
'payments',
|
|
31
|
+
details.stripe?.payment_intent_id as string
|
|
32
|
+
),
|
|
33
|
+
text: details.stripe?.payment_intent_id as string,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return { text: 'N/A', link: '' };
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
TxLink.defaultProps = {
|
|
41
|
+
mode: 'dashboard',
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export default function TxLink(props: {
|
|
45
|
+
details: PaymentDetails;
|
|
46
|
+
method: TPaymentMethod;
|
|
47
|
+
mode?: 'customer' | 'dashboard';
|
|
48
|
+
}) {
|
|
49
|
+
if (!props.details || (props.mode === 'customer' && props.method.type === 'stripe')) {
|
|
50
|
+
return (
|
|
51
|
+
<Typography component="small" color="text.secondary">
|
|
52
|
+
None
|
|
53
|
+
</Typography>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const { text, link } = getTxLink(props.method, props.details);
|
|
58
|
+
|
|
59
|
+
if (link) {
|
|
60
|
+
return (
|
|
61
|
+
<Link href={link} target="_blank" rel="noopener noreferrer">
|
|
62
|
+
<Stack component="span" direction="row" alignItems="center" spacing={1}>
|
|
63
|
+
<Typography component="span" color="primary">
|
|
64
|
+
{text.length > 40 ? [text.slice(0, 8), text.slice(-8)].join('...') : text}
|
|
65
|
+
</Typography>
|
|
66
|
+
<OpenInNewOutlined fontSize="small" />
|
|
67
|
+
</Stack>
|
|
68
|
+
</Link>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<Typography component="small" color="text.secondary">
|
|
74
|
+
None
|
|
75
|
+
</Typography>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
@@ -4,10 +4,11 @@ import type { Paginated, TInvoiceExpanded } from '@blocklet/payment-types';
|
|
|
4
4
|
import { Box, Button, CircularProgress, Stack, Typography } from '@mui/material';
|
|
5
5
|
import { fromUnitToToken } from '@ocap/util';
|
|
6
6
|
import { useInfiniteScroll } from 'ahooks';
|
|
7
|
+
import { joinURL } from 'ufo';
|
|
7
8
|
|
|
8
9
|
import api from '../../api';
|
|
9
10
|
import Status from '../../components/status';
|
|
10
|
-
import { formatToDate, getInvoiceStatusColor } from '../../util';
|
|
11
|
+
import { formatToDate, getInvoiceStatusColor, getPrefix } from '../../util';
|
|
11
12
|
|
|
12
13
|
const groupByDate = (items: TInvoiceExpanded[]) => {
|
|
13
14
|
const grouped: { [key: string]: TInvoiceExpanded[] } = {};
|
|
@@ -83,7 +84,7 @@ export default function CustomerInvoiceList({ customer_id, subscription_id }: Pr
|
|
|
83
84
|
}}
|
|
84
85
|
flexWrap="nowrap">
|
|
85
86
|
<Box flex={3}>
|
|
86
|
-
<a href={`/customer/invoice/${invoice.id}`}>
|
|
87
|
+
<a href={joinURL(window.location.origin, getPrefix(), `/customer/invoice/${invoice.id}`)}>
|
|
87
88
|
<Typography component="span">{invoice.number}</Typography>
|
|
88
89
|
</a>
|
|
89
90
|
</Box>
|
|
@@ -4,6 +4,7 @@ import type { Paginated, TInvoiceExpanded, TSubscriptionExpanded } from '@blockl
|
|
|
4
4
|
import { Box, Button, CircularProgress, Divider, List, ListItem, ListSubheader, Typography } from '@mui/material';
|
|
5
5
|
import { fromUnitToToken } from '@ocap/util';
|
|
6
6
|
import { useRequest } from 'ahooks';
|
|
7
|
+
import { joinURL } from 'ufo';
|
|
7
8
|
|
|
8
9
|
import api from '../../api';
|
|
9
10
|
import Status from '../../components/status';
|
|
@@ -12,6 +13,7 @@ import {
|
|
|
12
13
|
formatTime,
|
|
13
14
|
formatToDate,
|
|
14
15
|
getInvoiceStatusColor,
|
|
16
|
+
getPrefix,
|
|
15
17
|
getSubscriptionStatusColor,
|
|
16
18
|
} from '../../util';
|
|
17
19
|
|
|
@@ -37,7 +39,7 @@ export default function MiniInvoiceList() {
|
|
|
37
39
|
fetchInvoiceData({ page: 1, pageSize: 10, status: 'open,paid,uncollectible', subscription_id: subscriptionId })
|
|
38
40
|
);
|
|
39
41
|
|
|
40
|
-
if (!
|
|
42
|
+
if (!subscription || !data) {
|
|
41
43
|
return (
|
|
42
44
|
<Position>
|
|
43
45
|
<CircularProgress />
|
|
@@ -45,13 +47,7 @@ export default function MiniInvoiceList() {
|
|
|
45
47
|
);
|
|
46
48
|
}
|
|
47
49
|
|
|
48
|
-
|
|
49
|
-
return (
|
|
50
|
-
<Position>
|
|
51
|
-
<Typography color="text.secondary">{t('payment.customer.invoice.empty')}</Typography>
|
|
52
|
-
</Position>
|
|
53
|
-
);
|
|
54
|
-
}
|
|
50
|
+
const invoices = data.list || [];
|
|
55
51
|
|
|
56
52
|
const infoList = [
|
|
57
53
|
{
|
|
@@ -66,8 +62,10 @@ export default function MiniInvoiceList() {
|
|
|
66
62
|
name: t('common.status'),
|
|
67
63
|
value: <Status label={subscription.status} color={getSubscriptionStatusColor(subscription.status)} />,
|
|
68
64
|
},
|
|
65
|
+
];
|
|
69
66
|
|
|
70
|
-
|
|
67
|
+
if (subscription.status === 'active' || subscription.status === 'trailing') {
|
|
68
|
+
infoList.push({
|
|
71
69
|
name: t('payment.customer.subscriptions.nextInvoice'),
|
|
72
70
|
value: (
|
|
73
71
|
<Typography
|
|
@@ -79,13 +77,14 @@ export default function MiniInvoiceList() {
|
|
|
79
77
|
{formatTime(subscription.current_period_end * 1000)}
|
|
80
78
|
</Typography>
|
|
81
79
|
),
|
|
82
|
-
}
|
|
83
|
-
|
|
80
|
+
});
|
|
81
|
+
}
|
|
84
82
|
|
|
85
83
|
return (
|
|
86
84
|
<Position>
|
|
87
85
|
<Typography title={t('payment.checkout.subscription')} />
|
|
88
86
|
<Box
|
|
87
|
+
className="mini-invoice-wrap"
|
|
89
88
|
sx={{
|
|
90
89
|
display: 'flex',
|
|
91
90
|
flexDirection: 'column',
|
|
@@ -111,34 +110,40 @@ export default function MiniInvoiceList() {
|
|
|
111
110
|
</List>
|
|
112
111
|
</Box>
|
|
113
112
|
<Divider />
|
|
114
|
-
<Box sx={{ marginTop: '12px' }}>
|
|
115
|
-
<List
|
|
116
|
-
sx={{ overflow: 'auto', maxHeight: { xs: '240px', md: '360px', padding: 0 } }}
|
|
117
|
-
className="mini-invoice-list">
|
|
113
|
+
<Box sx={{ marginTop: '12px', flex: 1 }}>
|
|
114
|
+
<List sx={{ overflow: 'auto' }} className="mini-invoice-list">
|
|
118
115
|
<ListSubheader disableGutters sx={{ padding: 0 }}>
|
|
119
116
|
<Typography component="h2" variant="h6" fontSize="16px">
|
|
120
117
|
{t('payment.customer.invoices')}
|
|
121
118
|
</Typography>
|
|
122
119
|
</ListSubheader>
|
|
123
|
-
{(
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
120
|
+
{(invoices as any).length === 0 ? (
|
|
121
|
+
<Typography color="text.secondary">{t('payment.customer.invoice.empty')}</Typography>
|
|
122
|
+
) : (
|
|
123
|
+
(invoices as any).map((item: any) => {
|
|
124
|
+
return (
|
|
125
|
+
<ListItem key={item.id} disableGutters sx={{ display: 'flex', justifyContent: 'space-between' }}>
|
|
126
|
+
<Typography component="span" sx={{ flex: 3 }}>
|
|
127
|
+
{formatToDate(item.created_at)}
|
|
128
|
+
</Typography>
|
|
129
|
+
<Typography component="span" sx={{ flex: 1, textAlign: 'right' }}>
|
|
130
|
+
{fromUnitToToken(item.total, item.paymentCurrency.decimal)}
|
|
131
|
+
{item.paymentCurrency.symbol}
|
|
132
|
+
</Typography>
|
|
133
|
+
<Typography component="span" sx={{ flex: 2, textAlign: 'right' }}>
|
|
134
|
+
<Status label={item.status} color={getInvoiceStatusColor(item.status)} sx={{ flex: 2 }} />
|
|
135
|
+
</Typography>
|
|
136
|
+
</ListItem>
|
|
137
|
+
);
|
|
138
|
+
})
|
|
139
|
+
)}
|
|
139
140
|
</List>
|
|
140
141
|
</Box>
|
|
141
|
-
<Button
|
|
142
|
+
<Button
|
|
143
|
+
target="_blank"
|
|
144
|
+
variant="contained"
|
|
145
|
+
sx={{ marginTop: '10px 0', width: '100%', color: '#fff!important' }}
|
|
146
|
+
href={joinURL(window.location.origin, getPrefix(), `/customer/subscription/${subscription.id}`)}>
|
|
142
147
|
{t('payment.customer.subscriptions.title')}
|
|
143
148
|
</Button>
|
|
144
149
|
</Box>
|
|
@@ -151,7 +156,6 @@ function Position({ children }: any) {
|
|
|
151
156
|
<Box
|
|
152
157
|
className="mini-invoice-box" // 预留 class 用于设置定位
|
|
153
158
|
sx={{
|
|
154
|
-
justifyContent: 'center',
|
|
155
159
|
padding: '8px',
|
|
156
160
|
width: '100%',
|
|
157
161
|
maxWidth: '500px',
|
|
@@ -6,6 +6,7 @@ import { fromUnitToToken } from '@ocap/util';
|
|
|
6
6
|
import { useInfiniteScroll } from 'ahooks';
|
|
7
7
|
|
|
8
8
|
import api from '../../api';
|
|
9
|
+
import TxLink from '../../components/blockchain/tx';
|
|
9
10
|
import Status from '../../components/status';
|
|
10
11
|
import { formatToDate, getPaymentIntentStatusColor } from '../../util';
|
|
11
12
|
|
|
@@ -91,9 +92,18 @@ export default function CustomerPaymentList({ customer_id }: Props) {
|
|
|
91
92
|
<Box flex={3}>
|
|
92
93
|
<Status label={item.status} color={getPaymentIntentStatusColor(item.status)} />
|
|
93
94
|
</Box>
|
|
94
|
-
<Box flex={
|
|
95
|
+
<Box flex={3}>
|
|
95
96
|
<Typography>{item.description || item.id}</Typography>
|
|
96
97
|
</Box>
|
|
98
|
+
<Box flex={3} sx={{ minWidth: '220px' }}>
|
|
99
|
+
{(item as any).payment_details?.arcblock?.tx_hash && (
|
|
100
|
+
<TxLink
|
|
101
|
+
details={(item as any).payment_details}
|
|
102
|
+
method={(item as any).paymentMethod}
|
|
103
|
+
mode="customer"
|
|
104
|
+
/>
|
|
105
|
+
)}
|
|
106
|
+
</Box>
|
|
97
107
|
</Stack>
|
|
98
108
|
))}
|
|
99
109
|
</Box>
|
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 TxLink from './components/blockchain/tx';
|
|
4
5
|
import ConfirmDialog from './components/confirm';
|
|
5
6
|
import FormInput from './components/input';
|
|
6
7
|
import Livemode from './components/livemode';
|
|
@@ -39,4 +40,5 @@ export {
|
|
|
39
40
|
CustomerInvoiceList,
|
|
40
41
|
CustomerPaymentList,
|
|
41
42
|
MiniInvoiceList,
|
|
43
|
+
TxLink,
|
|
42
44
|
};
|
package/src/locales/en.tsx
CHANGED
|
@@ -207,17 +207,17 @@ export default flat({
|
|
|
207
207
|
pay: 'Pay this invoice',
|
|
208
208
|
paySuccess: 'You have successfully paid the invoice',
|
|
209
209
|
payError: 'Failed to paid the invoice',
|
|
210
|
-
empty: '
|
|
210
|
+
empty: 'There are no invoices here',
|
|
211
211
|
},
|
|
212
212
|
payment: {
|
|
213
|
-
empty: '
|
|
213
|
+
empty: 'There are no payments here',
|
|
214
214
|
},
|
|
215
215
|
subscriptions: {
|
|
216
216
|
plan: 'Plan',
|
|
217
217
|
nextInvoice: 'Next Invoice',
|
|
218
218
|
title: 'Manage subscriptions',
|
|
219
219
|
current: 'Current subscription',
|
|
220
|
-
empty: '
|
|
220
|
+
empty: 'There are no subscriptions here',
|
|
221
221
|
},
|
|
222
222
|
},
|
|
223
223
|
},
|
package/src/locales/zh.tsx
CHANGED
|
@@ -203,17 +203,17 @@ export default flat({
|
|
|
203
203
|
pay: '支付此发票',
|
|
204
204
|
paySuccess: '支付成功',
|
|
205
205
|
payError: '支付失败',
|
|
206
|
-
empty: '
|
|
206
|
+
empty: '没有任何发票',
|
|
207
207
|
},
|
|
208
208
|
payment: {
|
|
209
|
-
empty: '
|
|
209
|
+
empty: '没有任何支付',
|
|
210
210
|
},
|
|
211
211
|
subscriptions: {
|
|
212
212
|
plan: '订阅',
|
|
213
213
|
nextInvoice: '下一张发票',
|
|
214
214
|
title: '订阅管理',
|
|
215
215
|
current: '当前订阅',
|
|
216
|
-
empty: '
|
|
216
|
+
empty: '没有任何订阅',
|
|
217
217
|
},
|
|
218
218
|
},
|
|
219
219
|
},
|
package/src/util.ts
CHANGED
|
@@ -324,11 +324,14 @@ export function getCheckoutAmount(
|
|
|
324
324
|
upsell = true
|
|
325
325
|
) {
|
|
326
326
|
let renew = new BN(0);
|
|
327
|
-
|
|
328
327
|
const total = items
|
|
328
|
+
.filter((x) => {
|
|
329
|
+
const price = upsell ? x.upsell_price || x.price : x.price;
|
|
330
|
+
return price != null;
|
|
331
|
+
})
|
|
329
332
|
.reduce((acc, x) => {
|
|
330
333
|
const price = upsell ? x.upsell_price || x.price : x.price;
|
|
331
|
-
if (price
|
|
334
|
+
if (price?.type === 'recurring') {
|
|
332
335
|
renew = renew.add(new BN(getPriceUintAmountByCurrency(price, currency)).mul(new BN(x.quantity)));
|
|
333
336
|
|
|
334
337
|
if (includeFreeTrial) {
|