@blocklet/payment-react 1.16.2 → 1.16.4
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/README.md +34 -0
- package/es/components/over-due-invoice-payment.d.ts +38 -0
- package/es/components/over-due-invoice-payment.js +237 -0
- package/es/index.d.ts +2 -1
- package/es/index.js +3 -1
- package/es/locales/en.js +17 -1
- package/es/locales/zh.js +17 -1
- package/lib/components/over-due-invoice-payment.d.ts +38 -0
- package/lib/components/over-due-invoice-payment.js +284 -0
- package/lib/index.d.ts +2 -1
- package/lib/index.js +8 -0
- package/lib/locales/en.js +17 -1
- package/lib/locales/zh.js +17 -1
- package/package.json +3 -3
- package/src/components/over-due-invoice-payment.tsx +305 -0
- package/src/index.ts +2 -0
- package/src/locales/en.tsx +18 -0
- package/src/locales/zh.tsx +18 -0
package/README.md
CHANGED
|
@@ -394,6 +394,40 @@ We recommend using `showCheckoutSummary={false}` instead of `mode=inline-minimal
|
|
|
394
394
|
/>
|
|
395
395
|
```
|
|
396
396
|
|
|
397
|
+
### v1.16.4
|
|
398
|
+
|
|
399
|
+
- Add `OverdueInvoicePayment` component
|
|
400
|
+
- display all overdue invoices of a subscription, and support batch payment
|
|
401
|
+
- props:
|
|
402
|
+
- `subscriptionId`: [required] the id of the subscription
|
|
403
|
+
- `onPaid`: [optional] a callback function that will be called when the payment is successful
|
|
404
|
+
- `mode`: [optional] the mode of the component, `default` or `custom`, default is `default`
|
|
405
|
+
- `dialogProps`: [optional] the props of the dialog, default is `{ open: true }`
|
|
406
|
+
- `children`: [optional] a function that will be called with the payment data, if `mode` is `custom`, otherwise, the default dialog will be displayed
|
|
407
|
+
- custom mode:
|
|
408
|
+
- the `children` will receive two parameters:
|
|
409
|
+
- `handlePay`: a function that starts the payment process
|
|
410
|
+
- `data`: the payment data
|
|
411
|
+
- `subscription`: the subscription data
|
|
412
|
+
- `summary`: the summary of the payment, the key is the `currencyId`, the value includes `amount`, `currency`, `method`
|
|
413
|
+
- `invoices`: the list of invoices
|
|
414
|
+
- `subscriptionUrl`: the url of the subscription
|
|
415
|
+
```tsx
|
|
416
|
+
<OverdueInvoicePayment subscriptionId={data.id} onPaid={() => { console.log('paid') }} />
|
|
417
|
+
|
|
418
|
+
// custom mode
|
|
419
|
+
<OverdueInvoicePayment subscriptionId={data.id} onPaid={() => { console.log('paid') }} mode="custom">
|
|
420
|
+
{(handlePay, { subscription, summary, invoices, subscriptionUrl }) => (
|
|
421
|
+
<div>custom content</div>
|
|
422
|
+
<p>Subscription: {subscription.name}</p>
|
|
423
|
+
<p>Current currency Total: {summary[currencyId].amount}</p>
|
|
424
|
+
<p>Invoices: {invoices.length}</p>
|
|
425
|
+
<p>Subscription URL: {subscriptionUrl}</p>
|
|
426
|
+
<button onClick={() => handlePay(summary[currencyId])}>Pay</button>
|
|
427
|
+
)}
|
|
428
|
+
</OverdueInvoicePayment>
|
|
429
|
+
```
|
|
430
|
+
|
|
397
431
|
### Status & Utility Components
|
|
398
432
|
```tsx
|
|
399
433
|
import {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { Invoice, PaymentCurrency, PaymentMethod, Subscription } from '@blocklet/payment-types';
|
|
3
|
+
type DialogProps = {
|
|
4
|
+
open?: boolean;
|
|
5
|
+
onClose?: () => void;
|
|
6
|
+
title?: string;
|
|
7
|
+
};
|
|
8
|
+
type Props = {
|
|
9
|
+
subscriptionId: string;
|
|
10
|
+
mode?: 'default' | 'custom';
|
|
11
|
+
onPaid?: (subscriptionId: string, currencyId: string) => void;
|
|
12
|
+
dialogProps?: DialogProps;
|
|
13
|
+
children?: (handlePay: (item: SummaryItem) => void, data: {
|
|
14
|
+
subscription: Subscription;
|
|
15
|
+
summary: {
|
|
16
|
+
[key: string]: SummaryItem;
|
|
17
|
+
};
|
|
18
|
+
invoices: Invoice[];
|
|
19
|
+
subscriptionUrl: string;
|
|
20
|
+
}) => React.ReactNode;
|
|
21
|
+
};
|
|
22
|
+
type SummaryItem = {
|
|
23
|
+
amount: string;
|
|
24
|
+
currency: PaymentCurrency;
|
|
25
|
+
method: PaymentMethod;
|
|
26
|
+
};
|
|
27
|
+
declare function OverdueInvoicePayment({ subscriptionId, mode, dialogProps, children, onPaid, }: Props): import("react").JSX.Element;
|
|
28
|
+
declare namespace OverdueInvoicePayment {
|
|
29
|
+
var defaultProps: {
|
|
30
|
+
mode: string;
|
|
31
|
+
onPaid: () => void;
|
|
32
|
+
dialogProps: {
|
|
33
|
+
open: boolean;
|
|
34
|
+
};
|
|
35
|
+
children: null;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export default OverdueInvoicePayment;
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useMemo, useState } from "react";
|
|
3
|
+
import { Button, Typography, Stack, CircularProgress, Alert } from "@mui/material";
|
|
4
|
+
import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
|
|
5
|
+
import Toast from "@arcblock/ux/lib/Toast";
|
|
6
|
+
import { joinURL } from "ufo";
|
|
7
|
+
import { useRequest } from "ahooks";
|
|
8
|
+
import { Dialog } from "@arcblock/ux";
|
|
9
|
+
import { usePaymentContext } from "../contexts/payment.js";
|
|
10
|
+
import { formatAmount, formatError, getPrefix } from "../libs/util.js";
|
|
11
|
+
import { useSubscription } from "../hooks/subscription.js";
|
|
12
|
+
const fetchOverdueInvoices = async (subscriptionId) => {
|
|
13
|
+
const res = await fetch(`/api/subscriptions/${subscriptionId}/overdue/invoices`);
|
|
14
|
+
return res.json();
|
|
15
|
+
};
|
|
16
|
+
function OverdueInvoicePayment({
|
|
17
|
+
subscriptionId,
|
|
18
|
+
mode = "default",
|
|
19
|
+
dialogProps = {},
|
|
20
|
+
children,
|
|
21
|
+
onPaid = () => {
|
|
22
|
+
}
|
|
23
|
+
}) {
|
|
24
|
+
const { t } = useLocaleContext();
|
|
25
|
+
const { connect } = usePaymentContext();
|
|
26
|
+
const [selectCurrencyId, setSelectCurrencyId] = useState("");
|
|
27
|
+
const [payLoading, setPayLoading] = useState(false);
|
|
28
|
+
const [dialogOpen, setDialogOpen] = useState(dialogProps.open || false);
|
|
29
|
+
const [processedCurrencies, setProcessedCurrencies] = useState({});
|
|
30
|
+
const {
|
|
31
|
+
data = {
|
|
32
|
+
subscription: {},
|
|
33
|
+
summary: {},
|
|
34
|
+
invoices: []
|
|
35
|
+
},
|
|
36
|
+
error,
|
|
37
|
+
loading,
|
|
38
|
+
runAsync: refresh
|
|
39
|
+
} = useRequest(() => fetchOverdueInvoices(subscriptionId));
|
|
40
|
+
const subscriptionUrl = joinURL(getPrefix(), `/customer/subscription/${subscriptionId}`);
|
|
41
|
+
const summaryList = useMemo(() => {
|
|
42
|
+
if (!data?.summary) {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
return Object.values(data.summary);
|
|
46
|
+
}, [data?.summary]);
|
|
47
|
+
const subscription = useSubscription("events");
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (subscription) {
|
|
50
|
+
subscription.on("invoice.paid", ({ response }) => {
|
|
51
|
+
const uniqueKey = `${response.subscription_id}-${response.currency_id}`;
|
|
52
|
+
if (response.subscription_id === subscriptionId && !processedCurrencies[uniqueKey]) {
|
|
53
|
+
Toast.success(t("payment.customer.invoice.paySuccess"));
|
|
54
|
+
setPayLoading(false);
|
|
55
|
+
setProcessedCurrencies({ ...processedCurrencies, [uniqueKey]: 1 });
|
|
56
|
+
refresh().then((res) => {
|
|
57
|
+
if (res.invoices?.length === 0) {
|
|
58
|
+
setDialogOpen(false);
|
|
59
|
+
onPaid(subscriptionId, response.currency_id);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}, [subscription]);
|
|
66
|
+
const handlePay = (item) => {
|
|
67
|
+
const { currency, method } = item;
|
|
68
|
+
if (method.type === "stripe") {
|
|
69
|
+
Toast.error(t("payment.subscription.overdue.notSupport"));
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (payLoading) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
setSelectCurrencyId(currency.id);
|
|
76
|
+
setPayLoading(true);
|
|
77
|
+
if (method.type === "arcblock" || method.type === "ethereum") {
|
|
78
|
+
connect.open({
|
|
79
|
+
containerEl: void 0,
|
|
80
|
+
saveConnect: false,
|
|
81
|
+
action: "collect-batch",
|
|
82
|
+
prefix: joinURL("/api/did"),
|
|
83
|
+
extraParams: { currencyId: currency.id, subscriptionId },
|
|
84
|
+
onSuccess: () => {
|
|
85
|
+
connect.close();
|
|
86
|
+
},
|
|
87
|
+
onClose: () => {
|
|
88
|
+
connect.close();
|
|
89
|
+
setPayLoading(false);
|
|
90
|
+
},
|
|
91
|
+
onError: (err) => {
|
|
92
|
+
Toast.error(formatError(err));
|
|
93
|
+
setPayLoading(false);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
if (loading) {
|
|
99
|
+
return /* @__PURE__ */ jsx(CircularProgress, {});
|
|
100
|
+
}
|
|
101
|
+
const renderPayButton = (item, props) => {
|
|
102
|
+
const isPayLoading = payLoading && item.currency.id === selectCurrencyId;
|
|
103
|
+
if (item.method.type === "stripe") {
|
|
104
|
+
return /* @__PURE__ */ jsx(Button, { variant: "contained", color: "primary", onClick: () => window.open(subscriptionUrl, "_blank"), ...props, children: t("payment.subscription.overdue.viewNow") });
|
|
105
|
+
}
|
|
106
|
+
return /* @__PURE__ */ jsxs(Button, { variant: "contained", color: "primary", onClick: () => handlePay(item), ...props, disabled: isPayLoading, children: [
|
|
107
|
+
isPayLoading && /* @__PURE__ */ jsx(CircularProgress, { size: 14, sx: { mr: 1, color: "text.lighter" } }),
|
|
108
|
+
t("payment.subscription.overdue.payNow")
|
|
109
|
+
] });
|
|
110
|
+
};
|
|
111
|
+
if (mode === "custom" && children && typeof children === "function") {
|
|
112
|
+
return /* @__PURE__ */ jsx(Stack, { children: children(handlePay, {
|
|
113
|
+
subscription: data?.subscription,
|
|
114
|
+
subscriptionUrl,
|
|
115
|
+
summary: data?.summary,
|
|
116
|
+
invoices: data?.invoices
|
|
117
|
+
}) });
|
|
118
|
+
}
|
|
119
|
+
return /* @__PURE__ */ jsx(
|
|
120
|
+
Dialog,
|
|
121
|
+
{
|
|
122
|
+
open: dialogOpen,
|
|
123
|
+
onClose: () => setDialogOpen(false),
|
|
124
|
+
title: dialogProps.title || t("payment.subscription.overdue.pastDue"),
|
|
125
|
+
PaperProps: {
|
|
126
|
+
style: { minHeight: "auto" }
|
|
127
|
+
},
|
|
128
|
+
children: error ? /* @__PURE__ */ jsx(Alert, { severity: "error", children: error.message }) : /* @__PURE__ */ jsxs(Stack, { gap: 1, children: [
|
|
129
|
+
summaryList.length === 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
130
|
+
/* @__PURE__ */ jsx(Alert, { severity: "success", children: t("payment.subscription.overdue.empty", {
|
|
131
|
+
// @ts-ignore
|
|
132
|
+
name: data?.subscription?.description
|
|
133
|
+
}) }),
|
|
134
|
+
/* @__PURE__ */ jsx(Stack, { direction: "row", justifyContent: "flex-end", mt: 2, children: /* @__PURE__ */ jsx(
|
|
135
|
+
Button,
|
|
136
|
+
{
|
|
137
|
+
variant: "outlined",
|
|
138
|
+
color: "primary",
|
|
139
|
+
onClick: () => setDialogOpen(false),
|
|
140
|
+
sx: { width: "fit-content" },
|
|
141
|
+
children: t("common.know")
|
|
142
|
+
}
|
|
143
|
+
) })
|
|
144
|
+
] }),
|
|
145
|
+
summaryList.length === 1 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
146
|
+
/* @__PURE__ */ jsxs(Typography, { color: "text.secondary", variant: "body1", children: [
|
|
147
|
+
t("payment.subscription.overdue.title", {
|
|
148
|
+
// @ts-ignore
|
|
149
|
+
name: data?.subscription?.description,
|
|
150
|
+
count: data?.invoices?.length,
|
|
151
|
+
total: formatAmount(summaryList[0]?.amount, summaryList[0]?.currency?.decimal),
|
|
152
|
+
symbol: summaryList[0]?.currency?.symbol
|
|
153
|
+
}),
|
|
154
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
155
|
+
t("payment.subscription.overdue.description"),
|
|
156
|
+
/* @__PURE__ */ jsx(
|
|
157
|
+
"a",
|
|
158
|
+
{
|
|
159
|
+
href: subscriptionUrl,
|
|
160
|
+
target: "_blank",
|
|
161
|
+
rel: "noreferrer",
|
|
162
|
+
style: { color: "var(--foregrounds-fg-interactive, 0086FF)" },
|
|
163
|
+
children: t("payment.subscription.overdue.view")
|
|
164
|
+
}
|
|
165
|
+
)
|
|
166
|
+
] }),
|
|
167
|
+
/* @__PURE__ */ jsxs(Stack, { direction: "row", justifyContent: "flex-end", gap: 2, mt: 2, children: [
|
|
168
|
+
/* @__PURE__ */ jsx(Button, { variant: "outlined", color: "primary", onClick: () => setDialogOpen(false), children: t("common.cancel") }),
|
|
169
|
+
renderPayButton(summaryList[0])
|
|
170
|
+
] })
|
|
171
|
+
] }),
|
|
172
|
+
summaryList.length > 1 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
173
|
+
/* @__PURE__ */ jsxs(Typography, { color: "text.secondary", variant: "body1", children: [
|
|
174
|
+
t("payment.subscription.overdue.simpleTitle", {
|
|
175
|
+
// @ts-ignore
|
|
176
|
+
name: data?.subscription?.description,
|
|
177
|
+
count: data?.invoices?.length
|
|
178
|
+
}),
|
|
179
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
180
|
+
t("payment.subscription.overdue.description"),
|
|
181
|
+
/* @__PURE__ */ jsx(
|
|
182
|
+
"a",
|
|
183
|
+
{
|
|
184
|
+
href: subscriptionUrl,
|
|
185
|
+
target: "_blank",
|
|
186
|
+
rel: "noreferrer",
|
|
187
|
+
style: { color: "var(--foregrounds-fg-interactive, 0086FF)" },
|
|
188
|
+
children: t("payment.subscription.overdue.view")
|
|
189
|
+
}
|
|
190
|
+
)
|
|
191
|
+
] }),
|
|
192
|
+
/* @__PURE__ */ jsx(Typography, { color: "text.secondary", variant: "body1", children: t("payment.subscription.overdue.list") }),
|
|
193
|
+
/* @__PURE__ */ jsx(Stack, { children: summaryList.map((item) => /* @__PURE__ */ jsxs(
|
|
194
|
+
Stack,
|
|
195
|
+
{
|
|
196
|
+
direction: "row",
|
|
197
|
+
justifyContent: "space-between",
|
|
198
|
+
alignItems: "center",
|
|
199
|
+
sx: {
|
|
200
|
+
py: 1,
|
|
201
|
+
px: 0.5,
|
|
202
|
+
borderBottom: "1px solid var(--foregrounds-fg-border, #E0E0E0)",
|
|
203
|
+
"&:hover": {
|
|
204
|
+
background: "var(--backgrounds-bg-highlight, #eff6ff)"
|
|
205
|
+
},
|
|
206
|
+
mt: 0
|
|
207
|
+
},
|
|
208
|
+
children: [
|
|
209
|
+
/* @__PURE__ */ jsx(Typography, { children: t("payment.subscription.overdue.total", {
|
|
210
|
+
total: formatAmount(item?.amount, item?.currency?.decimal),
|
|
211
|
+
currency: item?.currency?.symbol
|
|
212
|
+
}) }),
|
|
213
|
+
renderPayButton(item, {
|
|
214
|
+
variant: "text",
|
|
215
|
+
sx: {
|
|
216
|
+
color: "text.link"
|
|
217
|
+
}
|
|
218
|
+
})
|
|
219
|
+
]
|
|
220
|
+
},
|
|
221
|
+
item?.currency?.id
|
|
222
|
+
)) })
|
|
223
|
+
] })
|
|
224
|
+
] })
|
|
225
|
+
}
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
OverdueInvoicePayment.defaultProps = {
|
|
229
|
+
mode: "default",
|
|
230
|
+
onPaid: () => {
|
|
231
|
+
},
|
|
232
|
+
dialogProps: {
|
|
233
|
+
open: true
|
|
234
|
+
},
|
|
235
|
+
children: null
|
|
236
|
+
};
|
|
237
|
+
export default OverdueInvoicePayment;
|
package/es/index.d.ts
CHANGED
|
@@ -28,6 +28,7 @@ import CountrySelect from './components/country-select';
|
|
|
28
28
|
import TruncatedText from './components/truncated-text';
|
|
29
29
|
import Link from './components/link';
|
|
30
30
|
import { createLazyComponent } from './components/lazy-loader';
|
|
31
|
+
import OverdueInvoicePayment from './components/over-due-invoice-payment';
|
|
31
32
|
export { PaymentThemeProvider } from './theme';
|
|
32
33
|
export * from './libs/util';
|
|
33
34
|
export * from './libs/connect';
|
|
@@ -38,4 +39,4 @@ export * from './hooks/mobile';
|
|
|
38
39
|
export * from './hooks/table';
|
|
39
40
|
export * from './hooks/scroll';
|
|
40
41
|
export { translations, createTranslator } from './locales';
|
|
41
|
-
export { createLazyComponent, api, dayjs, FormInput, PhoneInput, AddressForm, StripeForm, Status, Livemode, Switch, ConfirmDialog, CheckoutForm, CheckoutTable, CheckoutDonate, CurrencySelector, Payment, PaymentSummary, PricingTable, ProductSkeleton, Amount, CustomerInvoiceList, CustomerPaymentList, TxLink, TxGas, SafeGuard, PricingItem, CountrySelect, Table, TruncatedText, Link, };
|
|
42
|
+
export { createLazyComponent, api, dayjs, FormInput, PhoneInput, AddressForm, StripeForm, Status, Livemode, Switch, ConfirmDialog, CheckoutForm, CheckoutTable, CheckoutDonate, CurrencySelector, Payment, PaymentSummary, PricingTable, ProductSkeleton, Amount, CustomerInvoiceList, CustomerPaymentList, TxLink, TxGas, SafeGuard, PricingItem, CountrySelect, Table, TruncatedText, Link, OverdueInvoicePayment, };
|
package/es/index.js
CHANGED
|
@@ -28,6 +28,7 @@ import CountrySelect from "./components/country-select.js";
|
|
|
28
28
|
import TruncatedText from "./components/truncated-text.js";
|
|
29
29
|
import Link from "./components/link.js";
|
|
30
30
|
import { createLazyComponent } from "./components/lazy-loader.js";
|
|
31
|
+
import OverdueInvoicePayment from "./components/over-due-invoice-payment.js";
|
|
31
32
|
export { PaymentThemeProvider } from "./theme/index.js";
|
|
32
33
|
export * from "./libs/util.js";
|
|
33
34
|
export * from "./libs/connect.js";
|
|
@@ -68,5 +69,6 @@ export {
|
|
|
68
69
|
CountrySelect,
|
|
69
70
|
Table,
|
|
70
71
|
TruncatedText,
|
|
71
|
-
Link
|
|
72
|
+
Link,
|
|
73
|
+
OverdueInvoicePayment
|
|
72
74
|
};
|
package/es/locales/en.js
CHANGED
|
@@ -90,7 +90,8 @@ export default flat({
|
|
|
90
90
|
amountPrecisionLimit: "Amount decimal places must be less than or equal to {precision}",
|
|
91
91
|
saveAsDefaultPriceSuccess: "Set default price successfully",
|
|
92
92
|
stakeAmount: "Stake Amount",
|
|
93
|
-
slashStakeAmount: "Slash Stake Amount"
|
|
93
|
+
slashStakeAmount: "Slash Stake Amount",
|
|
94
|
+
know: "I know"
|
|
94
95
|
},
|
|
95
96
|
payment: {
|
|
96
97
|
checkout: {
|
|
@@ -316,6 +317,21 @@ export default flat({
|
|
|
316
317
|
recharge: "Add funds",
|
|
317
318
|
rechargeForSubscription: "Add funds for subscription"
|
|
318
319
|
}
|
|
320
|
+
},
|
|
321
|
+
subscription: {
|
|
322
|
+
overdue: {
|
|
323
|
+
simpleTitle: "There are {count} due invoices for your subscription {name}, you need to pay them to activate your subscription or before making new purchases.",
|
|
324
|
+
title: "There are {count} due invoices for your subscription {name}, the total due amount is {total} {symbol}, you need to pay them to activate your subscription or before making new purchases.",
|
|
325
|
+
payNow: "Pay Now",
|
|
326
|
+
notSupport: "This payment method is not supported",
|
|
327
|
+
total: "Total {total} {currency}",
|
|
328
|
+
view: "View Subscription Details",
|
|
329
|
+
viewNow: "View Now",
|
|
330
|
+
pastDue: "Past Due Invoices",
|
|
331
|
+
description: "If you have any questions, you can choose ",
|
|
332
|
+
list: "Past Due Invoices:",
|
|
333
|
+
empty: "There are no overdue invoices for your subscription {name}."
|
|
334
|
+
}
|
|
319
335
|
}
|
|
320
336
|
},
|
|
321
337
|
refund: {
|
package/es/locales/zh.js
CHANGED
|
@@ -90,7 +90,8 @@ export default flat({
|
|
|
90
90
|
amountPrecisionLimit: "\u91D1\u989D\u5C0F\u6570\u4F4D\u6570\u5FC5\u987B\u5728 {precision} \u4F4D\u4EE5\u5185",
|
|
91
91
|
saveAsDefaultPriceSuccess: "\u8BBE\u7F6E\u9ED8\u8BA4\u4EF7\u683C\u6210\u529F",
|
|
92
92
|
stakeAmount: "\u8D28\u62BC\u91D1\u989D",
|
|
93
|
-
slashStakeAmount: "\u7F5A\u6CA1\u91D1\u989D"
|
|
93
|
+
slashStakeAmount: "\u7F5A\u6CA1\u91D1\u989D",
|
|
94
|
+
know: "\u6211\u77E5\u9053\u4E86"
|
|
94
95
|
},
|
|
95
96
|
payment: {
|
|
96
97
|
checkout: {
|
|
@@ -316,6 +317,21 @@ export default flat({
|
|
|
316
317
|
recharge: "\u5145\u503C",
|
|
317
318
|
rechargeForSubscription: "\u8BA2\u9605\u5145\u503C"
|
|
318
319
|
}
|
|
320
|
+
},
|
|
321
|
+
subscription: {
|
|
322
|
+
overdue: {
|
|
323
|
+
title: "\u60A8\u7684\u3010{name}\u3011\u8BA2\u9605\u5171\u6709 {count} \u5F20\u6B20\u8D39\u8D26\u5355\uFF0C\u603B\u8BA1 {total} {symbol}\uFF0C\u60A8\u9700\u8981\u652F\u4ED8\u8FD9\u4E9B\u8D26\u5355\u4EE5\u6FC0\u6D3B\u60A8\u7684\u8BA2\u9605\uFF0C\u6216\u5728\u8FDB\u884C\u65B0\u7684\u8D2D\u4E70\u4E4B\u524D\u5B8C\u6210\u652F\u4ED8\u3002",
|
|
324
|
+
simpleTitle: "\u60A8\u7684\u3010{name}\u3011\u8BA2\u9605\u5171\u6709 {count} \u5F20\u6B20\u8D39\u8D26\u5355\uFF0C\u60A8\u9700\u8981\u652F\u4ED8\u8FD9\u4E9B\u8D26\u5355\u4EE5\u6FC0\u6D3B\u60A8\u7684\u8BA2\u9605\uFF0C\u6216\u5728\u8FDB\u884C\u65B0\u7684\u8D2D\u4E70\u4E4B\u524D\u5B8C\u6210\u652F\u4ED8\u3002",
|
|
325
|
+
payNow: "\u7ACB\u5373\u652F\u4ED8",
|
|
326
|
+
notSupport: "\u6682\u4E0D\u652F\u6301\u8BE5\u652F\u4ED8\u65B9\u5F0F",
|
|
327
|
+
total: "\u603B\u8BA1 {total} {currency}",
|
|
328
|
+
view: "\u67E5\u770B\u8BA2\u9605\u8BE6\u60C5",
|
|
329
|
+
pastDue: "\u6B20\u8D39\u8D26\u5355",
|
|
330
|
+
viewNow: "\u7ACB\u5373\u67E5\u770B",
|
|
331
|
+
description: "\u5982\u679C\u60A8\u6709\u4EFB\u4F55\u7591\u95EE\uFF0C\u53EF\u4EE5\u9009\u62E9 ",
|
|
332
|
+
list: "\u6B20\u8D39\u8D26\u5355\uFF1A",
|
|
333
|
+
empty: "\u60A8\u7684\u3010{name}\u3011\u8BA2\u9605\u5F53\u524D\u6CA1\u6709\u6B20\u8D39\u8D26\u5355"
|
|
334
|
+
}
|
|
319
335
|
}
|
|
320
336
|
},
|
|
321
337
|
refund: {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { Invoice, PaymentCurrency, PaymentMethod, Subscription } from '@blocklet/payment-types';
|
|
3
|
+
type DialogProps = {
|
|
4
|
+
open?: boolean;
|
|
5
|
+
onClose?: () => void;
|
|
6
|
+
title?: string;
|
|
7
|
+
};
|
|
8
|
+
type Props = {
|
|
9
|
+
subscriptionId: string;
|
|
10
|
+
mode?: 'default' | 'custom';
|
|
11
|
+
onPaid?: (subscriptionId: string, currencyId: string) => void;
|
|
12
|
+
dialogProps?: DialogProps;
|
|
13
|
+
children?: (handlePay: (item: SummaryItem) => void, data: {
|
|
14
|
+
subscription: Subscription;
|
|
15
|
+
summary: {
|
|
16
|
+
[key: string]: SummaryItem;
|
|
17
|
+
};
|
|
18
|
+
invoices: Invoice[];
|
|
19
|
+
subscriptionUrl: string;
|
|
20
|
+
}) => React.ReactNode;
|
|
21
|
+
};
|
|
22
|
+
type SummaryItem = {
|
|
23
|
+
amount: string;
|
|
24
|
+
currency: PaymentCurrency;
|
|
25
|
+
method: PaymentMethod;
|
|
26
|
+
};
|
|
27
|
+
declare function OverdueInvoicePayment({ subscriptionId, mode, dialogProps, children, onPaid, }: Props): import("react").JSX.Element;
|
|
28
|
+
declare namespace OverdueInvoicePayment {
|
|
29
|
+
var defaultProps: {
|
|
30
|
+
mode: string;
|
|
31
|
+
onPaid: () => void;
|
|
32
|
+
dialogProps: {
|
|
33
|
+
open: boolean;
|
|
34
|
+
};
|
|
35
|
+
children: null;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export default OverdueInvoicePayment;
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
8
|
+
var _react = require("react");
|
|
9
|
+
var _material = require("@mui/material");
|
|
10
|
+
var _context = require("@arcblock/ux/lib/Locale/context");
|
|
11
|
+
var _Toast = _interopRequireDefault(require("@arcblock/ux/lib/Toast"));
|
|
12
|
+
var _ufo = require("ufo");
|
|
13
|
+
var _ahooks = require("ahooks");
|
|
14
|
+
var _ux = require("@arcblock/ux");
|
|
15
|
+
var _payment = require("../contexts/payment");
|
|
16
|
+
var _util = require("../libs/util");
|
|
17
|
+
var _subscription = require("../hooks/subscription");
|
|
18
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
19
|
+
const fetchOverdueInvoices = async subscriptionId => {
|
|
20
|
+
const res = await fetch(`/api/subscriptions/${subscriptionId}/overdue/invoices`);
|
|
21
|
+
return res.json();
|
|
22
|
+
};
|
|
23
|
+
function OverdueInvoicePayment({
|
|
24
|
+
subscriptionId,
|
|
25
|
+
mode = "default",
|
|
26
|
+
dialogProps = {},
|
|
27
|
+
children,
|
|
28
|
+
onPaid = () => {}
|
|
29
|
+
}) {
|
|
30
|
+
const {
|
|
31
|
+
t
|
|
32
|
+
} = (0, _context.useLocaleContext)();
|
|
33
|
+
const {
|
|
34
|
+
connect
|
|
35
|
+
} = (0, _payment.usePaymentContext)();
|
|
36
|
+
const [selectCurrencyId, setSelectCurrencyId] = (0, _react.useState)("");
|
|
37
|
+
const [payLoading, setPayLoading] = (0, _react.useState)(false);
|
|
38
|
+
const [dialogOpen, setDialogOpen] = (0, _react.useState)(dialogProps.open || false);
|
|
39
|
+
const [processedCurrencies, setProcessedCurrencies] = (0, _react.useState)({});
|
|
40
|
+
const {
|
|
41
|
+
data = {
|
|
42
|
+
subscription: {},
|
|
43
|
+
summary: {},
|
|
44
|
+
invoices: []
|
|
45
|
+
},
|
|
46
|
+
error,
|
|
47
|
+
loading,
|
|
48
|
+
runAsync: refresh
|
|
49
|
+
} = (0, _ahooks.useRequest)(() => fetchOverdueInvoices(subscriptionId));
|
|
50
|
+
const subscriptionUrl = (0, _ufo.joinURL)((0, _util.getPrefix)(), `/customer/subscription/${subscriptionId}`);
|
|
51
|
+
const summaryList = (0, _react.useMemo)(() => {
|
|
52
|
+
if (!data?.summary) {
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
return Object.values(data.summary);
|
|
56
|
+
}, [data?.summary]);
|
|
57
|
+
const subscription = (0, _subscription.useSubscription)("events");
|
|
58
|
+
(0, _react.useEffect)(() => {
|
|
59
|
+
if (subscription) {
|
|
60
|
+
subscription.on("invoice.paid", ({
|
|
61
|
+
response
|
|
62
|
+
}) => {
|
|
63
|
+
const uniqueKey = `${response.subscription_id}-${response.currency_id}`;
|
|
64
|
+
if (response.subscription_id === subscriptionId && !processedCurrencies[uniqueKey]) {
|
|
65
|
+
_Toast.default.success(t("payment.customer.invoice.paySuccess"));
|
|
66
|
+
setPayLoading(false);
|
|
67
|
+
setProcessedCurrencies({
|
|
68
|
+
...processedCurrencies,
|
|
69
|
+
[uniqueKey]: 1
|
|
70
|
+
});
|
|
71
|
+
refresh().then(res => {
|
|
72
|
+
if (res.invoices?.length === 0) {
|
|
73
|
+
setDialogOpen(false);
|
|
74
|
+
onPaid(subscriptionId, response.currency_id);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}, [subscription]);
|
|
81
|
+
const handlePay = item => {
|
|
82
|
+
const {
|
|
83
|
+
currency,
|
|
84
|
+
method
|
|
85
|
+
} = item;
|
|
86
|
+
if (method.type === "stripe") {
|
|
87
|
+
_Toast.default.error(t("payment.subscription.overdue.notSupport"));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (payLoading) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
setSelectCurrencyId(currency.id);
|
|
94
|
+
setPayLoading(true);
|
|
95
|
+
if (method.type === "arcblock" || method.type === "ethereum") {
|
|
96
|
+
connect.open({
|
|
97
|
+
containerEl: void 0,
|
|
98
|
+
saveConnect: false,
|
|
99
|
+
action: "collect-batch",
|
|
100
|
+
prefix: (0, _ufo.joinURL)("/api/did"),
|
|
101
|
+
extraParams: {
|
|
102
|
+
currencyId: currency.id,
|
|
103
|
+
subscriptionId
|
|
104
|
+
},
|
|
105
|
+
onSuccess: () => {
|
|
106
|
+
connect.close();
|
|
107
|
+
},
|
|
108
|
+
onClose: () => {
|
|
109
|
+
connect.close();
|
|
110
|
+
setPayLoading(false);
|
|
111
|
+
},
|
|
112
|
+
onError: err => {
|
|
113
|
+
_Toast.default.error((0, _util.formatError)(err));
|
|
114
|
+
setPayLoading(false);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
if (loading) {
|
|
120
|
+
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.CircularProgress, {});
|
|
121
|
+
}
|
|
122
|
+
const renderPayButton = (item, props) => {
|
|
123
|
+
const isPayLoading = payLoading && item.currency.id === selectCurrencyId;
|
|
124
|
+
if (item.method.type === "stripe") {
|
|
125
|
+
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
|
|
126
|
+
variant: "contained",
|
|
127
|
+
color: "primary",
|
|
128
|
+
onClick: () => window.open(subscriptionUrl, "_blank"),
|
|
129
|
+
...props,
|
|
130
|
+
children: t("payment.subscription.overdue.viewNow")
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Button, {
|
|
134
|
+
variant: "contained",
|
|
135
|
+
color: "primary",
|
|
136
|
+
onClick: () => handlePay(item),
|
|
137
|
+
...props,
|
|
138
|
+
disabled: isPayLoading,
|
|
139
|
+
children: [isPayLoading && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.CircularProgress, {
|
|
140
|
+
size: 14,
|
|
141
|
+
sx: {
|
|
142
|
+
mr: 1,
|
|
143
|
+
color: "text.lighter"
|
|
144
|
+
}
|
|
145
|
+
}), t("payment.subscription.overdue.payNow")]
|
|
146
|
+
});
|
|
147
|
+
};
|
|
148
|
+
if (mode === "custom" && children && typeof children === "function") {
|
|
149
|
+
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Stack, {
|
|
150
|
+
children: children(handlePay, {
|
|
151
|
+
subscription: data?.subscription,
|
|
152
|
+
subscriptionUrl,
|
|
153
|
+
summary: data?.summary,
|
|
154
|
+
invoices: data?.invoices
|
|
155
|
+
})
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_ux.Dialog, {
|
|
159
|
+
open: dialogOpen,
|
|
160
|
+
onClose: () => setDialogOpen(false),
|
|
161
|
+
title: dialogProps.title || t("payment.subscription.overdue.pastDue"),
|
|
162
|
+
PaperProps: {
|
|
163
|
+
style: {
|
|
164
|
+
minHeight: "auto"
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
children: error ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Alert, {
|
|
168
|
+
severity: "error",
|
|
169
|
+
children: error.message
|
|
170
|
+
}) : /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
171
|
+
gap: 1,
|
|
172
|
+
children: [summaryList.length === 0 && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
173
|
+
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Alert, {
|
|
174
|
+
severity: "success",
|
|
175
|
+
children: t("payment.subscription.overdue.empty", {
|
|
176
|
+
// @ts-ignore
|
|
177
|
+
name: data?.subscription?.description
|
|
178
|
+
})
|
|
179
|
+
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Stack, {
|
|
180
|
+
direction: "row",
|
|
181
|
+
justifyContent: "flex-end",
|
|
182
|
+
mt: 2,
|
|
183
|
+
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
|
|
184
|
+
variant: "outlined",
|
|
185
|
+
color: "primary",
|
|
186
|
+
onClick: () => setDialogOpen(false),
|
|
187
|
+
sx: {
|
|
188
|
+
width: "fit-content"
|
|
189
|
+
},
|
|
190
|
+
children: t("common.know")
|
|
191
|
+
})
|
|
192
|
+
})]
|
|
193
|
+
}), summaryList.length === 1 && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
194
|
+
children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, {
|
|
195
|
+
color: "text.secondary",
|
|
196
|
+
variant: "body1",
|
|
197
|
+
children: [t("payment.subscription.overdue.title", {
|
|
198
|
+
// @ts-ignore
|
|
199
|
+
name: data?.subscription?.description,
|
|
200
|
+
count: data?.invoices?.length,
|
|
201
|
+
total: (0, _util.formatAmount)(summaryList[0]?.amount, summaryList[0]?.currency?.decimal),
|
|
202
|
+
symbol: summaryList[0]?.currency?.symbol
|
|
203
|
+
}), /* @__PURE__ */(0, _jsxRuntime.jsx)("br", {}), t("payment.subscription.overdue.description"), /* @__PURE__ */(0, _jsxRuntime.jsx)("a", {
|
|
204
|
+
href: subscriptionUrl,
|
|
205
|
+
target: "_blank",
|
|
206
|
+
rel: "noreferrer",
|
|
207
|
+
style: {
|
|
208
|
+
color: "var(--foregrounds-fg-interactive, 0086FF)"
|
|
209
|
+
},
|
|
210
|
+
children: t("payment.subscription.overdue.view")
|
|
211
|
+
})]
|
|
212
|
+
}), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
213
|
+
direction: "row",
|
|
214
|
+
justifyContent: "flex-end",
|
|
215
|
+
gap: 2,
|
|
216
|
+
mt: 2,
|
|
217
|
+
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
|
|
218
|
+
variant: "outlined",
|
|
219
|
+
color: "primary",
|
|
220
|
+
onClick: () => setDialogOpen(false),
|
|
221
|
+
children: t("common.cancel")
|
|
222
|
+
}), renderPayButton(summaryList[0])]
|
|
223
|
+
})]
|
|
224
|
+
}), summaryList.length > 1 && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
225
|
+
children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, {
|
|
226
|
+
color: "text.secondary",
|
|
227
|
+
variant: "body1",
|
|
228
|
+
children: [t("payment.subscription.overdue.simpleTitle", {
|
|
229
|
+
// @ts-ignore
|
|
230
|
+
name: data?.subscription?.description,
|
|
231
|
+
count: data?.invoices?.length
|
|
232
|
+
}), /* @__PURE__ */(0, _jsxRuntime.jsx)("br", {}), t("payment.subscription.overdue.description"), /* @__PURE__ */(0, _jsxRuntime.jsx)("a", {
|
|
233
|
+
href: subscriptionUrl,
|
|
234
|
+
target: "_blank",
|
|
235
|
+
rel: "noreferrer",
|
|
236
|
+
style: {
|
|
237
|
+
color: "var(--foregrounds-fg-interactive, 0086FF)"
|
|
238
|
+
},
|
|
239
|
+
children: t("payment.subscription.overdue.view")
|
|
240
|
+
})]
|
|
241
|
+
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
242
|
+
color: "text.secondary",
|
|
243
|
+
variant: "body1",
|
|
244
|
+
children: t("payment.subscription.overdue.list")
|
|
245
|
+
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Stack, {
|
|
246
|
+
children: summaryList.map(item => /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
247
|
+
direction: "row",
|
|
248
|
+
justifyContent: "space-between",
|
|
249
|
+
alignItems: "center",
|
|
250
|
+
sx: {
|
|
251
|
+
py: 1,
|
|
252
|
+
px: 0.5,
|
|
253
|
+
borderBottom: "1px solid var(--foregrounds-fg-border, #E0E0E0)",
|
|
254
|
+
"&:hover": {
|
|
255
|
+
background: "var(--backgrounds-bg-highlight, #eff6ff)"
|
|
256
|
+
},
|
|
257
|
+
mt: 0
|
|
258
|
+
},
|
|
259
|
+
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
260
|
+
children: t("payment.subscription.overdue.total", {
|
|
261
|
+
total: (0, _util.formatAmount)(item?.amount, item?.currency?.decimal),
|
|
262
|
+
currency: item?.currency?.symbol
|
|
263
|
+
})
|
|
264
|
+
}), renderPayButton(item, {
|
|
265
|
+
variant: "text",
|
|
266
|
+
sx: {
|
|
267
|
+
color: "text.link"
|
|
268
|
+
}
|
|
269
|
+
})]
|
|
270
|
+
}, item?.currency?.id))
|
|
271
|
+
})]
|
|
272
|
+
})]
|
|
273
|
+
})
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
OverdueInvoicePayment.defaultProps = {
|
|
277
|
+
mode: "default",
|
|
278
|
+
onPaid: () => {},
|
|
279
|
+
dialogProps: {
|
|
280
|
+
open: true
|
|
281
|
+
},
|
|
282
|
+
children: null
|
|
283
|
+
};
|
|
284
|
+
module.exports = OverdueInvoicePayment;
|
package/lib/index.d.ts
CHANGED
|
@@ -28,6 +28,7 @@ import CountrySelect from './components/country-select';
|
|
|
28
28
|
import TruncatedText from './components/truncated-text';
|
|
29
29
|
import Link from './components/link';
|
|
30
30
|
import { createLazyComponent } from './components/lazy-loader';
|
|
31
|
+
import OverdueInvoicePayment from './components/over-due-invoice-payment';
|
|
31
32
|
export { PaymentThemeProvider } from './theme';
|
|
32
33
|
export * from './libs/util';
|
|
33
34
|
export * from './libs/connect';
|
|
@@ -38,4 +39,4 @@ export * from './hooks/mobile';
|
|
|
38
39
|
export * from './hooks/table';
|
|
39
40
|
export * from './hooks/scroll';
|
|
40
41
|
export { translations, createTranslator } from './locales';
|
|
41
|
-
export { createLazyComponent, api, dayjs, FormInput, PhoneInput, AddressForm, StripeForm, Status, Livemode, Switch, ConfirmDialog, CheckoutForm, CheckoutTable, CheckoutDonate, CurrencySelector, Payment, PaymentSummary, PricingTable, ProductSkeleton, Amount, CustomerInvoiceList, CustomerPaymentList, TxLink, TxGas, SafeGuard, PricingItem, CountrySelect, Table, TruncatedText, Link, };
|
|
42
|
+
export { createLazyComponent, api, dayjs, FormInput, PhoneInput, AddressForm, StripeForm, Status, Livemode, Switch, ConfirmDialog, CheckoutForm, CheckoutTable, CheckoutDonate, CurrencySelector, Payment, PaymentSummary, PricingTable, ProductSkeleton, Amount, CustomerInvoiceList, CustomerPaymentList, TxLink, TxGas, SafeGuard, PricingItem, CountrySelect, Table, TruncatedText, Link, OverdueInvoicePayment, };
|
package/lib/index.js
CHANGED
|
@@ -34,6 +34,7 @@ var _exportNames = {
|
|
|
34
34
|
TruncatedText: true,
|
|
35
35
|
Link: true,
|
|
36
36
|
createLazyComponent: true,
|
|
37
|
+
OverdueInvoicePayment: true,
|
|
37
38
|
PaymentThemeProvider: true,
|
|
38
39
|
translations: true,
|
|
39
40
|
createTranslator: true
|
|
@@ -116,6 +117,12 @@ Object.defineProperty(exports, "Livemode", {
|
|
|
116
117
|
return _livemode.default;
|
|
117
118
|
}
|
|
118
119
|
});
|
|
120
|
+
Object.defineProperty(exports, "OverdueInvoicePayment", {
|
|
121
|
+
enumerable: true,
|
|
122
|
+
get: function () {
|
|
123
|
+
return _overDueInvoicePayment.default;
|
|
124
|
+
}
|
|
125
|
+
});
|
|
119
126
|
Object.defineProperty(exports, "Payment", {
|
|
120
127
|
enumerable: true,
|
|
121
128
|
get: function () {
|
|
@@ -266,6 +273,7 @@ var _countrySelect = _interopRequireDefault(require("./components/country-select
|
|
|
266
273
|
var _truncatedText = _interopRequireDefault(require("./components/truncated-text"));
|
|
267
274
|
var _link = _interopRequireDefault(require("./components/link"));
|
|
268
275
|
var _lazyLoader = require("./components/lazy-loader");
|
|
276
|
+
var _overDueInvoicePayment = _interopRequireDefault(require("./components/over-due-invoice-payment"));
|
|
269
277
|
var _theme = require("./theme");
|
|
270
278
|
var _util = require("./libs/util");
|
|
271
279
|
Object.keys(_util).forEach(function (key) {
|
package/lib/locales/en.js
CHANGED
|
@@ -97,7 +97,8 @@ module.exports = (0, _flat.default)({
|
|
|
97
97
|
amountPrecisionLimit: "Amount decimal places must be less than or equal to {precision}",
|
|
98
98
|
saveAsDefaultPriceSuccess: "Set default price successfully",
|
|
99
99
|
stakeAmount: "Stake Amount",
|
|
100
|
-
slashStakeAmount: "Slash Stake Amount"
|
|
100
|
+
slashStakeAmount: "Slash Stake Amount",
|
|
101
|
+
know: "I know"
|
|
101
102
|
},
|
|
102
103
|
payment: {
|
|
103
104
|
checkout: {
|
|
@@ -323,6 +324,21 @@ module.exports = (0, _flat.default)({
|
|
|
323
324
|
recharge: "Add funds",
|
|
324
325
|
rechargeForSubscription: "Add funds for subscription"
|
|
325
326
|
}
|
|
327
|
+
},
|
|
328
|
+
subscription: {
|
|
329
|
+
overdue: {
|
|
330
|
+
simpleTitle: "There are {count} due invoices for your subscription {name}, you need to pay them to activate your subscription or before making new purchases.",
|
|
331
|
+
title: "There are {count} due invoices for your subscription {name}, the total due amount is {total} {symbol}, you need to pay them to activate your subscription or before making new purchases.",
|
|
332
|
+
payNow: "Pay Now",
|
|
333
|
+
notSupport: "This payment method is not supported",
|
|
334
|
+
total: "Total {total} {currency}",
|
|
335
|
+
view: "View Subscription Details",
|
|
336
|
+
viewNow: "View Now",
|
|
337
|
+
pastDue: "Past Due Invoices",
|
|
338
|
+
description: "If you have any questions, you can choose ",
|
|
339
|
+
list: "Past Due Invoices:",
|
|
340
|
+
empty: "There are no overdue invoices for your subscription {name}."
|
|
341
|
+
}
|
|
326
342
|
}
|
|
327
343
|
},
|
|
328
344
|
refund: {
|
package/lib/locales/zh.js
CHANGED
|
@@ -97,7 +97,8 @@ module.exports = (0, _flat.default)({
|
|
|
97
97
|
amountPrecisionLimit: "\u91D1\u989D\u5C0F\u6570\u4F4D\u6570\u5FC5\u987B\u5728 {precision} \u4F4D\u4EE5\u5185",
|
|
98
98
|
saveAsDefaultPriceSuccess: "\u8BBE\u7F6E\u9ED8\u8BA4\u4EF7\u683C\u6210\u529F",
|
|
99
99
|
stakeAmount: "\u8D28\u62BC\u91D1\u989D",
|
|
100
|
-
slashStakeAmount: "\u7F5A\u6CA1\u91D1\u989D"
|
|
100
|
+
slashStakeAmount: "\u7F5A\u6CA1\u91D1\u989D",
|
|
101
|
+
know: "\u6211\u77E5\u9053\u4E86"
|
|
101
102
|
},
|
|
102
103
|
payment: {
|
|
103
104
|
checkout: {
|
|
@@ -323,6 +324,21 @@ module.exports = (0, _flat.default)({
|
|
|
323
324
|
recharge: "\u5145\u503C",
|
|
324
325
|
rechargeForSubscription: "\u8BA2\u9605\u5145\u503C"
|
|
325
326
|
}
|
|
327
|
+
},
|
|
328
|
+
subscription: {
|
|
329
|
+
overdue: {
|
|
330
|
+
title: "\u60A8\u7684\u3010{name}\u3011\u8BA2\u9605\u5171\u6709 {count} \u5F20\u6B20\u8D39\u8D26\u5355\uFF0C\u603B\u8BA1 {total} {symbol}\uFF0C\u60A8\u9700\u8981\u652F\u4ED8\u8FD9\u4E9B\u8D26\u5355\u4EE5\u6FC0\u6D3B\u60A8\u7684\u8BA2\u9605\uFF0C\u6216\u5728\u8FDB\u884C\u65B0\u7684\u8D2D\u4E70\u4E4B\u524D\u5B8C\u6210\u652F\u4ED8\u3002",
|
|
331
|
+
simpleTitle: "\u60A8\u7684\u3010{name}\u3011\u8BA2\u9605\u5171\u6709 {count} \u5F20\u6B20\u8D39\u8D26\u5355\uFF0C\u60A8\u9700\u8981\u652F\u4ED8\u8FD9\u4E9B\u8D26\u5355\u4EE5\u6FC0\u6D3B\u60A8\u7684\u8BA2\u9605\uFF0C\u6216\u5728\u8FDB\u884C\u65B0\u7684\u8D2D\u4E70\u4E4B\u524D\u5B8C\u6210\u652F\u4ED8\u3002",
|
|
332
|
+
payNow: "\u7ACB\u5373\u652F\u4ED8",
|
|
333
|
+
notSupport: "\u6682\u4E0D\u652F\u6301\u8BE5\u652F\u4ED8\u65B9\u5F0F",
|
|
334
|
+
total: "\u603B\u8BA1 {total} {currency}",
|
|
335
|
+
view: "\u67E5\u770B\u8BA2\u9605\u8BE6\u60C5",
|
|
336
|
+
pastDue: "\u6B20\u8D39\u8D26\u5355",
|
|
337
|
+
viewNow: "\u7ACB\u5373\u67E5\u770B",
|
|
338
|
+
description: "\u5982\u679C\u60A8\u6709\u4EFB\u4F55\u7591\u95EE\uFF0C\u53EF\u4EE5\u9009\u62E9 ",
|
|
339
|
+
list: "\u6B20\u8D39\u8D26\u5355\uFF1A",
|
|
340
|
+
empty: "\u60A8\u7684\u3010{name}\u3011\u8BA2\u9605\u5F53\u524D\u6CA1\u6709\u6B20\u8D39\u8D26\u5355"
|
|
341
|
+
}
|
|
326
342
|
}
|
|
327
343
|
},
|
|
328
344
|
refund: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/payment-react",
|
|
3
|
-
"version": "1.16.
|
|
3
|
+
"version": "1.16.4",
|
|
4
4
|
"description": "Reusable react components for payment kit v2",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"@babel/core": "^7.25.2",
|
|
93
93
|
"@babel/preset-env": "^7.25.2",
|
|
94
94
|
"@babel/preset-react": "^7.24.7",
|
|
95
|
-
"@blocklet/payment-types": "1.16.
|
|
95
|
+
"@blocklet/payment-types": "1.16.4",
|
|
96
96
|
"@storybook/addon-essentials": "^7.6.20",
|
|
97
97
|
"@storybook/addon-interactions": "^7.6.20",
|
|
98
98
|
"@storybook/addon-links": "^7.6.20",
|
|
@@ -122,5 +122,5 @@
|
|
|
122
122
|
"vite-plugin-babel": "^1.2.0",
|
|
123
123
|
"vite-plugin-node-polyfills": "^0.21.0"
|
|
124
124
|
},
|
|
125
|
-
"gitHead": "
|
|
125
|
+
"gitHead": "d2c53c8bec3a4a34d0ef3a011ec215b69bc9a5ab"
|
|
126
126
|
}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import { Button, Typography, Stack, CircularProgress, Alert } from '@mui/material';
|
|
3
|
+
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
4
|
+
import Toast from '@arcblock/ux/lib/Toast';
|
|
5
|
+
import { joinURL } from 'ufo';
|
|
6
|
+
import type { Invoice, PaymentCurrency, PaymentMethod, Subscription, TInvoiceExpanded } from '@blocklet/payment-types';
|
|
7
|
+
import { useRequest } from 'ahooks';
|
|
8
|
+
import { Dialog } from '@arcblock/ux';
|
|
9
|
+
import { usePaymentContext } from '../contexts/payment';
|
|
10
|
+
import { formatAmount, formatError, getPrefix } from '../libs/util';
|
|
11
|
+
import { useSubscription } from '../hooks/subscription';
|
|
12
|
+
|
|
13
|
+
type DialogProps = {
|
|
14
|
+
open?: boolean;
|
|
15
|
+
onClose?: () => void;
|
|
16
|
+
title?: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
type Props = {
|
|
20
|
+
subscriptionId: string;
|
|
21
|
+
mode?: 'default' | 'custom';
|
|
22
|
+
onPaid?: (subscriptionId: string, currencyId: string) => void;
|
|
23
|
+
dialogProps?: DialogProps;
|
|
24
|
+
children?: (
|
|
25
|
+
handlePay: (item: SummaryItem) => void,
|
|
26
|
+
data: {
|
|
27
|
+
subscription: Subscription;
|
|
28
|
+
summary: { [key: string]: SummaryItem };
|
|
29
|
+
invoices: Invoice[];
|
|
30
|
+
subscriptionUrl: string;
|
|
31
|
+
}
|
|
32
|
+
) => React.ReactNode;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
type SummaryItem = {
|
|
36
|
+
amount: string;
|
|
37
|
+
currency: PaymentCurrency;
|
|
38
|
+
method: PaymentMethod;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const fetchOverdueInvoices = async (
|
|
42
|
+
subscriptionId: string
|
|
43
|
+
): Promise<{
|
|
44
|
+
subscription: Subscription;
|
|
45
|
+
summary: { [key: string]: SummaryItem };
|
|
46
|
+
invoices: Invoice[];
|
|
47
|
+
}> => {
|
|
48
|
+
const res = await fetch(`/api/subscriptions/${subscriptionId}/overdue/invoices`);
|
|
49
|
+
return res.json();
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
function OverdueInvoicePayment({
|
|
53
|
+
subscriptionId,
|
|
54
|
+
mode = 'default',
|
|
55
|
+
dialogProps = {},
|
|
56
|
+
children,
|
|
57
|
+
onPaid = () => {},
|
|
58
|
+
}: Props) {
|
|
59
|
+
const { t } = useLocaleContext();
|
|
60
|
+
const { connect } = usePaymentContext();
|
|
61
|
+
const [selectCurrencyId, setSelectCurrencyId] = useState('');
|
|
62
|
+
const [payLoading, setPayLoading] = useState(false);
|
|
63
|
+
const [dialogOpen, setDialogOpen] = useState(dialogProps.open || false);
|
|
64
|
+
const [processedCurrencies, setProcessedCurrencies] = useState<{ [key: string]: number }>({});
|
|
65
|
+
const {
|
|
66
|
+
data = {
|
|
67
|
+
subscription: {} as Subscription,
|
|
68
|
+
summary: {},
|
|
69
|
+
invoices: [],
|
|
70
|
+
},
|
|
71
|
+
error,
|
|
72
|
+
loading,
|
|
73
|
+
runAsync: refresh,
|
|
74
|
+
} = useRequest(() => fetchOverdueInvoices(subscriptionId));
|
|
75
|
+
|
|
76
|
+
const subscriptionUrl = joinURL(getPrefix(), `/customer/subscription/${subscriptionId}`);
|
|
77
|
+
const summaryList = useMemo(() => {
|
|
78
|
+
if (!data?.summary) {
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
return Object.values(data.summary);
|
|
82
|
+
}, [data?.summary]);
|
|
83
|
+
|
|
84
|
+
const subscription = useSubscription('events');
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
if (subscription) {
|
|
87
|
+
subscription.on('invoice.paid', ({ response }: { response: TInvoiceExpanded }) => {
|
|
88
|
+
const uniqueKey = `${response.subscription_id}-${response.currency_id}`;
|
|
89
|
+
if (response.subscription_id === subscriptionId && !processedCurrencies[uniqueKey]) {
|
|
90
|
+
Toast.success(t('payment.customer.invoice.paySuccess'));
|
|
91
|
+
setPayLoading(false);
|
|
92
|
+
setProcessedCurrencies({ ...processedCurrencies, [uniqueKey]: 1 });
|
|
93
|
+
refresh().then((res) => {
|
|
94
|
+
if (res.invoices?.length === 0) {
|
|
95
|
+
setDialogOpen(false);
|
|
96
|
+
onPaid(subscriptionId, response.currency_id);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
103
|
+
}, [subscription]);
|
|
104
|
+
|
|
105
|
+
const handlePay = (item: SummaryItem) => {
|
|
106
|
+
const { currency, method } = item;
|
|
107
|
+
if (method.type === 'stripe') {
|
|
108
|
+
Toast.error(t('payment.subscription.overdue.notSupport'));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (payLoading) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
setSelectCurrencyId(currency.id);
|
|
115
|
+
setPayLoading(true);
|
|
116
|
+
if (method.type === 'arcblock' || method.type === 'ethereum') {
|
|
117
|
+
connect.open({
|
|
118
|
+
containerEl: undefined as unknown as Element,
|
|
119
|
+
saveConnect: false,
|
|
120
|
+
action: 'collect-batch',
|
|
121
|
+
prefix: joinURL('/api/did'),
|
|
122
|
+
extraParams: { currencyId: currency.id, subscriptionId },
|
|
123
|
+
onSuccess: () => {
|
|
124
|
+
connect.close();
|
|
125
|
+
},
|
|
126
|
+
onClose: () => {
|
|
127
|
+
connect.close();
|
|
128
|
+
setPayLoading(false);
|
|
129
|
+
},
|
|
130
|
+
onError: (err: any) => {
|
|
131
|
+
Toast.error(formatError(err));
|
|
132
|
+
setPayLoading(false);
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
if (loading) {
|
|
139
|
+
return <CircularProgress />;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const renderPayButton = (item: SummaryItem, props: any) => {
|
|
143
|
+
const isPayLoading = payLoading && item.currency.id === selectCurrencyId;
|
|
144
|
+
if (item.method.type === 'stripe') {
|
|
145
|
+
return (
|
|
146
|
+
<Button variant="contained" color="primary" onClick={() => window.open(subscriptionUrl, '_blank')} {...props}>
|
|
147
|
+
{t('payment.subscription.overdue.viewNow')}
|
|
148
|
+
</Button>
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
return (
|
|
152
|
+
<Button variant="contained" color="primary" onClick={() => handlePay(item)} {...props} disabled={isPayLoading}>
|
|
153
|
+
{isPayLoading && <CircularProgress size={14} sx={{ mr: 1, color: 'text.lighter' }} />}
|
|
154
|
+
{t('payment.subscription.overdue.payNow')}
|
|
155
|
+
</Button>
|
|
156
|
+
);
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
if (mode === 'custom' && children && typeof children === 'function') {
|
|
160
|
+
return (
|
|
161
|
+
<Stack>
|
|
162
|
+
{children(handlePay, {
|
|
163
|
+
subscription: data?.subscription as Subscription,
|
|
164
|
+
subscriptionUrl,
|
|
165
|
+
summary: data?.summary as { [key: string]: SummaryItem },
|
|
166
|
+
invoices: data?.invoices as Invoice[],
|
|
167
|
+
})}
|
|
168
|
+
</Stack>
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Default mode
|
|
173
|
+
return (
|
|
174
|
+
<Dialog
|
|
175
|
+
open={dialogOpen}
|
|
176
|
+
onClose={() => setDialogOpen(false)}
|
|
177
|
+
title={dialogProps.title || t('payment.subscription.overdue.pastDue')}
|
|
178
|
+
PaperProps={{
|
|
179
|
+
style: { minHeight: 'auto' },
|
|
180
|
+
}}>
|
|
181
|
+
{error ? (
|
|
182
|
+
<Alert severity="error">{error.message}</Alert>
|
|
183
|
+
) : (
|
|
184
|
+
<Stack gap={1}>
|
|
185
|
+
{summaryList.length === 0 && (
|
|
186
|
+
<>
|
|
187
|
+
<Alert severity="success">
|
|
188
|
+
{t('payment.subscription.overdue.empty', {
|
|
189
|
+
// @ts-ignore
|
|
190
|
+
name: data?.subscription?.description,
|
|
191
|
+
})}
|
|
192
|
+
</Alert>
|
|
193
|
+
<Stack direction="row" justifyContent="flex-end" mt={2}>
|
|
194
|
+
<Button
|
|
195
|
+
variant="outlined"
|
|
196
|
+
color="primary"
|
|
197
|
+
onClick={() => setDialogOpen(false)}
|
|
198
|
+
sx={{ width: 'fit-content' }}>
|
|
199
|
+
{/* @ts-ignore */}
|
|
200
|
+
{t('common.know')}
|
|
201
|
+
</Button>
|
|
202
|
+
</Stack>
|
|
203
|
+
</>
|
|
204
|
+
)}
|
|
205
|
+
{summaryList.length === 1 && (
|
|
206
|
+
<>
|
|
207
|
+
<Typography color="text.secondary" variant="body1">
|
|
208
|
+
{t('payment.subscription.overdue.title', {
|
|
209
|
+
// @ts-ignore
|
|
210
|
+
name: data?.subscription?.description,
|
|
211
|
+
count: data?.invoices?.length,
|
|
212
|
+
total: formatAmount(summaryList[0]?.amount, summaryList[0]?.currency?.decimal),
|
|
213
|
+
symbol: summaryList[0]?.currency?.symbol,
|
|
214
|
+
})}
|
|
215
|
+
<br />
|
|
216
|
+
{t('payment.subscription.overdue.description')}
|
|
217
|
+
<a
|
|
218
|
+
href={subscriptionUrl}
|
|
219
|
+
target="_blank"
|
|
220
|
+
rel="noreferrer"
|
|
221
|
+
style={{ color: 'var(--foregrounds-fg-interactive, 0086FF)' }}>
|
|
222
|
+
{t('payment.subscription.overdue.view')}
|
|
223
|
+
</a>
|
|
224
|
+
</Typography>
|
|
225
|
+
<Stack direction="row" justifyContent="flex-end" gap={2} mt={2}>
|
|
226
|
+
<Button variant="outlined" color="primary" onClick={() => setDialogOpen(false)}>
|
|
227
|
+
{/* @ts-ignore */}
|
|
228
|
+
{t('common.cancel')}
|
|
229
|
+
</Button>
|
|
230
|
+
{/* @ts-ignore */}
|
|
231
|
+
{renderPayButton(summaryList[0])}
|
|
232
|
+
</Stack>
|
|
233
|
+
</>
|
|
234
|
+
)}
|
|
235
|
+
{summaryList.length > 1 && (
|
|
236
|
+
<>
|
|
237
|
+
<Typography color="text.secondary" variant="body1">
|
|
238
|
+
{/* @ts-ignore */}
|
|
239
|
+
{t('payment.subscription.overdue.simpleTitle', {
|
|
240
|
+
// @ts-ignore
|
|
241
|
+
name: data?.subscription?.description,
|
|
242
|
+
count: data?.invoices?.length,
|
|
243
|
+
})}
|
|
244
|
+
<br />
|
|
245
|
+
{t('payment.subscription.overdue.description')}
|
|
246
|
+
<a
|
|
247
|
+
href={subscriptionUrl}
|
|
248
|
+
target="_blank"
|
|
249
|
+
rel="noreferrer"
|
|
250
|
+
style={{ color: 'var(--foregrounds-fg-interactive, 0086FF)' }}>
|
|
251
|
+
{t('payment.subscription.overdue.view')}
|
|
252
|
+
</a>
|
|
253
|
+
</Typography>
|
|
254
|
+
<Typography color="text.secondary" variant="body1">
|
|
255
|
+
{t('payment.subscription.overdue.list')}
|
|
256
|
+
</Typography>
|
|
257
|
+
<Stack>
|
|
258
|
+
{summaryList.map((item: any) => (
|
|
259
|
+
<Stack
|
|
260
|
+
key={item?.currency?.id}
|
|
261
|
+
direction="row"
|
|
262
|
+
justifyContent="space-between"
|
|
263
|
+
alignItems="center"
|
|
264
|
+
sx={{
|
|
265
|
+
py: 1,
|
|
266
|
+
px: 0.5,
|
|
267
|
+
borderBottom: '1px solid var(--foregrounds-fg-border, #E0E0E0)',
|
|
268
|
+
'&:hover': {
|
|
269
|
+
background: 'var(--backgrounds-bg-highlight, #eff6ff)',
|
|
270
|
+
},
|
|
271
|
+
mt: 0,
|
|
272
|
+
}}>
|
|
273
|
+
<Typography>
|
|
274
|
+
{t('payment.subscription.overdue.total', {
|
|
275
|
+
total: formatAmount(item?.amount, item?.currency?.decimal),
|
|
276
|
+
currency: item?.currency?.symbol,
|
|
277
|
+
})}
|
|
278
|
+
</Typography>
|
|
279
|
+
{renderPayButton(item, {
|
|
280
|
+
variant: 'text',
|
|
281
|
+
sx: {
|
|
282
|
+
color: 'text.link',
|
|
283
|
+
},
|
|
284
|
+
})}
|
|
285
|
+
</Stack>
|
|
286
|
+
))}
|
|
287
|
+
</Stack>
|
|
288
|
+
</>
|
|
289
|
+
)}
|
|
290
|
+
</Stack>
|
|
291
|
+
)}
|
|
292
|
+
</Dialog>
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
OverdueInvoicePayment.defaultProps = {
|
|
297
|
+
mode: 'default',
|
|
298
|
+
onPaid: () => {},
|
|
299
|
+
dialogProps: {
|
|
300
|
+
open: true,
|
|
301
|
+
},
|
|
302
|
+
children: null,
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
export default OverdueInvoicePayment;
|
package/src/index.ts
CHANGED
|
@@ -28,6 +28,7 @@ import CountrySelect from './components/country-select';
|
|
|
28
28
|
import TruncatedText from './components/truncated-text';
|
|
29
29
|
import Link from './components/link';
|
|
30
30
|
import { createLazyComponent } from './components/lazy-loader';
|
|
31
|
+
import OverdueInvoicePayment from './components/over-due-invoice-payment';
|
|
31
32
|
|
|
32
33
|
export { PaymentThemeProvider } from './theme';
|
|
33
34
|
|
|
@@ -73,4 +74,5 @@ export {
|
|
|
73
74
|
Table,
|
|
74
75
|
TruncatedText,
|
|
75
76
|
Link,
|
|
77
|
+
OverdueInvoicePayment,
|
|
76
78
|
};
|
package/src/locales/en.tsx
CHANGED
|
@@ -93,6 +93,7 @@ export default flat({
|
|
|
93
93
|
saveAsDefaultPriceSuccess: 'Set default price successfully',
|
|
94
94
|
stakeAmount: 'Stake Amount',
|
|
95
95
|
slashStakeAmount: 'Slash Stake Amount',
|
|
96
|
+
know: 'I know',
|
|
96
97
|
},
|
|
97
98
|
payment: {
|
|
98
99
|
checkout: {
|
|
@@ -330,6 +331,23 @@ export default flat({
|
|
|
330
331
|
rechargeForSubscription: 'Add funds for subscription',
|
|
331
332
|
},
|
|
332
333
|
},
|
|
334
|
+
subscription: {
|
|
335
|
+
overdue: {
|
|
336
|
+
simpleTitle:
|
|
337
|
+
'There are {count} due invoices for your subscription {name}, you need to pay them to activate your subscription or before making new purchases.',
|
|
338
|
+
title:
|
|
339
|
+
'There are {count} due invoices for your subscription {name}, the total due amount is {total} {symbol}, you need to pay them to activate your subscription or before making new purchases.',
|
|
340
|
+
payNow: 'Pay Now',
|
|
341
|
+
notSupport: 'This payment method is not supported',
|
|
342
|
+
total: 'Total {total} {currency}',
|
|
343
|
+
view: 'View Subscription Details',
|
|
344
|
+
viewNow: 'View Now',
|
|
345
|
+
pastDue: 'Past Due Invoices',
|
|
346
|
+
description: 'If you have any questions, you can choose ',
|
|
347
|
+
list: 'Past Due Invoices:',
|
|
348
|
+
empty: 'There are no overdue invoices for your subscription {name}.',
|
|
349
|
+
},
|
|
350
|
+
},
|
|
333
351
|
},
|
|
334
352
|
refund: {
|
|
335
353
|
type: {
|
package/src/locales/zh.tsx
CHANGED
|
@@ -93,6 +93,7 @@ export default flat({
|
|
|
93
93
|
saveAsDefaultPriceSuccess: '设置默认价格成功',
|
|
94
94
|
stakeAmount: '质押金额',
|
|
95
95
|
slashStakeAmount: '罚没金额',
|
|
96
|
+
know: '我知道了',
|
|
96
97
|
},
|
|
97
98
|
payment: {
|
|
98
99
|
checkout: {
|
|
@@ -320,6 +321,23 @@ export default flat({
|
|
|
320
321
|
rechargeForSubscription: '订阅充值',
|
|
321
322
|
},
|
|
322
323
|
},
|
|
324
|
+
subscription: {
|
|
325
|
+
overdue: {
|
|
326
|
+
title:
|
|
327
|
+
'您的【{name}】订阅共有 {count} 张欠费账单,总计 {total} {symbol},您需要支付这些账单以激活您的订阅,或在进行新的购买之前完成支付。',
|
|
328
|
+
simpleTitle:
|
|
329
|
+
'您的【{name}】订阅共有 {count} 张欠费账单,您需要支付这些账单以激活您的订阅,或在进行新的购买之前完成支付。',
|
|
330
|
+
payNow: '立即支付',
|
|
331
|
+
notSupport: '暂不支持该支付方式',
|
|
332
|
+
total: '总计 {total} {currency}',
|
|
333
|
+
view: '查看订阅详情',
|
|
334
|
+
pastDue: '欠费账单',
|
|
335
|
+
viewNow: '立即查看',
|
|
336
|
+
description: '如果您有任何疑问,可以选择 ',
|
|
337
|
+
list: '欠费账单:',
|
|
338
|
+
empty: '您的【{name}】订阅当前没有欠费账单',
|
|
339
|
+
},
|
|
340
|
+
},
|
|
323
341
|
},
|
|
324
342
|
refund: {
|
|
325
343
|
type: {
|