@blocklet/payment-react 1.18.12 → 1.18.13
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/link.js +1 -0
- package/es/components/over-due-invoice-payment.d.ts +3 -1
- package/es/components/over-due-invoice-payment.js +14 -3
- package/es/history/invoice/list.js +42 -32
- package/es/libs/navigation.d.ts +33 -0
- package/es/libs/navigation.js +45 -0
- package/es/locales/en.js +2 -2
- package/es/locales/zh.js +2 -2
- package/lib/components/link.js +1 -0
- package/lib/components/over-due-invoice-payment.d.ts +3 -1
- package/lib/components/over-due-invoice-payment.js +18 -3
- package/lib/history/invoice/list.js +53 -42
- package/lib/libs/navigation.d.ts +33 -0
- package/lib/libs/navigation.js +59 -0
- package/lib/locales/en.js +2 -2
- package/lib/locales/zh.js +2 -2
- package/package.json +3 -3
- package/src/components/link.tsx +1 -0
- package/src/components/over-due-invoice-payment.tsx +14 -1
- package/src/history/invoice/list.tsx +46 -35
- package/src/libs/navigation.ts +89 -0
- package/src/locales/en.tsx +2 -2
- package/src/locales/zh.tsx +2 -2
package/es/components/link.js
CHANGED
|
@@ -11,6 +11,7 @@ export default function Link({ to, children, onClick, replace, target, outLink =
|
|
|
11
11
|
e.preventDefault();
|
|
12
12
|
window.location.href = to;
|
|
13
13
|
}
|
|
14
|
+
e.preventDefault();
|
|
14
15
|
onClick?.(e);
|
|
15
16
|
};
|
|
16
17
|
return /* @__PURE__ */ jsx("a", { href: to, onClick: handleClick, target, rel: "noreferrer", ...props, children });
|
|
@@ -9,6 +9,7 @@ type Props = {
|
|
|
9
9
|
mode?: 'default' | 'custom';
|
|
10
10
|
onPaid?: (subscriptionId: string, currencyId: string) => void;
|
|
11
11
|
dialogProps?: DialogProps;
|
|
12
|
+
inSubscriptionDetail?: boolean;
|
|
12
13
|
children?: (handlePay: (item: SummaryItem) => void, data: {
|
|
13
14
|
subscription: Subscription;
|
|
14
15
|
summary: {
|
|
@@ -23,7 +24,7 @@ type SummaryItem = {
|
|
|
23
24
|
currency: PaymentCurrency;
|
|
24
25
|
method: PaymentMethod;
|
|
25
26
|
};
|
|
26
|
-
declare function OverdueInvoicePayment({ subscriptionId, mode, dialogProps, children, onPaid, }: Props): import("react").JSX.Element;
|
|
27
|
+
declare function OverdueInvoicePayment({ subscriptionId, mode, dialogProps, children, onPaid, inSubscriptionDetail, }: Props): import("react").JSX.Element | null;
|
|
27
28
|
declare namespace OverdueInvoicePayment {
|
|
28
29
|
var defaultProps: {
|
|
29
30
|
mode: string;
|
|
@@ -32,6 +33,7 @@ declare namespace OverdueInvoicePayment {
|
|
|
32
33
|
open: boolean;
|
|
33
34
|
};
|
|
34
35
|
children: null;
|
|
36
|
+
inSubscriptionDetail: boolean;
|
|
35
37
|
};
|
|
36
38
|
}
|
|
37
39
|
export default OverdueInvoicePayment;
|
|
@@ -20,7 +20,8 @@ function OverdueInvoicePayment({
|
|
|
20
20
|
dialogProps = {},
|
|
21
21
|
children,
|
|
22
22
|
onPaid = () => {
|
|
23
|
-
}
|
|
23
|
+
},
|
|
24
|
+
inSubscriptionDetail = false
|
|
24
25
|
}) {
|
|
25
26
|
const { t } = useLocaleContext();
|
|
26
27
|
const { connect } = usePaymentContext();
|
|
@@ -100,8 +101,14 @@ function OverdueInvoicePayment({
|
|
|
100
101
|
setDialogOpen(false);
|
|
101
102
|
dialogProps.onClose?.();
|
|
102
103
|
};
|
|
104
|
+
const handleViewDetailClick = (e) => {
|
|
105
|
+
if (inSubscriptionDetail) {
|
|
106
|
+
e.preventDefault();
|
|
107
|
+
handleClose();
|
|
108
|
+
}
|
|
109
|
+
};
|
|
103
110
|
if (loading) {
|
|
104
|
-
return
|
|
111
|
+
return null;
|
|
105
112
|
}
|
|
106
113
|
const renderPayButton = (item, props) => {
|
|
107
114
|
const isPayLoading = payLoading && item.currency.id === selectCurrencyId;
|
|
@@ -130,6 +137,7 @@ function OverdueInvoicePayment({
|
|
|
130
137
|
...dialogProps || {},
|
|
131
138
|
open: dialogOpen,
|
|
132
139
|
title: dialogProps?.title || t("payment.subscription.overdue.pastDue"),
|
|
140
|
+
sx: { "& .MuiDialogContent-root": { pt: 0 } },
|
|
133
141
|
onClose: handleClose,
|
|
134
142
|
children: error ? /* @__PURE__ */ jsx(Alert, { severity: "error", children: error.message }) : /* @__PURE__ */ jsxs(Stack, { gap: 1, children: [
|
|
135
143
|
summaryList.length === 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -155,6 +163,7 @@ function OverdueInvoicePayment({
|
|
|
155
163
|
{
|
|
156
164
|
href: subscriptionUrl,
|
|
157
165
|
target: "_blank",
|
|
166
|
+
onClick: handleViewDetailClick,
|
|
158
167
|
rel: "noreferrer",
|
|
159
168
|
style: { color: "var(--foregrounds-fg-interactive, 0086FF)" },
|
|
160
169
|
children: t("payment.subscription.overdue.view")
|
|
@@ -181,6 +190,7 @@ function OverdueInvoicePayment({
|
|
|
181
190
|
href: subscriptionUrl,
|
|
182
191
|
target: "_blank",
|
|
183
192
|
rel: "noreferrer",
|
|
193
|
+
onClick: handleViewDetailClick,
|
|
184
194
|
style: { color: "var(--foregrounds-fg-interactive, 0086FF)" },
|
|
185
195
|
children: t("payment.subscription.overdue.view")
|
|
186
196
|
}
|
|
@@ -229,6 +239,7 @@ OverdueInvoicePayment.defaultProps = {
|
|
|
229
239
|
dialogProps: {
|
|
230
240
|
open: true
|
|
231
241
|
},
|
|
232
|
-
children: null
|
|
242
|
+
children: null,
|
|
243
|
+
inSubscriptionDetail: false
|
|
233
244
|
};
|
|
234
245
|
export default OverdueInvoicePayment;
|
|
@@ -6,7 +6,7 @@ import { Box, Button, CircularProgress, Hidden, Stack, Typography } from "@mui/m
|
|
|
6
6
|
import { styled } from "@mui/system";
|
|
7
7
|
import { useInfiniteScroll, useRequest, useSetState } from "ahooks";
|
|
8
8
|
import React, { useEffect, useRef, useState } from "react";
|
|
9
|
-
import {
|
|
9
|
+
import { useNavigate } from "react-router-dom";
|
|
10
10
|
import debounce from "lodash/debounce";
|
|
11
11
|
import Status from "../../components/status.js";
|
|
12
12
|
import { usePaymentContext } from "../../contexts/payment.js";
|
|
@@ -19,10 +19,10 @@ import {
|
|
|
19
19
|
formatToDatetime,
|
|
20
20
|
getInvoiceDescriptionAndReason,
|
|
21
21
|
getInvoiceStatusColor,
|
|
22
|
-
getPrefix,
|
|
23
22
|
getTxLink
|
|
24
23
|
} from "../../libs/util.js";
|
|
25
24
|
import Table from "../../components/table.js";
|
|
25
|
+
import { createLink, handleNavigation } from "../../libs/navigation.js";
|
|
26
26
|
const groupByDate = (items) => {
|
|
27
27
|
const grouped = {};
|
|
28
28
|
items.forEach((item) => {
|
|
@@ -45,21 +45,20 @@ const fetchData = (params = {}) => {
|
|
|
45
45
|
};
|
|
46
46
|
const getInvoiceLink = (invoice, action) => {
|
|
47
47
|
if (invoice.id.startsWith("in_")) {
|
|
48
|
+
const path = `/customer/invoice/${invoice.id}${invoice.status === "uncollectible" && action ? `?action=${action}` : ""}`;
|
|
48
49
|
return {
|
|
49
|
-
external: false,
|
|
50
50
|
connect: invoice.status === "uncollectible",
|
|
51
|
-
|
|
52
|
-
getPrefix(),
|
|
53
|
-
`/customer/invoice/${invoice.id}?action=${invoice.status === "uncollectible" ? action : ""}`
|
|
54
|
-
)
|
|
51
|
+
link: createLink(path)
|
|
55
52
|
};
|
|
56
53
|
}
|
|
57
54
|
return {
|
|
58
|
-
external: true,
|
|
59
55
|
connect: false,
|
|
60
|
-
|
|
56
|
+
link: createLink(getTxLink(invoice.paymentMethod, invoice.metadata?.payment_details).link, true)
|
|
61
57
|
};
|
|
62
58
|
};
|
|
59
|
+
const linkStyle = {
|
|
60
|
+
cursor: "pointer"
|
|
61
|
+
};
|
|
63
62
|
const InvoiceTable = React.memo((props) => {
|
|
64
63
|
const {
|
|
65
64
|
pageSize,
|
|
@@ -77,6 +76,7 @@ const InvoiceTable = React.memo((props) => {
|
|
|
77
76
|
} = props;
|
|
78
77
|
const listKey = "invoice-table";
|
|
79
78
|
const { t, locale } = useLocaleContext();
|
|
79
|
+
const navigate = useNavigate();
|
|
80
80
|
const [search, setSearch] = useState({
|
|
81
81
|
pageSize: pageSize || 10,
|
|
82
82
|
page: 1
|
|
@@ -131,6 +131,10 @@ const InvoiceTable = React.memo((props) => {
|
|
|
131
131
|
});
|
|
132
132
|
}
|
|
133
133
|
}, [subscription]);
|
|
134
|
+
const handleLinkClick = (e, invoice) => {
|
|
135
|
+
const { link } = getInvoiceLink(invoice, action);
|
|
136
|
+
handleNavigation(e, link, navigate, { target: link.external ? "_blank" : target });
|
|
137
|
+
};
|
|
134
138
|
const columns = [
|
|
135
139
|
{
|
|
136
140
|
label: t("common.amount"),
|
|
@@ -140,8 +144,7 @@ const InvoiceTable = React.memo((props) => {
|
|
|
140
144
|
options: {
|
|
141
145
|
customBodyRenderLite: (_, index) => {
|
|
142
146
|
const invoice = data?.list[index];
|
|
143
|
-
|
|
144
|
-
return /* @__PURE__ */ jsx("a", { href: link.url, target: link.external ? "_blank" : target, rel: "noreferrer", children: /* @__PURE__ */ jsxs(Typography, { children: [
|
|
147
|
+
return /* @__PURE__ */ jsx(Box, { onClick: (e) => handleLinkClick(e, invoice), sx: linkStyle, children: /* @__PURE__ */ jsxs(Typography, { children: [
|
|
145
148
|
formatBNStr(invoice.total, invoice.paymentCurrency.decimal),
|
|
146
149
|
"\xA0",
|
|
147
150
|
invoice.paymentCurrency.symbol
|
|
@@ -155,8 +158,7 @@ const InvoiceTable = React.memo((props) => {
|
|
|
155
158
|
options: {
|
|
156
159
|
customBodyRenderLite: (_, index) => {
|
|
157
160
|
const invoice = data.list[index];
|
|
158
|
-
|
|
159
|
-
return /* @__PURE__ */ jsx("a", { href: link.url, target: link.external ? "_blank" : target, rel: "noreferrer", children: /* @__PURE__ */ jsx(Status, { label: getInvoiceDescriptionAndReason(invoice, locale)?.type }) });
|
|
161
|
+
return /* @__PURE__ */ jsx(Box, { onClick: (e) => handleLinkClick(e, invoice), sx: linkStyle, children: /* @__PURE__ */ jsx(Status, { label: getInvoiceDescriptionAndReason(invoice, locale)?.type }) });
|
|
160
162
|
}
|
|
161
163
|
}
|
|
162
164
|
},
|
|
@@ -166,8 +168,7 @@ const InvoiceTable = React.memo((props) => {
|
|
|
166
168
|
options: {
|
|
167
169
|
customBodyRenderLite: (_, index) => {
|
|
168
170
|
const invoice = data?.list[index];
|
|
169
|
-
|
|
170
|
-
return /* @__PURE__ */ jsx("a", { href: link.url, target: link.external ? "_blank" : target, rel: "noreferrer", children: invoice?.number });
|
|
171
|
+
return /* @__PURE__ */ jsx(Box, { onClick: (e) => handleLinkClick(e, invoice), sx: linkStyle, children: invoice?.number });
|
|
171
172
|
}
|
|
172
173
|
}
|
|
173
174
|
},
|
|
@@ -177,8 +178,7 @@ const InvoiceTable = React.memo((props) => {
|
|
|
177
178
|
options: {
|
|
178
179
|
customBodyRenderLite: (val, index) => {
|
|
179
180
|
const invoice = data?.list[index];
|
|
180
|
-
|
|
181
|
-
return /* @__PURE__ */ jsx("a", { href: link.url, target: link.external ? "_blank" : target, rel: "noreferrer", children: formatToDate(invoice.created_at, locale, "YYYY-MM-DD HH:mm:ss") });
|
|
181
|
+
return /* @__PURE__ */ jsx(Box, { onClick: (e) => handleLinkClick(e, invoice), sx: linkStyle, children: formatToDate(invoice.created_at, locale, "YYYY-MM-DD HH:mm:ss") });
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
},
|
|
@@ -189,8 +189,7 @@ const InvoiceTable = React.memo((props) => {
|
|
|
189
189
|
sort: false,
|
|
190
190
|
customBodyRenderLite: (val, index) => {
|
|
191
191
|
const invoice = data?.list[index];
|
|
192
|
-
|
|
193
|
-
return /* @__PURE__ */ jsx("a", { href: link.url, target: link.external ? "_blank" : target, rel: "noreferrer", children: getInvoiceDescriptionAndReason(invoice, locale)?.description || invoice.id });
|
|
192
|
+
return /* @__PURE__ */ jsx(Box, { onClick: (e) => handleLinkClick(e, invoice), sx: linkStyle, children: getInvoiceDescriptionAndReason(invoice, locale)?.description || invoice.id });
|
|
194
193
|
}
|
|
195
194
|
}
|
|
196
195
|
},
|
|
@@ -200,24 +199,23 @@ const InvoiceTable = React.memo((props) => {
|
|
|
200
199
|
options: {
|
|
201
200
|
customBodyRenderLite: (val, index) => {
|
|
202
201
|
const invoice = data?.list[index];
|
|
203
|
-
const link = getInvoiceLink(invoice, action);
|
|
204
202
|
const hidePay = invoice.billing_reason === "overdraft-protection";
|
|
203
|
+
const { connect } = getInvoiceLink(invoice, action);
|
|
205
204
|
if (action && !hidePay) {
|
|
206
|
-
return
|
|
205
|
+
return connect ? /* @__PURE__ */ jsx(Button, { variant: "text", size: "small", onClick: () => onPay(invoice.id), sx: { color: "text.link" }, children: t("payment.customer.invoice.pay") }) : /* @__PURE__ */ jsx(
|
|
207
206
|
Button,
|
|
208
207
|
{
|
|
209
208
|
component: "a",
|
|
210
209
|
variant: "text",
|
|
211
210
|
size: "small",
|
|
212
|
-
|
|
213
|
-
target: link.external ? "_blank" : target,
|
|
211
|
+
onClick: (e) => handleLinkClick(e, invoice),
|
|
214
212
|
sx: { color: "var(--foregrounds-fg-interactive, #0086FF) !important" },
|
|
215
213
|
rel: "noreferrer",
|
|
216
214
|
children: t("payment.customer.invoice.pay")
|
|
217
215
|
}
|
|
218
216
|
);
|
|
219
217
|
}
|
|
220
|
-
return /* @__PURE__ */ jsx(
|
|
218
|
+
return /* @__PURE__ */ jsx(Box, { onClick: (e) => handleLinkClick(e, invoice), sx: linkStyle, children: /* @__PURE__ */ jsx(Status, { label: invoice.status, color: getInvoiceStatusColor(invoice.status) }) });
|
|
221
219
|
}
|
|
222
220
|
}
|
|
223
221
|
}
|
|
@@ -283,6 +281,7 @@ const InvoiceList = React.memo((props) => {
|
|
|
283
281
|
const size = pageSize || 10;
|
|
284
282
|
const subscription = useSubscription("events");
|
|
285
283
|
const { t, locale } = useLocaleContext();
|
|
284
|
+
const navigate = useNavigate();
|
|
286
285
|
const { data, loadMore, loadingMore, loading, reloadAsync } = useInfiniteScroll(
|
|
287
286
|
(d) => {
|
|
288
287
|
const page = d ? Math.ceil(d.list.length / size) + 1 : 1;
|
|
@@ -342,11 +341,14 @@ const InvoiceList = React.memo((props) => {
|
|
|
342
341
|
}
|
|
343
342
|
const hasMore = data && data.list.length < data.count;
|
|
344
343
|
const grouped = groupByDate(data.list);
|
|
344
|
+
const handleLinkClick = (e, link) => {
|
|
345
|
+
handleNavigation(e, link, navigate, { target: link.external ? "_blank" : target });
|
|
346
|
+
};
|
|
345
347
|
return /* @__PURE__ */ jsxs(Root, { direction: "column", gap: 1, sx: { mt: 1 }, children: [
|
|
346
348
|
Object.entries(grouped).map(([date, invoices]) => /* @__PURE__ */ jsxs(Box, { children: [
|
|
347
349
|
/* @__PURE__ */ jsx(Typography, { sx: { fontWeight: "bold", color: "text.secondary", mt: 2, mb: 1 }, children: date }),
|
|
348
350
|
invoices.map((invoice) => {
|
|
349
|
-
const link = getInvoiceLink(invoice, action);
|
|
351
|
+
const { link, connect } = getInvoiceLink(invoice, action);
|
|
350
352
|
return /* @__PURE__ */ jsxs(
|
|
351
353
|
Stack,
|
|
352
354
|
{
|
|
@@ -360,10 +362,19 @@ const InvoiceList = React.memo((props) => {
|
|
|
360
362
|
alignItems: "center",
|
|
361
363
|
flexWrap: "nowrap",
|
|
362
364
|
children: [
|
|
363
|
-
/* @__PURE__ */ jsx(Box, { flex: 2, children: /* @__PURE__ */ jsx(
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
365
|
+
/* @__PURE__ */ jsx(Box, { flex: 2, children: /* @__PURE__ */ jsx(
|
|
366
|
+
"a",
|
|
367
|
+
{
|
|
368
|
+
href: link.url,
|
|
369
|
+
target: link.external ? "_blank" : target,
|
|
370
|
+
rel: "noreferrer",
|
|
371
|
+
onClick: (e) => handleLinkClick(e, link),
|
|
372
|
+
children: /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", spacing: 0.5, children: [
|
|
373
|
+
/* @__PURE__ */ jsx(Typography, { component: "span", children: invoice.number }),
|
|
374
|
+
link.external && /* @__PURE__ */ jsx(Hidden, { mdDown: true, children: /* @__PURE__ */ jsx(OpenInNewOutlined, { fontSize: "small", sx: { color: "text.secondary" } }) })
|
|
375
|
+
] })
|
|
376
|
+
}
|
|
377
|
+
) }),
|
|
367
378
|
/* @__PURE__ */ jsx(Box, { flex: 1, textAlign: "right", children: /* @__PURE__ */ jsxs(Typography, { children: [
|
|
368
379
|
formatBNStr(invoice.total, invoice.paymentCurrency.decimal),
|
|
369
380
|
"\xA0",
|
|
@@ -371,7 +382,7 @@ const InvoiceList = React.memo((props) => {
|
|
|
371
382
|
] }) }),
|
|
372
383
|
/* @__PURE__ */ jsx(Box, { flex: 1, textAlign: "right", children: /* @__PURE__ */ jsx(Typography, { children: formatToDate(invoice.created_at, locale, "HH:mm:ss") }) }),
|
|
373
384
|
!action && /* @__PURE__ */ jsx(Hidden, { mdDown: true, children: /* @__PURE__ */ jsx(Box, { flex: 2, className: "invoice-description", textAlign: "right", children: /* @__PURE__ */ jsx(Typography, { children: invoice.description || invoice.id }) }) }),
|
|
374
|
-
/* @__PURE__ */ jsx(Box, { flex: 1, textAlign: "right", children: action ?
|
|
385
|
+
/* @__PURE__ */ jsx(Box, { flex: 1, textAlign: "right", children: action ? connect ? /* @__PURE__ */ jsx(
|
|
375
386
|
Button,
|
|
376
387
|
{
|
|
377
388
|
variant: "contained",
|
|
@@ -387,8 +398,7 @@ const InvoiceList = React.memo((props) => {
|
|
|
387
398
|
component: "a",
|
|
388
399
|
variant: "contained",
|
|
389
400
|
size: "small",
|
|
390
|
-
|
|
391
|
-
target: link.external ? "_blank" : target,
|
|
401
|
+
onClick: (e) => handleLinkClick(e, link),
|
|
392
402
|
sx: { whiteSpace: "nowrap" },
|
|
393
403
|
rel: "noreferrer",
|
|
394
404
|
children: t("payment.customer.invoice.pay")
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { NavigateFunction } from 'react-router-dom';
|
|
2
|
+
export interface LinkInfo {
|
|
3
|
+
url: string;
|
|
4
|
+
external: boolean;
|
|
5
|
+
path: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Check if currently running inside Payment Kit
|
|
9
|
+
*/
|
|
10
|
+
export declare function isInPaymentKit(): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Create link information object
|
|
13
|
+
* @param path Path or URL
|
|
14
|
+
* @param external Force external link behavior
|
|
15
|
+
*/
|
|
16
|
+
export declare function createLink(path: string, external?: boolean): LinkInfo;
|
|
17
|
+
/**
|
|
18
|
+
* Get HTML attributes for a link
|
|
19
|
+
* @param link Link information
|
|
20
|
+
* @param target Link target (default: _self)
|
|
21
|
+
*/
|
|
22
|
+
export declare function getLinkProps(link: LinkInfo, target?: string): Record<string, any>;
|
|
23
|
+
/**
|
|
24
|
+
* Handle link navigation
|
|
25
|
+
* @param e Click event
|
|
26
|
+
* @param link Link information
|
|
27
|
+
* @param navigate React Router navigate function
|
|
28
|
+
* @param options Navigation options
|
|
29
|
+
*/
|
|
30
|
+
export declare function handleNavigation(e: React.MouseEvent, link: LinkInfo, navigate?: NavigateFunction, options?: {
|
|
31
|
+
replace?: boolean;
|
|
32
|
+
target?: string;
|
|
33
|
+
}): void;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { joinURL } from "ufo";
|
|
2
|
+
import { getPrefix, PAYMENT_KIT_DID } from "./util.js";
|
|
3
|
+
export function isInPaymentKit() {
|
|
4
|
+
const componentId = (window.blocklet?.componentId || "").split("/").pop();
|
|
5
|
+
return componentId === PAYMENT_KIT_DID;
|
|
6
|
+
}
|
|
7
|
+
export function createLink(path, external = false) {
|
|
8
|
+
const isAbsoluteUrl = /^https?:\/\//.test(path);
|
|
9
|
+
const isExternal = external || isAbsoluteUrl;
|
|
10
|
+
const url = isExternal ? path : joinURL(getPrefix(), path);
|
|
11
|
+
return {
|
|
12
|
+
url,
|
|
13
|
+
external: isExternal,
|
|
14
|
+
path
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function getLinkProps(link, target = "_self") {
|
|
18
|
+
const props = {
|
|
19
|
+
href: link.url
|
|
20
|
+
};
|
|
21
|
+
if (link.external) {
|
|
22
|
+
props.target = target;
|
|
23
|
+
props.rel = target === "_blank" ? "noopener noreferrer" : void 0;
|
|
24
|
+
}
|
|
25
|
+
return props;
|
|
26
|
+
}
|
|
27
|
+
export function handleNavigation(e, link, navigate, options = {}) {
|
|
28
|
+
if (e) {
|
|
29
|
+
e.preventDefault();
|
|
30
|
+
}
|
|
31
|
+
const { replace = false, target = "_self" } = options;
|
|
32
|
+
if (link.external || target === "_blank") {
|
|
33
|
+
window.open(link.url, target);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (isInPaymentKit() && navigate) {
|
|
37
|
+
navigate(link.path, { replace });
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (replace) {
|
|
41
|
+
window.location.replace(link.url);
|
|
42
|
+
} else {
|
|
43
|
+
window.location.href = link.url;
|
|
44
|
+
}
|
|
45
|
+
}
|
package/es/locales/en.js
CHANGED
|
@@ -245,8 +245,8 @@ export default flat({
|
|
|
245
245
|
}
|
|
246
246
|
},
|
|
247
247
|
recover: {
|
|
248
|
-
button: "
|
|
249
|
-
title: "
|
|
248
|
+
button: "Resume Subscription",
|
|
249
|
+
title: "Resume Your Subscription",
|
|
250
250
|
description: "Your subscription will not be canceled and will be automatically renewed on {date}, please confirm to continue"
|
|
251
251
|
},
|
|
252
252
|
changePlan: {
|
package/es/locales/zh.js
CHANGED
|
@@ -245,8 +245,8 @@ export default flat({
|
|
|
245
245
|
}
|
|
246
246
|
},
|
|
247
247
|
recover: {
|
|
248
|
-
button: "\
|
|
249
|
-
title: "\
|
|
248
|
+
button: "\u6062\u590D\u8BA2\u9605",
|
|
249
|
+
title: "\u6062\u590D\u60A8\u7684\u8BA2\u9605",
|
|
250
250
|
description: "\u60A8\u7684\u8BA2\u9605\u5C06\u4E0D\u4F1A\u88AB\u53D6\u6D88\uFF0C\u5E76\u5C06\u5728{date}\u81EA\u52A8\u7EED\u8BA2\uFF0C\u8BF7\u786E\u8BA4\u662F\u5426\u7EE7\u7EED"
|
|
251
251
|
},
|
|
252
252
|
changePlan: {
|
package/lib/components/link.js
CHANGED
|
@@ -9,6 +9,7 @@ type Props = {
|
|
|
9
9
|
mode?: 'default' | 'custom';
|
|
10
10
|
onPaid?: (subscriptionId: string, currencyId: string) => void;
|
|
11
11
|
dialogProps?: DialogProps;
|
|
12
|
+
inSubscriptionDetail?: boolean;
|
|
12
13
|
children?: (handlePay: (item: SummaryItem) => void, data: {
|
|
13
14
|
subscription: Subscription;
|
|
14
15
|
summary: {
|
|
@@ -23,7 +24,7 @@ type SummaryItem = {
|
|
|
23
24
|
currency: PaymentCurrency;
|
|
24
25
|
method: PaymentMethod;
|
|
25
26
|
};
|
|
26
|
-
declare function OverdueInvoicePayment({ subscriptionId, mode, dialogProps, children, onPaid, }: Props): import("react").JSX.Element;
|
|
27
|
+
declare function OverdueInvoicePayment({ subscriptionId, mode, dialogProps, children, onPaid, inSubscriptionDetail, }: Props): import("react").JSX.Element | null;
|
|
27
28
|
declare namespace OverdueInvoicePayment {
|
|
28
29
|
var defaultProps: {
|
|
29
30
|
mode: string;
|
|
@@ -32,6 +33,7 @@ declare namespace OverdueInvoicePayment {
|
|
|
32
33
|
open: boolean;
|
|
33
34
|
};
|
|
34
35
|
children: null;
|
|
36
|
+
inSubscriptionDetail: boolean;
|
|
35
37
|
};
|
|
36
38
|
}
|
|
37
39
|
export default OverdueInvoicePayment;
|
|
@@ -26,7 +26,8 @@ function OverdueInvoicePayment({
|
|
|
26
26
|
mode = "default",
|
|
27
27
|
dialogProps = {},
|
|
28
28
|
children,
|
|
29
|
-
onPaid = () => {}
|
|
29
|
+
onPaid = () => {},
|
|
30
|
+
inSubscriptionDetail = false
|
|
30
31
|
}) {
|
|
31
32
|
const {
|
|
32
33
|
t
|
|
@@ -121,8 +122,14 @@ function OverdueInvoicePayment({
|
|
|
121
122
|
setDialogOpen(false);
|
|
122
123
|
dialogProps.onClose?.();
|
|
123
124
|
};
|
|
125
|
+
const handleViewDetailClick = e => {
|
|
126
|
+
if (inSubscriptionDetail) {
|
|
127
|
+
e.preventDefault();
|
|
128
|
+
handleClose();
|
|
129
|
+
}
|
|
130
|
+
};
|
|
124
131
|
if (loading) {
|
|
125
|
-
return
|
|
132
|
+
return null;
|
|
126
133
|
}
|
|
127
134
|
const renderPayButton = (item, props) => {
|
|
128
135
|
const isPayLoading = payLoading && item.currency.id === selectCurrencyId;
|
|
@@ -169,6 +176,11 @@ function OverdueInvoicePayment({
|
|
|
169
176
|
...(dialogProps || {}),
|
|
170
177
|
open: dialogOpen,
|
|
171
178
|
title: dialogProps?.title || t("payment.subscription.overdue.pastDue"),
|
|
179
|
+
sx: {
|
|
180
|
+
"& .MuiDialogContent-root": {
|
|
181
|
+
pt: 0
|
|
182
|
+
}
|
|
183
|
+
},
|
|
172
184
|
onClose: handleClose,
|
|
173
185
|
children: error ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Alert, {
|
|
174
186
|
severity: "error",
|
|
@@ -209,6 +221,7 @@ function OverdueInvoicePayment({
|
|
|
209
221
|
}), /* @__PURE__ */(0, _jsxRuntime.jsx)("br", {}), t("payment.subscription.overdue.description"), /* @__PURE__ */(0, _jsxRuntime.jsx)("a", {
|
|
210
222
|
href: subscriptionUrl,
|
|
211
223
|
target: "_blank",
|
|
224
|
+
onClick: handleViewDetailClick,
|
|
212
225
|
rel: "noreferrer",
|
|
213
226
|
style: {
|
|
214
227
|
color: "var(--foregrounds-fg-interactive, 0086FF)"
|
|
@@ -239,6 +252,7 @@ function OverdueInvoicePayment({
|
|
|
239
252
|
href: subscriptionUrl,
|
|
240
253
|
target: "_blank",
|
|
241
254
|
rel: "noreferrer",
|
|
255
|
+
onClick: handleViewDetailClick,
|
|
242
256
|
style: {
|
|
243
257
|
color: "var(--foregrounds-fg-interactive, 0086FF)"
|
|
244
258
|
},
|
|
@@ -285,6 +299,7 @@ OverdueInvoicePayment.defaultProps = {
|
|
|
285
299
|
dialogProps: {
|
|
286
300
|
open: true
|
|
287
301
|
},
|
|
288
|
-
children: null
|
|
302
|
+
children: null,
|
|
303
|
+
inSubscriptionDetail: false
|
|
289
304
|
};
|
|
290
305
|
module.exports = OverdueInvoicePayment;
|
|
@@ -12,7 +12,7 @@ var _material = require("@mui/material");
|
|
|
12
12
|
var _system = require("@mui/system");
|
|
13
13
|
var _ahooks = require("ahooks");
|
|
14
14
|
var _react = _interopRequireWildcard(require("react"));
|
|
15
|
-
var
|
|
15
|
+
var _reactRouterDom = require("react-router-dom");
|
|
16
16
|
var _debounce = _interopRequireDefault(require("lodash/debounce"));
|
|
17
17
|
var _status = _interopRequireDefault(require("../../components/status"));
|
|
18
18
|
var _payment = require("../../contexts/payment");
|
|
@@ -20,6 +20,7 @@ var _subscription = require("../../hooks/subscription");
|
|
|
20
20
|
var _api = _interopRequireDefault(require("../../libs/api"));
|
|
21
21
|
var _util = require("../../libs/util");
|
|
22
22
|
var _table = _interopRequireDefault(require("../../components/table"));
|
|
23
|
+
var _navigation = require("../../libs/navigation");
|
|
23
24
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
24
25
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
25
26
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -45,18 +46,20 @@ const fetchData = (params = {}) => {
|
|
|
45
46
|
};
|
|
46
47
|
const getInvoiceLink = (invoice, action) => {
|
|
47
48
|
if (invoice.id.startsWith("in_")) {
|
|
49
|
+
const path = `/customer/invoice/${invoice.id}${invoice.status === "uncollectible" && action ? `?action=${action}` : ""}`;
|
|
48
50
|
return {
|
|
49
|
-
external: false,
|
|
50
51
|
connect: invoice.status === "uncollectible",
|
|
51
|
-
|
|
52
|
+
link: (0, _navigation.createLink)(path)
|
|
52
53
|
};
|
|
53
54
|
}
|
|
54
55
|
return {
|
|
55
|
-
external: true,
|
|
56
56
|
connect: false,
|
|
57
|
-
|
|
57
|
+
link: (0, _navigation.createLink)((0, _util.getTxLink)(invoice.paymentMethod, invoice.metadata?.payment_details).link, true)
|
|
58
58
|
};
|
|
59
59
|
};
|
|
60
|
+
const linkStyle = {
|
|
61
|
+
cursor: "pointer"
|
|
62
|
+
};
|
|
60
63
|
const InvoiceTable = _react.default.memo(props => {
|
|
61
64
|
const {
|
|
62
65
|
pageSize,
|
|
@@ -77,6 +80,7 @@ const InvoiceTable = _react.default.memo(props => {
|
|
|
77
80
|
t,
|
|
78
81
|
locale
|
|
79
82
|
} = (0, _context.useLocaleContext)();
|
|
83
|
+
const navigate = (0, _reactRouterDom.useNavigate)();
|
|
80
84
|
const [search, setSearch] = (0, _react.useState)({
|
|
81
85
|
pageSize: pageSize || 10,
|
|
82
86
|
page: 1
|
|
@@ -129,6 +133,14 @@ const InvoiceTable = _react.default.memo(props => {
|
|
|
129
133
|
});
|
|
130
134
|
}
|
|
131
135
|
}, [subscription]);
|
|
136
|
+
const handleLinkClick = (e, invoice) => {
|
|
137
|
+
const {
|
|
138
|
+
link
|
|
139
|
+
} = getInvoiceLink(invoice, action);
|
|
140
|
+
(0, _navigation.handleNavigation)(e, link, navigate, {
|
|
141
|
+
target: link.external ? "_blank" : target
|
|
142
|
+
});
|
|
143
|
+
};
|
|
132
144
|
const columns = [{
|
|
133
145
|
label: t("common.amount"),
|
|
134
146
|
name: "total",
|
|
@@ -137,11 +149,9 @@ const InvoiceTable = _react.default.memo(props => {
|
|
|
137
149
|
options: {
|
|
138
150
|
customBodyRenderLite: (_, index) => {
|
|
139
151
|
const invoice = data?.list[index];
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
target: link.external ? "_blank" : target,
|
|
144
|
-
rel: "noreferrer",
|
|
152
|
+
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
153
|
+
onClick: e => handleLinkClick(e, invoice),
|
|
154
|
+
sx: linkStyle,
|
|
145
155
|
children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, {
|
|
146
156
|
children: [(0, _util.formatBNStr)(invoice.total, invoice.paymentCurrency.decimal), "\xA0", invoice.paymentCurrency.symbol]
|
|
147
157
|
})
|
|
@@ -154,11 +164,9 @@ const InvoiceTable = _react.default.memo(props => {
|
|
|
154
164
|
options: {
|
|
155
165
|
customBodyRenderLite: (_, index) => {
|
|
156
166
|
const invoice = data.list[index];
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
target: link.external ? "_blank" : target,
|
|
161
|
-
rel: "noreferrer",
|
|
167
|
+
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
168
|
+
onClick: e => handleLinkClick(e, invoice),
|
|
169
|
+
sx: linkStyle,
|
|
162
170
|
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_status.default, {
|
|
163
171
|
label: (0, _util.getInvoiceDescriptionAndReason)(invoice, locale)?.type
|
|
164
172
|
})
|
|
@@ -171,11 +179,9 @@ const InvoiceTable = _react.default.memo(props => {
|
|
|
171
179
|
options: {
|
|
172
180
|
customBodyRenderLite: (_, index) => {
|
|
173
181
|
const invoice = data?.list[index];
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
target: link.external ? "_blank" : target,
|
|
178
|
-
rel: "noreferrer",
|
|
182
|
+
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
183
|
+
onClick: e => handleLinkClick(e, invoice),
|
|
184
|
+
sx: linkStyle,
|
|
179
185
|
children: invoice?.number
|
|
180
186
|
});
|
|
181
187
|
}
|
|
@@ -186,11 +192,9 @@ const InvoiceTable = _react.default.memo(props => {
|
|
|
186
192
|
options: {
|
|
187
193
|
customBodyRenderLite: (val, index) => {
|
|
188
194
|
const invoice = data?.list[index];
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
target: link.external ? "_blank" : target,
|
|
193
|
-
rel: "noreferrer",
|
|
195
|
+
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
196
|
+
onClick: e => handleLinkClick(e, invoice),
|
|
197
|
+
sx: linkStyle,
|
|
194
198
|
children: (0, _util.formatToDate)(invoice.created_at, locale, "YYYY-MM-DD HH:mm:ss")
|
|
195
199
|
});
|
|
196
200
|
}
|
|
@@ -202,11 +206,9 @@ const InvoiceTable = _react.default.memo(props => {
|
|
|
202
206
|
sort: false,
|
|
203
207
|
customBodyRenderLite: (val, index) => {
|
|
204
208
|
const invoice = data?.list[index];
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
target: link.external ? "_blank" : target,
|
|
209
|
-
rel: "noreferrer",
|
|
209
|
+
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
210
|
+
onClick: e => handleLinkClick(e, invoice),
|
|
211
|
+
sx: linkStyle,
|
|
210
212
|
children: (0, _util.getInvoiceDescriptionAndReason)(invoice, locale)?.description || invoice.id
|
|
211
213
|
});
|
|
212
214
|
}
|
|
@@ -217,10 +219,12 @@ const InvoiceTable = _react.default.memo(props => {
|
|
|
217
219
|
options: {
|
|
218
220
|
customBodyRenderLite: (val, index) => {
|
|
219
221
|
const invoice = data?.list[index];
|
|
220
|
-
const link = getInvoiceLink(invoice, action);
|
|
221
222
|
const hidePay = invoice.billing_reason === "overdraft-protection";
|
|
223
|
+
const {
|
|
224
|
+
connect
|
|
225
|
+
} = getInvoiceLink(invoice, action);
|
|
222
226
|
if (action && !hidePay) {
|
|
223
|
-
return
|
|
227
|
+
return connect ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
|
|
224
228
|
variant: "text",
|
|
225
229
|
size: "small",
|
|
226
230
|
onClick: () => onPay(invoice.id),
|
|
@@ -232,8 +236,7 @@ const InvoiceTable = _react.default.memo(props => {
|
|
|
232
236
|
component: "a",
|
|
233
237
|
variant: "text",
|
|
234
238
|
size: "small",
|
|
235
|
-
|
|
236
|
-
target: link.external ? "_blank" : target,
|
|
239
|
+
onClick: e => handleLinkClick(e, invoice),
|
|
237
240
|
sx: {
|
|
238
241
|
color: "var(--foregrounds-fg-interactive, #0086FF) !important"
|
|
239
242
|
},
|
|
@@ -241,10 +244,9 @@ const InvoiceTable = _react.default.memo(props => {
|
|
|
241
244
|
children: t("payment.customer.invoice.pay")
|
|
242
245
|
});
|
|
243
246
|
}
|
|
244
|
-
return /* @__PURE__ */(0, _jsxRuntime.jsx)(
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
rel: "noreferrer",
|
|
247
|
+
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
248
|
+
onClick: e => handleLinkClick(e, invoice),
|
|
249
|
+
sx: linkStyle,
|
|
248
250
|
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_status.default, {
|
|
249
251
|
label: invoice.status,
|
|
250
252
|
color: (0, _util.getInvoiceStatusColor)(invoice.status)
|
|
@@ -330,6 +332,7 @@ const InvoiceList = _react.default.memo(props => {
|
|
|
330
332
|
t,
|
|
331
333
|
locale
|
|
332
334
|
} = (0, _context.useLocaleContext)();
|
|
335
|
+
const navigate = (0, _reactRouterDom.useNavigate)();
|
|
333
336
|
const {
|
|
334
337
|
data,
|
|
335
338
|
loadMore,
|
|
@@ -404,6 +407,11 @@ const InvoiceList = _react.default.memo(props => {
|
|
|
404
407
|
}
|
|
405
408
|
const hasMore = data && data.list.length < data.count;
|
|
406
409
|
const grouped = groupByDate(data.list);
|
|
410
|
+
const handleLinkClick = (e, link) => {
|
|
411
|
+
(0, _navigation.handleNavigation)(e, link, navigate, {
|
|
412
|
+
target: link.external ? "_blank" : target
|
|
413
|
+
});
|
|
414
|
+
};
|
|
407
415
|
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(Root, {
|
|
408
416
|
direction: "column",
|
|
409
417
|
gap: 1,
|
|
@@ -420,7 +428,10 @@ const InvoiceList = _react.default.memo(props => {
|
|
|
420
428
|
},
|
|
421
429
|
children: date
|
|
422
430
|
}), invoices.map(invoice => {
|
|
423
|
-
const
|
|
431
|
+
const {
|
|
432
|
+
link,
|
|
433
|
+
connect
|
|
434
|
+
} = getInvoiceLink(invoice, action);
|
|
424
435
|
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
425
436
|
direction: "row",
|
|
426
437
|
sx: {
|
|
@@ -439,6 +450,7 @@ const InvoiceList = _react.default.memo(props => {
|
|
|
439
450
|
href: link.url,
|
|
440
451
|
target: link.external ? "_blank" : target,
|
|
441
452
|
rel: "noreferrer",
|
|
453
|
+
onClick: e => handleLinkClick(e, link),
|
|
442
454
|
children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
443
455
|
direction: "row",
|
|
444
456
|
alignItems: "center",
|
|
@@ -482,7 +494,7 @@ const InvoiceList = _react.default.memo(props => {
|
|
|
482
494
|
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
483
495
|
flex: 1,
|
|
484
496
|
textAlign: "right",
|
|
485
|
-
children: action ?
|
|
497
|
+
children: action ? connect ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
|
|
486
498
|
variant: "contained",
|
|
487
499
|
color: "primary",
|
|
488
500
|
size: "small",
|
|
@@ -495,8 +507,7 @@ const InvoiceList = _react.default.memo(props => {
|
|
|
495
507
|
component: "a",
|
|
496
508
|
variant: "contained",
|
|
497
509
|
size: "small",
|
|
498
|
-
|
|
499
|
-
target: link.external ? "_blank" : target,
|
|
510
|
+
onClick: e => handleLinkClick(e, link),
|
|
500
511
|
sx: {
|
|
501
512
|
whiteSpace: "nowrap"
|
|
502
513
|
},
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { NavigateFunction } from 'react-router-dom';
|
|
2
|
+
export interface LinkInfo {
|
|
3
|
+
url: string;
|
|
4
|
+
external: boolean;
|
|
5
|
+
path: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Check if currently running inside Payment Kit
|
|
9
|
+
*/
|
|
10
|
+
export declare function isInPaymentKit(): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Create link information object
|
|
13
|
+
* @param path Path or URL
|
|
14
|
+
* @param external Force external link behavior
|
|
15
|
+
*/
|
|
16
|
+
export declare function createLink(path: string, external?: boolean): LinkInfo;
|
|
17
|
+
/**
|
|
18
|
+
* Get HTML attributes for a link
|
|
19
|
+
* @param link Link information
|
|
20
|
+
* @param target Link target (default: _self)
|
|
21
|
+
*/
|
|
22
|
+
export declare function getLinkProps(link: LinkInfo, target?: string): Record<string, any>;
|
|
23
|
+
/**
|
|
24
|
+
* Handle link navigation
|
|
25
|
+
* @param e Click event
|
|
26
|
+
* @param link Link information
|
|
27
|
+
* @param navigate React Router navigate function
|
|
28
|
+
* @param options Navigation options
|
|
29
|
+
*/
|
|
30
|
+
export declare function handleNavigation(e: React.MouseEvent, link: LinkInfo, navigate?: NavigateFunction, options?: {
|
|
31
|
+
replace?: boolean;
|
|
32
|
+
target?: string;
|
|
33
|
+
}): void;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.createLink = createLink;
|
|
7
|
+
exports.getLinkProps = getLinkProps;
|
|
8
|
+
exports.handleNavigation = handleNavigation;
|
|
9
|
+
exports.isInPaymentKit = isInPaymentKit;
|
|
10
|
+
var _ufo = require("ufo");
|
|
11
|
+
var _util = require("./util");
|
|
12
|
+
function isInPaymentKit() {
|
|
13
|
+
const componentId = (window.blocklet?.componentId || "").split("/").pop();
|
|
14
|
+
return componentId === _util.PAYMENT_KIT_DID;
|
|
15
|
+
}
|
|
16
|
+
function createLink(path, external = false) {
|
|
17
|
+
const isAbsoluteUrl = /^https?:\/\//.test(path);
|
|
18
|
+
const isExternal = external || isAbsoluteUrl;
|
|
19
|
+
const url = isExternal ? path : (0, _ufo.joinURL)((0, _util.getPrefix)(), path);
|
|
20
|
+
return {
|
|
21
|
+
url,
|
|
22
|
+
external: isExternal,
|
|
23
|
+
path
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function getLinkProps(link, target = "_self") {
|
|
27
|
+
const props = {
|
|
28
|
+
href: link.url
|
|
29
|
+
};
|
|
30
|
+
if (link.external) {
|
|
31
|
+
props.target = target;
|
|
32
|
+
props.rel = target === "_blank" ? "noopener noreferrer" : void 0;
|
|
33
|
+
}
|
|
34
|
+
return props;
|
|
35
|
+
}
|
|
36
|
+
function handleNavigation(e, link, navigate, options = {}) {
|
|
37
|
+
if (e) {
|
|
38
|
+
e.preventDefault();
|
|
39
|
+
}
|
|
40
|
+
const {
|
|
41
|
+
replace = false,
|
|
42
|
+
target = "_self"
|
|
43
|
+
} = options;
|
|
44
|
+
if (link.external || target === "_blank") {
|
|
45
|
+
window.open(link.url, target);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (isInPaymentKit() && navigate) {
|
|
49
|
+
navigate(link.path, {
|
|
50
|
+
replace
|
|
51
|
+
});
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (replace) {
|
|
55
|
+
window.location.replace(link.url);
|
|
56
|
+
} else {
|
|
57
|
+
window.location.href = link.url;
|
|
58
|
+
}
|
|
59
|
+
}
|
package/lib/locales/en.js
CHANGED
|
@@ -252,8 +252,8 @@ module.exports = (0, _flat.default)({
|
|
|
252
252
|
}
|
|
253
253
|
},
|
|
254
254
|
recover: {
|
|
255
|
-
button: "
|
|
256
|
-
title: "
|
|
255
|
+
button: "Resume Subscription",
|
|
256
|
+
title: "Resume Your Subscription",
|
|
257
257
|
description: "Your subscription will not be canceled and will be automatically renewed on {date}, please confirm to continue"
|
|
258
258
|
},
|
|
259
259
|
changePlan: {
|
package/lib/locales/zh.js
CHANGED
|
@@ -252,8 +252,8 @@ module.exports = (0, _flat.default)({
|
|
|
252
252
|
}
|
|
253
253
|
},
|
|
254
254
|
recover: {
|
|
255
|
-
button: "\
|
|
256
|
-
title: "\
|
|
255
|
+
button: "\u6062\u590D\u8BA2\u9605",
|
|
256
|
+
title: "\u6062\u590D\u60A8\u7684\u8BA2\u9605",
|
|
257
257
|
description: "\u60A8\u7684\u8BA2\u9605\u5C06\u4E0D\u4F1A\u88AB\u53D6\u6D88\uFF0C\u5E76\u5C06\u5728{date}\u81EA\u52A8\u7EED\u8BA2\uFF0C\u8BF7\u786E\u8BA4\u662F\u5426\u7EE7\u7EED"
|
|
258
258
|
},
|
|
259
259
|
changePlan: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/payment-react",
|
|
3
|
-
"version": "1.18.
|
|
3
|
+
"version": "1.18.13",
|
|
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.18.
|
|
95
|
+
"@blocklet/payment-types": "1.18.13",
|
|
96
96
|
"@storybook/addon-essentials": "^7.6.20",
|
|
97
97
|
"@storybook/addon-interactions": "^7.6.20",
|
|
98
98
|
"@storybook/addon-links": "^7.6.20",
|
|
@@ -123,5 +123,5 @@
|
|
|
123
123
|
"vite-plugin-babel": "^1.2.0",
|
|
124
124
|
"vite-plugin-node-polyfills": "^0.21.0"
|
|
125
125
|
},
|
|
126
|
-
"gitHead": "
|
|
126
|
+
"gitHead": "b26aa859ba5961c7a8dedfc238a31476cf16036c"
|
|
127
127
|
}
|
package/src/components/link.tsx
CHANGED
|
@@ -22,6 +22,7 @@ type Props = {
|
|
|
22
22
|
mode?: 'default' | 'custom';
|
|
23
23
|
onPaid?: (subscriptionId: string, currencyId: string) => void;
|
|
24
24
|
dialogProps?: DialogProps;
|
|
25
|
+
inSubscriptionDetail?: boolean;
|
|
25
26
|
children?: (
|
|
26
27
|
handlePay: (item: SummaryItem) => void,
|
|
27
28
|
data: {
|
|
@@ -56,6 +57,7 @@ function OverdueInvoicePayment({
|
|
|
56
57
|
dialogProps = {},
|
|
57
58
|
children,
|
|
58
59
|
onPaid = () => {},
|
|
60
|
+
inSubscriptionDetail = false,
|
|
59
61
|
}: Props) {
|
|
60
62
|
const { t } = useLocaleContext();
|
|
61
63
|
const { connect } = usePaymentContext();
|
|
@@ -141,8 +143,15 @@ function OverdueInvoicePayment({
|
|
|
141
143
|
dialogProps.onClose?.();
|
|
142
144
|
};
|
|
143
145
|
|
|
146
|
+
const handleViewDetailClick = (e: React.MouseEvent) => {
|
|
147
|
+
if (inSubscriptionDetail) {
|
|
148
|
+
e.preventDefault();
|
|
149
|
+
handleClose();
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
|
|
144
153
|
if (loading) {
|
|
145
|
-
return
|
|
154
|
+
return null;
|
|
146
155
|
}
|
|
147
156
|
|
|
148
157
|
const renderPayButton = (item: SummaryItem, props: any) => {
|
|
@@ -184,6 +193,7 @@ function OverdueInvoicePayment({
|
|
|
184
193
|
{...(dialogProps || {})}
|
|
185
194
|
open={dialogOpen}
|
|
186
195
|
title={dialogProps?.title || t('payment.subscription.overdue.pastDue')}
|
|
196
|
+
sx={{ '& .MuiDialogContent-root': { pt: 0 } }}
|
|
187
197
|
onClose={handleClose}>
|
|
188
198
|
{error ? (
|
|
189
199
|
<Alert severity="error">{error.message}</Alert>
|
|
@@ -220,6 +230,7 @@ function OverdueInvoicePayment({
|
|
|
220
230
|
<a
|
|
221
231
|
href={subscriptionUrl}
|
|
222
232
|
target="_blank"
|
|
233
|
+
onClick={handleViewDetailClick}
|
|
223
234
|
rel="noreferrer"
|
|
224
235
|
style={{ color: 'var(--foregrounds-fg-interactive, 0086FF)' }}>
|
|
225
236
|
{t('payment.subscription.overdue.view')}
|
|
@@ -250,6 +261,7 @@ function OverdueInvoicePayment({
|
|
|
250
261
|
href={subscriptionUrl}
|
|
251
262
|
target="_blank"
|
|
252
263
|
rel="noreferrer"
|
|
264
|
+
onClick={handleViewDetailClick}
|
|
253
265
|
style={{ color: 'var(--foregrounds-fg-interactive, 0086FF)' }}>
|
|
254
266
|
{t('payment.subscription.overdue.view')}
|
|
255
267
|
</a>
|
|
@@ -303,6 +315,7 @@ OverdueInvoicePayment.defaultProps = {
|
|
|
303
315
|
open: true,
|
|
304
316
|
},
|
|
305
317
|
children: null,
|
|
318
|
+
inSubscriptionDetail: false,
|
|
306
319
|
};
|
|
307
320
|
|
|
308
321
|
export default OverdueInvoicePayment;
|
|
@@ -12,7 +12,8 @@ import { Box, Button, CircularProgress, Hidden, Stack, Typography } from '@mui/m
|
|
|
12
12
|
import { styled } from '@mui/system';
|
|
13
13
|
import { useInfiniteScroll, useRequest, useSetState } from 'ahooks';
|
|
14
14
|
import React, { useEffect, useRef, useState } from 'react';
|
|
15
|
-
|
|
15
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
16
|
+
import { useNavigate } from 'react-router-dom';
|
|
16
17
|
|
|
17
18
|
import debounce from 'lodash/debounce';
|
|
18
19
|
import Status from '../../components/status';
|
|
@@ -26,10 +27,10 @@ import {
|
|
|
26
27
|
formatToDatetime,
|
|
27
28
|
getInvoiceDescriptionAndReason,
|
|
28
29
|
getInvoiceStatusColor,
|
|
29
|
-
getPrefix,
|
|
30
30
|
getTxLink,
|
|
31
31
|
} from '../../libs/util';
|
|
32
32
|
import Table from '../../components/table';
|
|
33
|
+
import { createLink, handleNavigation, LinkInfo } from '../../libs/navigation';
|
|
33
34
|
|
|
34
35
|
type Result = Paginated<TInvoiceExpanded> & { subscription: TSubscription };
|
|
35
36
|
|
|
@@ -72,23 +73,23 @@ type Props = {
|
|
|
72
73
|
|
|
73
74
|
const getInvoiceLink = (invoice: TInvoiceExpanded, action?: string) => {
|
|
74
75
|
if (invoice.id.startsWith('in_')) {
|
|
76
|
+
const path = `/customer/invoice/${invoice.id}${invoice.status === 'uncollectible' && action ? `?action=${action}` : ''}`;
|
|
75
77
|
return {
|
|
76
|
-
external: false,
|
|
77
78
|
connect: invoice.status === 'uncollectible',
|
|
78
|
-
|
|
79
|
-
getPrefix(),
|
|
80
|
-
`/customer/invoice/${invoice.id}?action=${invoice.status === 'uncollectible' ? action : ''}`
|
|
81
|
-
),
|
|
79
|
+
link: createLink(path),
|
|
82
80
|
};
|
|
83
81
|
}
|
|
84
82
|
|
|
85
83
|
return {
|
|
86
|
-
external: true,
|
|
87
84
|
connect: false,
|
|
88
|
-
|
|
85
|
+
link: createLink(getTxLink(invoice.paymentMethod, invoice.metadata?.payment_details).link, true),
|
|
89
86
|
};
|
|
90
87
|
};
|
|
91
88
|
|
|
89
|
+
const linkStyle = {
|
|
90
|
+
cursor: 'pointer',
|
|
91
|
+
};
|
|
92
|
+
|
|
92
93
|
const InvoiceTable = React.memo((props: Props & { onPay: (invoiceId: string) => void }) => {
|
|
93
94
|
const {
|
|
94
95
|
pageSize,
|
|
@@ -106,6 +107,7 @@ const InvoiceTable = React.memo((props: Props & { onPay: (invoiceId: string) =>
|
|
|
106
107
|
} = props;
|
|
107
108
|
const listKey = 'invoice-table';
|
|
108
109
|
const { t, locale } = useLocaleContext();
|
|
110
|
+
const navigate = useNavigate();
|
|
109
111
|
|
|
110
112
|
const [search, setSearch] = useState<{ pageSize: number; page: number }>({
|
|
111
113
|
pageSize: pageSize || 10,
|
|
@@ -170,6 +172,11 @@ const InvoiceTable = React.memo((props: Props & { onPay: (invoiceId: string) =>
|
|
|
170
172
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
171
173
|
}, [subscription]);
|
|
172
174
|
|
|
175
|
+
const handleLinkClick = (e: React.MouseEvent, invoice: TInvoiceExpanded) => {
|
|
176
|
+
const { link } = getInvoiceLink(invoice, action);
|
|
177
|
+
handleNavigation(e, link, navigate, { target: link.external ? '_blank' : target });
|
|
178
|
+
};
|
|
179
|
+
|
|
173
180
|
const columns = [
|
|
174
181
|
{
|
|
175
182
|
label: t('common.amount'),
|
|
@@ -179,14 +186,13 @@ const InvoiceTable = React.memo((props: Props & { onPay: (invoiceId: string) =>
|
|
|
179
186
|
options: {
|
|
180
187
|
customBodyRenderLite: (_: string, index: number) => {
|
|
181
188
|
const invoice = data?.list[index] as TInvoiceExpanded;
|
|
182
|
-
const link = getInvoiceLink(invoice, action);
|
|
183
189
|
return (
|
|
184
|
-
<
|
|
190
|
+
<Box onClick={(e) => handleLinkClick(e, invoice)} sx={linkStyle}>
|
|
185
191
|
<Typography>
|
|
186
192
|
{formatBNStr(invoice.total, invoice.paymentCurrency.decimal)}
|
|
187
193
|
{invoice.paymentCurrency.symbol}
|
|
188
194
|
</Typography>
|
|
189
|
-
</
|
|
195
|
+
</Box>
|
|
190
196
|
);
|
|
191
197
|
},
|
|
192
198
|
},
|
|
@@ -197,11 +203,10 @@ const InvoiceTable = React.memo((props: Props & { onPay: (invoiceId: string) =>
|
|
|
197
203
|
options: {
|
|
198
204
|
customBodyRenderLite: (_: string, index: number) => {
|
|
199
205
|
const invoice = data.list[index] as TInvoiceExpanded;
|
|
200
|
-
const link = getInvoiceLink(invoice, action);
|
|
201
206
|
return (
|
|
202
|
-
<
|
|
207
|
+
<Box onClick={(e) => handleLinkClick(e, invoice)} sx={linkStyle}>
|
|
203
208
|
<Status label={getInvoiceDescriptionAndReason(invoice, locale)?.type} />
|
|
204
|
-
</
|
|
209
|
+
</Box>
|
|
205
210
|
);
|
|
206
211
|
},
|
|
207
212
|
},
|
|
@@ -212,11 +217,10 @@ const InvoiceTable = React.memo((props: Props & { onPay: (invoiceId: string) =>
|
|
|
212
217
|
options: {
|
|
213
218
|
customBodyRenderLite: (_: string, index: number) => {
|
|
214
219
|
const invoice = data?.list[index] as TInvoiceExpanded;
|
|
215
|
-
const link = getInvoiceLink(invoice, action);
|
|
216
220
|
return (
|
|
217
|
-
<
|
|
221
|
+
<Box onClick={(e) => handleLinkClick(e, invoice)} sx={linkStyle}>
|
|
218
222
|
{invoice?.number}
|
|
219
|
-
</
|
|
223
|
+
</Box>
|
|
220
224
|
);
|
|
221
225
|
},
|
|
222
226
|
},
|
|
@@ -227,11 +231,11 @@ const InvoiceTable = React.memo((props: Props & { onPay: (invoiceId: string) =>
|
|
|
227
231
|
options: {
|
|
228
232
|
customBodyRenderLite: (val: string, index: number) => {
|
|
229
233
|
const invoice = data?.list[index] as TInvoiceExpanded;
|
|
230
|
-
|
|
234
|
+
|
|
231
235
|
return (
|
|
232
|
-
<
|
|
236
|
+
<Box onClick={(e) => handleLinkClick(e, invoice)} sx={linkStyle}>
|
|
233
237
|
{formatToDate(invoice.created_at, locale, 'YYYY-MM-DD HH:mm:ss')}
|
|
234
|
-
</
|
|
238
|
+
</Box>
|
|
235
239
|
);
|
|
236
240
|
},
|
|
237
241
|
},
|
|
@@ -243,11 +247,11 @@ const InvoiceTable = React.memo((props: Props & { onPay: (invoiceId: string) =>
|
|
|
243
247
|
sort: false,
|
|
244
248
|
customBodyRenderLite: (val: string, index: number) => {
|
|
245
249
|
const invoice = data?.list[index] as TInvoiceExpanded;
|
|
246
|
-
|
|
250
|
+
|
|
247
251
|
return (
|
|
248
|
-
<
|
|
252
|
+
<Box onClick={(e) => handleLinkClick(e, invoice)} sx={linkStyle}>
|
|
249
253
|
{getInvoiceDescriptionAndReason(invoice, locale)?.description || invoice.id}
|
|
250
|
-
</
|
|
254
|
+
</Box>
|
|
251
255
|
);
|
|
252
256
|
},
|
|
253
257
|
},
|
|
@@ -258,10 +262,10 @@ const InvoiceTable = React.memo((props: Props & { onPay: (invoiceId: string) =>
|
|
|
258
262
|
options: {
|
|
259
263
|
customBodyRenderLite: (val: string, index: number) => {
|
|
260
264
|
const invoice = data?.list[index] as TInvoiceExpanded;
|
|
261
|
-
const link = getInvoiceLink(invoice, action);
|
|
262
265
|
const hidePay = invoice.billing_reason === 'overdraft-protection';
|
|
266
|
+
const { connect } = getInvoiceLink(invoice, action);
|
|
263
267
|
if (action && !hidePay) {
|
|
264
|
-
return
|
|
268
|
+
return connect ? (
|
|
265
269
|
<Button variant="text" size="small" onClick={() => onPay(invoice.id)} sx={{ color: 'text.link' }}>
|
|
266
270
|
{t('payment.customer.invoice.pay')}
|
|
267
271
|
</Button>
|
|
@@ -270,8 +274,7 @@ const InvoiceTable = React.memo((props: Props & { onPay: (invoiceId: string) =>
|
|
|
270
274
|
component="a"
|
|
271
275
|
variant="text"
|
|
272
276
|
size="small"
|
|
273
|
-
|
|
274
|
-
target={link.external ? '_blank' : target}
|
|
277
|
+
onClick={(e) => handleLinkClick(e, invoice)}
|
|
275
278
|
sx={{ color: 'var(--foregrounds-fg-interactive, #0086FF) !important' }}
|
|
276
279
|
rel="noreferrer">
|
|
277
280
|
{t('payment.customer.invoice.pay')}
|
|
@@ -279,9 +282,9 @@ const InvoiceTable = React.memo((props: Props & { onPay: (invoiceId: string) =>
|
|
|
279
282
|
);
|
|
280
283
|
}
|
|
281
284
|
return (
|
|
282
|
-
<
|
|
285
|
+
<Box onClick={(e) => handleLinkClick(e, invoice)} sx={linkStyle}>
|
|
283
286
|
<Status label={invoice.status} color={getInvoiceStatusColor(invoice.status)} />
|
|
284
|
-
</
|
|
287
|
+
</Box>
|
|
285
288
|
);
|
|
286
289
|
},
|
|
287
290
|
},
|
|
@@ -354,6 +357,7 @@ const InvoiceList = React.memo((props: Props & { onPay: (invoiceId: string) => v
|
|
|
354
357
|
|
|
355
358
|
const subscription = useSubscription('events');
|
|
356
359
|
const { t, locale } = useLocaleContext();
|
|
360
|
+
const navigate = useNavigate();
|
|
357
361
|
|
|
358
362
|
const { data, loadMore, loadingMore, loading, reloadAsync } = useInfiniteScroll<Result>(
|
|
359
363
|
(d) => {
|
|
@@ -433,13 +437,17 @@ const InvoiceList = React.memo((props: Props & { onPay: (invoiceId: string) => v
|
|
|
433
437
|
|
|
434
438
|
const grouped = groupByDate(data.list as any);
|
|
435
439
|
|
|
440
|
+
const handleLinkClick = (e: React.MouseEvent, link: LinkInfo) => {
|
|
441
|
+
handleNavigation(e, link, navigate, { target: link.external ? '_blank' : target });
|
|
442
|
+
};
|
|
443
|
+
|
|
436
444
|
return (
|
|
437
445
|
<Root direction="column" gap={1} sx={{ mt: 1 }}>
|
|
438
446
|
{Object.entries(grouped).map(([date, invoices]) => (
|
|
439
447
|
<Box key={date}>
|
|
440
448
|
<Typography sx={{ fontWeight: 'bold', color: 'text.secondary', mt: 2, mb: 1 }}>{date}</Typography>
|
|
441
449
|
{invoices.map((invoice) => {
|
|
442
|
-
const link = getInvoiceLink(invoice, action);
|
|
450
|
+
const { link, connect } = getInvoiceLink(invoice, action);
|
|
443
451
|
return (
|
|
444
452
|
<Stack
|
|
445
453
|
key={invoice.id}
|
|
@@ -453,7 +461,11 @@ const InvoiceList = React.memo((props: Props & { onPay: (invoiceId: string) => v
|
|
|
453
461
|
alignItems="center"
|
|
454
462
|
flexWrap="nowrap">
|
|
455
463
|
<Box flex={2}>
|
|
456
|
-
<a
|
|
464
|
+
<a
|
|
465
|
+
href={link.url}
|
|
466
|
+
target={link.external ? '_blank' : target}
|
|
467
|
+
rel="noreferrer"
|
|
468
|
+
onClick={(e) => handleLinkClick(e, link)}>
|
|
457
469
|
<Stack direction="row" alignItems="center" spacing={0.5}>
|
|
458
470
|
<Typography component="span">{invoice.number}</Typography>
|
|
459
471
|
{link.external && (
|
|
@@ -482,7 +494,7 @@ const InvoiceList = React.memo((props: Props & { onPay: (invoiceId: string) => v
|
|
|
482
494
|
)}
|
|
483
495
|
<Box flex={1} textAlign="right">
|
|
484
496
|
{action ? (
|
|
485
|
-
|
|
497
|
+
connect ? (
|
|
486
498
|
<Button
|
|
487
499
|
variant="contained"
|
|
488
500
|
color="primary"
|
|
@@ -496,8 +508,7 @@ const InvoiceList = React.memo((props: Props & { onPay: (invoiceId: string) => v
|
|
|
496
508
|
component="a"
|
|
497
509
|
variant="contained"
|
|
498
510
|
size="small"
|
|
499
|
-
|
|
500
|
-
target={link.external ? '_blank' : target}
|
|
511
|
+
onClick={(e) => handleLinkClick(e, link)}
|
|
501
512
|
sx={{ whiteSpace: 'nowrap' }}
|
|
502
513
|
rel="noreferrer">
|
|
503
514
|
{t('payment.customer.invoice.pay')}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
2
|
+
import { NavigateFunction } from 'react-router-dom';
|
|
3
|
+
import { joinURL } from 'ufo';
|
|
4
|
+
import { getPrefix, PAYMENT_KIT_DID } from './util';
|
|
5
|
+
|
|
6
|
+
export interface LinkInfo {
|
|
7
|
+
// Full URL for href attribute
|
|
8
|
+
url: string;
|
|
9
|
+
// Whether this is an external link
|
|
10
|
+
external: boolean;
|
|
11
|
+
// Original path (used for React Router)
|
|
12
|
+
path: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Check if currently running inside Payment Kit
|
|
17
|
+
*/
|
|
18
|
+
export function isInPaymentKit(): boolean {
|
|
19
|
+
const componentId = (window.blocklet?.componentId || '').split('/').pop();
|
|
20
|
+
return componentId === PAYMENT_KIT_DID;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Create link information object
|
|
25
|
+
* @param path Path or URL
|
|
26
|
+
* @param external Force external link behavior
|
|
27
|
+
*/
|
|
28
|
+
export function createLink(path: string, external = false): LinkInfo {
|
|
29
|
+
const isAbsoluteUrl = /^https?:\/\//.test(path);
|
|
30
|
+
const isExternal = external || isAbsoluteUrl;
|
|
31
|
+
const url = isExternal ? path : joinURL(getPrefix(), path);
|
|
32
|
+
return {
|
|
33
|
+
url,
|
|
34
|
+
external: isExternal,
|
|
35
|
+
path,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Get HTML attributes for a link
|
|
41
|
+
* @param link Link information
|
|
42
|
+
* @param target Link target (default: _self)
|
|
43
|
+
*/
|
|
44
|
+
export function getLinkProps(link: LinkInfo, target = '_self'): Record<string, any> {
|
|
45
|
+
const props: Record<string, any> = {
|
|
46
|
+
href: link.url,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
if (link.external) {
|
|
50
|
+
props.target = target;
|
|
51
|
+
props.rel = target === '_blank' ? 'noopener noreferrer' : undefined;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return props;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Handle link navigation
|
|
59
|
+
* @param e Click event
|
|
60
|
+
* @param link Link information
|
|
61
|
+
* @param navigate React Router navigate function
|
|
62
|
+
* @param options Navigation options
|
|
63
|
+
*/
|
|
64
|
+
export function handleNavigation(
|
|
65
|
+
e: React.MouseEvent,
|
|
66
|
+
link: LinkInfo,
|
|
67
|
+
navigate?: NavigateFunction,
|
|
68
|
+
options: { replace?: boolean; target?: string } = {}
|
|
69
|
+
): void {
|
|
70
|
+
if (e) {
|
|
71
|
+
e.preventDefault();
|
|
72
|
+
}
|
|
73
|
+
const { replace = false, target = '_self' } = options;
|
|
74
|
+
if (link.external || target === '_blank') {
|
|
75
|
+
window.open(link.url, target);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (isInPaymentKit() && navigate) {
|
|
80
|
+
navigate(link.path, { replace });
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (replace) {
|
|
85
|
+
window.location.replace(link.url);
|
|
86
|
+
} else {
|
|
87
|
+
window.location.href = link.url;
|
|
88
|
+
}
|
|
89
|
+
}
|
package/src/locales/en.tsx
CHANGED
|
@@ -254,8 +254,8 @@ export default flat({
|
|
|
254
254
|
},
|
|
255
255
|
},
|
|
256
256
|
recover: {
|
|
257
|
-
button: '
|
|
258
|
-
title: '
|
|
257
|
+
button: 'Resume Subscription',
|
|
258
|
+
title: 'Resume Your Subscription',
|
|
259
259
|
description:
|
|
260
260
|
'Your subscription will not be canceled and will be automatically renewed on {date}, please confirm to continue',
|
|
261
261
|
},
|