@blocklet/payment-react 1.19.18 → 1.19.20
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 +313 -0
- package/es/checkout/form.js +18 -2
- package/es/components/auto-topup/index.d.ts +14 -0
- package/es/components/auto-topup/index.js +417 -0
- package/es/components/auto-topup/modal.d.ts +35 -0
- package/es/components/auto-topup/modal.js +734 -0
- package/es/components/auto-topup/product-card.d.ts +13 -0
- package/es/components/auto-topup/product-card.js +173 -0
- package/es/components/collapse.d.ts +13 -0
- package/es/components/collapse.js +76 -0
- package/es/components/input.d.ts +2 -1
- package/es/components/input.js +64 -13
- package/es/components/label.d.ts +2 -1
- package/es/components/label.js +2 -1
- package/es/index.d.ts +4 -1
- package/es/index.js +7 -1
- package/es/libs/util.js +2 -1
- package/es/locales/en.js +56 -0
- package/es/locales/zh.js +56 -0
- package/es/payment/form/index.js +17 -1
- package/es/payment/product-item.js +17 -10
- package/lib/checkout/form.js +18 -2
- package/lib/components/auto-topup/index.d.ts +14 -0
- package/lib/components/auto-topup/index.js +451 -0
- package/lib/components/auto-topup/modal.d.ts +35 -0
- package/lib/components/auto-topup/modal.js +803 -0
- package/lib/components/auto-topup/product-card.d.ts +13 -0
- package/lib/components/auto-topup/product-card.js +149 -0
- package/lib/components/collapse.d.ts +13 -0
- package/lib/components/collapse.js +74 -0
- package/lib/components/input.d.ts +2 -1
- package/lib/components/input.js +66 -24
- package/lib/components/label.d.ts +2 -1
- package/lib/components/label.js +3 -1
- package/lib/index.d.ts +4 -1
- package/lib/index.js +24 -0
- package/lib/libs/util.js +2 -1
- package/lib/locales/en.js +56 -0
- package/lib/locales/zh.js +56 -0
- package/lib/payment/form/index.js +17 -1
- package/lib/payment/product-item.js +18 -10
- package/package.json +9 -9
- package/src/checkout/form.tsx +21 -2
- package/src/components/auto-topup/index.tsx +449 -0
- package/src/components/auto-topup/modal.tsx +773 -0
- package/src/components/auto-topup/product-card.tsx +156 -0
- package/src/components/collapse.tsx +82 -0
- package/src/components/input.tsx +71 -22
- package/src/components/label.tsx +8 -2
- package/src/index.ts +7 -0
- package/src/libs/util.ts +1 -0
- package/src/locales/en.tsx +59 -0
- package/src/locales/zh.tsx +57 -0
- package/src/payment/form/index.tsx +19 -1
- package/src/payment/product-item.tsx +18 -11
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { TPaymentCurrency } from '@blocklet/payment-types';
|
|
2
|
+
interface AutoTopupProductCardProps {
|
|
3
|
+
product: any;
|
|
4
|
+
price: any;
|
|
5
|
+
currency: TPaymentCurrency;
|
|
6
|
+
quantity: number;
|
|
7
|
+
onQuantityChange: (quantity: number) => void;
|
|
8
|
+
maxQuantity?: number;
|
|
9
|
+
minQuantity?: number;
|
|
10
|
+
creditCurrency: TPaymentCurrency;
|
|
11
|
+
}
|
|
12
|
+
export default function AutoTopupProductCard({ product, price, currency, quantity, onQuantityChange, maxQuantity, minQuantity, creditCurrency, }: AutoTopupProductCardProps): import("react").JSX.Element;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Stack, Typography, TextField, Card } from "@mui/material";
|
|
3
|
+
import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
|
|
4
|
+
import { useState } from "react";
|
|
5
|
+
import ProductCard from "../../payment/product-card.js";
|
|
6
|
+
import { formatPrice, formatNumber } from "../../libs/util.js";
|
|
7
|
+
export default function AutoTopupProductCard({
|
|
8
|
+
product,
|
|
9
|
+
price,
|
|
10
|
+
currency,
|
|
11
|
+
quantity,
|
|
12
|
+
onQuantityChange,
|
|
13
|
+
maxQuantity = 99,
|
|
14
|
+
minQuantity = 1,
|
|
15
|
+
creditCurrency
|
|
16
|
+
}) {
|
|
17
|
+
const { t } = useLocaleContext();
|
|
18
|
+
const [localQuantity, setLocalQuantity] = useState(quantity);
|
|
19
|
+
const localQuantityNum = Number(localQuantity) || 0;
|
|
20
|
+
const handleQuantityChange = (newQuantity) => {
|
|
21
|
+
if (!newQuantity) {
|
|
22
|
+
setLocalQuantity(void 0);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (newQuantity >= minQuantity && newQuantity <= maxQuantity) {
|
|
26
|
+
setLocalQuantity(newQuantity);
|
|
27
|
+
onQuantityChange(newQuantity);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const handleQuantityInputChange = (event) => {
|
|
31
|
+
const value = parseInt(event.target.value || "0", 10);
|
|
32
|
+
if (!Number.isNaN(value)) {
|
|
33
|
+
handleQuantityChange(value);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const creditUnitAmount = Number(price.metadata?.credit_config?.credit_amount || 0);
|
|
37
|
+
return /* @__PURE__ */ jsxs(Card, { variant: "outlined", sx: { p: 2 }, children: [
|
|
38
|
+
/* @__PURE__ */ jsxs(
|
|
39
|
+
Stack,
|
|
40
|
+
{
|
|
41
|
+
direction: "row",
|
|
42
|
+
spacing: 2,
|
|
43
|
+
sx: {
|
|
44
|
+
flexDirection: {
|
|
45
|
+
xs: "column",
|
|
46
|
+
sm: "row"
|
|
47
|
+
},
|
|
48
|
+
alignItems: {
|
|
49
|
+
xs: "flex-start",
|
|
50
|
+
sm: "center"
|
|
51
|
+
},
|
|
52
|
+
justifyContent: {
|
|
53
|
+
xs: "flex-start",
|
|
54
|
+
sm: "space-between"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
children: [
|
|
58
|
+
/* @__PURE__ */ jsx(
|
|
59
|
+
Stack,
|
|
60
|
+
{
|
|
61
|
+
direction: "row",
|
|
62
|
+
spacing: 2,
|
|
63
|
+
sx: {
|
|
64
|
+
alignItems: "center",
|
|
65
|
+
flex: 1
|
|
66
|
+
},
|
|
67
|
+
children: /* @__PURE__ */ jsx(
|
|
68
|
+
ProductCard,
|
|
69
|
+
{
|
|
70
|
+
name: product?.name || "",
|
|
71
|
+
description: t("payment.autoTopup.creditsIncluded", {
|
|
72
|
+
name: creditCurrency?.name,
|
|
73
|
+
num: formatNumber(creditUnitAmount * localQuantityNum)
|
|
74
|
+
}),
|
|
75
|
+
logo: product?.images?.[0],
|
|
76
|
+
size: 40
|
|
77
|
+
}
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
),
|
|
81
|
+
/* @__PURE__ */ jsxs(
|
|
82
|
+
Stack,
|
|
83
|
+
{
|
|
84
|
+
direction: "row",
|
|
85
|
+
spacing: 1,
|
|
86
|
+
sx: {
|
|
87
|
+
alignItems: "center",
|
|
88
|
+
alignSelf: {
|
|
89
|
+
xs: "flex-end",
|
|
90
|
+
sm: "center"
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
children: [
|
|
94
|
+
/* @__PURE__ */ jsxs(
|
|
95
|
+
Typography,
|
|
96
|
+
{
|
|
97
|
+
variant: "body2",
|
|
98
|
+
sx: {
|
|
99
|
+
color: "text.secondary",
|
|
100
|
+
minWidth: "fit-content"
|
|
101
|
+
},
|
|
102
|
+
children: [
|
|
103
|
+
t("common.quantity"),
|
|
104
|
+
":"
|
|
105
|
+
]
|
|
106
|
+
}
|
|
107
|
+
),
|
|
108
|
+
/* @__PURE__ */ jsx(
|
|
109
|
+
TextField,
|
|
110
|
+
{
|
|
111
|
+
size: "small",
|
|
112
|
+
value: localQuantity,
|
|
113
|
+
onChange: handleQuantityInputChange,
|
|
114
|
+
type: "number",
|
|
115
|
+
sx: {
|
|
116
|
+
"& .MuiInputBase-root": {
|
|
117
|
+
height: 32
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
slotProps: {
|
|
121
|
+
htmlInput: {
|
|
122
|
+
min: 0,
|
|
123
|
+
max: maxQuantity,
|
|
124
|
+
style: { textAlign: "center", padding: "4px 8px" }
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
)
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
)
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
),
|
|
135
|
+
/* @__PURE__ */ jsxs(
|
|
136
|
+
Stack,
|
|
137
|
+
{
|
|
138
|
+
direction: "row",
|
|
139
|
+
sx: {
|
|
140
|
+
justifyContent: "space-between",
|
|
141
|
+
alignItems: "center",
|
|
142
|
+
mt: 2,
|
|
143
|
+
pt: 2,
|
|
144
|
+
borderTop: "1px solid",
|
|
145
|
+
borderColor: "divider"
|
|
146
|
+
},
|
|
147
|
+
children: [
|
|
148
|
+
/* @__PURE__ */ jsx(
|
|
149
|
+
Typography,
|
|
150
|
+
{
|
|
151
|
+
variant: "body2",
|
|
152
|
+
sx: {
|
|
153
|
+
color: "text.secondary"
|
|
154
|
+
},
|
|
155
|
+
children: t("payment.autoTopup.rechargeAmount")
|
|
156
|
+
}
|
|
157
|
+
),
|
|
158
|
+
/* @__PURE__ */ jsx(
|
|
159
|
+
Typography,
|
|
160
|
+
{
|
|
161
|
+
variant: "h6",
|
|
162
|
+
sx: {
|
|
163
|
+
fontWeight: 600,
|
|
164
|
+
color: "text.primary"
|
|
165
|
+
},
|
|
166
|
+
children: formatPrice(price, currency, product?.unit_label, localQuantity, true)
|
|
167
|
+
}
|
|
168
|
+
)
|
|
169
|
+
]
|
|
170
|
+
}
|
|
171
|
+
)
|
|
172
|
+
] });
|
|
173
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
trigger: string | ((expanded: boolean) => React.ReactNode) | React.ReactNode;
|
|
3
|
+
children?: React.ReactNode;
|
|
4
|
+
expanded?: boolean;
|
|
5
|
+
addons?: React.ReactNode;
|
|
6
|
+
style?: Record<string, any>;
|
|
7
|
+
value?: string;
|
|
8
|
+
onChange?: (value: string, expanded: boolean) => void;
|
|
9
|
+
lazy?: boolean;
|
|
10
|
+
card?: boolean;
|
|
11
|
+
};
|
|
12
|
+
export default function IconCollapse(rawProps: Props): import("react").JSX.Element;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ExpandLessOutlined, ExpandMoreOutlined } from "@mui/icons-material";
|
|
3
|
+
import { Box, Collapse, Stack } from "@mui/material";
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
5
|
+
export default function IconCollapse(rawProps) {
|
|
6
|
+
const props = Object.assign(
|
|
7
|
+
{
|
|
8
|
+
value: "",
|
|
9
|
+
onChange: () => {
|
|
10
|
+
},
|
|
11
|
+
children: null,
|
|
12
|
+
expanded: false,
|
|
13
|
+
addons: null,
|
|
14
|
+
style: {},
|
|
15
|
+
lazy: true,
|
|
16
|
+
card: false
|
|
17
|
+
},
|
|
18
|
+
rawProps
|
|
19
|
+
);
|
|
20
|
+
const [expanded, setExpanded] = useState(props.expanded || false);
|
|
21
|
+
const toggleExpanded = () => {
|
|
22
|
+
const newExpanded = !expanded;
|
|
23
|
+
setExpanded(newExpanded);
|
|
24
|
+
};
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
setExpanded(props.expanded || false);
|
|
27
|
+
}, [props.expanded]);
|
|
28
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
29
|
+
/* @__PURE__ */ jsxs(
|
|
30
|
+
Stack,
|
|
31
|
+
{
|
|
32
|
+
direction: "row",
|
|
33
|
+
onClick: (e) => {
|
|
34
|
+
e.stopPropagation();
|
|
35
|
+
props.onChange?.(props.value || "", !expanded);
|
|
36
|
+
toggleExpanded();
|
|
37
|
+
},
|
|
38
|
+
sx: {
|
|
39
|
+
alignItems: "center",
|
|
40
|
+
justifyContent: "space-between",
|
|
41
|
+
width: 1,
|
|
42
|
+
cursor: "pointer",
|
|
43
|
+
fontWeight: 500,
|
|
44
|
+
color: "text.primary",
|
|
45
|
+
"& :hover": { color: "primary.main" },
|
|
46
|
+
...props.card && {
|
|
47
|
+
borderRadius: 1,
|
|
48
|
+
padding: 1,
|
|
49
|
+
pl: 2,
|
|
50
|
+
backgroundColor: "grey.100"
|
|
51
|
+
},
|
|
52
|
+
...props.style
|
|
53
|
+
},
|
|
54
|
+
children: [
|
|
55
|
+
/* @__PURE__ */ jsx(Box, { children: typeof props.trigger === "function" ? props.trigger(expanded) : props.trigger }),
|
|
56
|
+
/* @__PURE__ */ jsxs(
|
|
57
|
+
Stack,
|
|
58
|
+
{
|
|
59
|
+
direction: "row",
|
|
60
|
+
spacing: 2,
|
|
61
|
+
sx: {
|
|
62
|
+
alignItems: "center"
|
|
63
|
+
},
|
|
64
|
+
children: [
|
|
65
|
+
props.addons,
|
|
66
|
+
" ",
|
|
67
|
+
expanded ? /* @__PURE__ */ jsx(ExpandLessOutlined, {}) : /* @__PURE__ */ jsx(ExpandMoreOutlined, {})
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
),
|
|
74
|
+
/* @__PURE__ */ jsx(Collapse, { in: expanded, sx: { width: "100%" }, children: expanded || props.lazy ? props.children : null })
|
|
75
|
+
] });
|
|
76
|
+
}
|
package/es/components/input.d.ts
CHANGED
|
@@ -11,8 +11,9 @@ type InputProps = TextFieldProps & {
|
|
|
11
11
|
required?: boolean;
|
|
12
12
|
tooltip?: ReactNode | string;
|
|
13
13
|
description?: ReactNode | string;
|
|
14
|
+
layout?: 'vertical' | 'horizontal';
|
|
14
15
|
};
|
|
15
|
-
export default function FormInput({ ref, name, label, placeholder, rules, errorPosition, wrapperStyle, inputProps, required, tooltip, description, ...rest }: InputProps & {
|
|
16
|
+
export default function FormInput({ ref, name, label, placeholder, rules, errorPosition, wrapperStyle, inputProps, required, tooltip, description, layout, slotProps, ...rest }: InputProps & {
|
|
16
17
|
ref?: React.RefObject<HTMLInputElement | null>;
|
|
17
18
|
inputProps?: TextFieldProps['inputProps'];
|
|
18
19
|
}): JSX.Element;
|
package/es/components/input.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useImperativeHandle, useRef } from "react";
|
|
3
|
-
import { Box, InputAdornment, TextField, Typography } from "@mui/material";
|
|
3
|
+
import { Box, InputAdornment, TextField, Typography, Stack, useMediaQuery, useTheme } from "@mui/material";
|
|
4
4
|
import get from "lodash/get";
|
|
5
5
|
import { Controller, useFormContext } from "react-hook-form";
|
|
6
6
|
import FormLabel from "./label.js";
|
|
@@ -19,43 +19,94 @@ export default function FormInput({
|
|
|
19
19
|
required = false,
|
|
20
20
|
tooltip = "",
|
|
21
21
|
description = "",
|
|
22
|
+
layout = "vertical",
|
|
23
|
+
slotProps,
|
|
22
24
|
...rest
|
|
23
25
|
}) {
|
|
24
26
|
const { control, formState } = useFormContext();
|
|
27
|
+
const theme = useTheme();
|
|
28
|
+
const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
|
|
25
29
|
const inputRef = useRef(null);
|
|
26
30
|
useImperativeHandle(ref, () => {
|
|
27
31
|
return inputRef.current;
|
|
28
32
|
});
|
|
29
33
|
const error = get(formState.errors, name)?.message;
|
|
34
|
+
const isHorizontal = layout === "horizontal" && !isMobile;
|
|
35
|
+
const mergedSlotProps = {
|
|
36
|
+
htmlInput: { ...inputProps, ...slotProps?.htmlInput },
|
|
37
|
+
input: Object.assign(
|
|
38
|
+
rest.InputProps || {},
|
|
39
|
+
slotProps?.input || {},
|
|
40
|
+
errorPosition === "right" && error ? { endAdornment: /* @__PURE__ */ jsx(FormInputError, { error }) } : {}
|
|
41
|
+
)
|
|
42
|
+
};
|
|
43
|
+
const renderLabel = () => {
|
|
44
|
+
if (!label) return null;
|
|
45
|
+
return /* @__PURE__ */ jsx(
|
|
46
|
+
FormLabel,
|
|
47
|
+
{
|
|
48
|
+
required,
|
|
49
|
+
tooltip,
|
|
50
|
+
description,
|
|
51
|
+
boxSx: isHorizontal ? { width: "fit-content", whiteSpace: "nowrap", minWidth: "fit-content" } : void 0,
|
|
52
|
+
children: label
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
};
|
|
30
56
|
return /* @__PURE__ */ jsx(
|
|
31
57
|
Controller,
|
|
32
58
|
{
|
|
33
59
|
name,
|
|
34
60
|
control,
|
|
35
61
|
rules,
|
|
36
|
-
render: ({ field }) => /* @__PURE__ */
|
|
37
|
-
|
|
62
|
+
render: ({ field }) => /* @__PURE__ */ jsx(Box, { sx: { width: "100%", ...wrapperStyle }, children: isHorizontal ? /* @__PURE__ */ jsxs(
|
|
63
|
+
Stack,
|
|
64
|
+
{
|
|
65
|
+
direction: "row",
|
|
66
|
+
spacing: 2,
|
|
67
|
+
sx: {
|
|
68
|
+
alignItems: "center",
|
|
69
|
+
justifyContent: "space-between"
|
|
70
|
+
},
|
|
71
|
+
children: [
|
|
72
|
+
renderLabel(),
|
|
73
|
+
/* @__PURE__ */ jsx(
|
|
74
|
+
TextField,
|
|
75
|
+
{
|
|
76
|
+
fullWidth: false,
|
|
77
|
+
error: !!error,
|
|
78
|
+
helperText: errorPosition === "bottom" && error ? error : "",
|
|
79
|
+
placeholder,
|
|
80
|
+
size: "small",
|
|
81
|
+
...field,
|
|
82
|
+
...rest,
|
|
83
|
+
inputRef,
|
|
84
|
+
slotProps: mergedSlotProps,
|
|
85
|
+
sx: {
|
|
86
|
+
flex: 1,
|
|
87
|
+
...rest.sx
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
)
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
94
|
+
renderLabel(),
|
|
38
95
|
/* @__PURE__ */ jsx(
|
|
39
96
|
TextField,
|
|
40
97
|
{
|
|
41
98
|
fullWidth: true,
|
|
42
|
-
error: !!
|
|
99
|
+
error: !!error,
|
|
43
100
|
helperText: errorPosition === "bottom" && error ? error : "",
|
|
44
101
|
placeholder,
|
|
45
102
|
size: "small",
|
|
46
103
|
...field,
|
|
47
104
|
...rest,
|
|
48
105
|
inputRef,
|
|
49
|
-
slotProps:
|
|
50
|
-
htmlInput: inputProps,
|
|
51
|
-
input: Object.assign(
|
|
52
|
-
rest.InputProps || {},
|
|
53
|
-
errorPosition === "right" && error ? { endAdornment: /* @__PURE__ */ jsx(FormInputError, { error }) } : {}
|
|
54
|
-
)
|
|
55
|
-
}
|
|
106
|
+
slotProps: mergedSlotProps
|
|
56
107
|
}
|
|
57
108
|
)
|
|
58
|
-
] })
|
|
109
|
+
] }) })
|
|
59
110
|
}
|
|
60
111
|
);
|
|
61
112
|
}
|
package/es/components/label.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { FormLabelProps } from '@mui/material';
|
|
2
2
|
import type { ReactNode } from 'react';
|
|
3
|
-
export default function CustomFormLabel({ children, required, tooltip, description, ...props }: FormLabelProps & {
|
|
3
|
+
export default function CustomFormLabel({ children, required, tooltip, description, boxSx, ...props }: FormLabelProps & {
|
|
4
4
|
required?: boolean;
|
|
5
5
|
tooltip?: ReactNode | string;
|
|
6
6
|
description?: ReactNode | string;
|
|
7
|
+
boxSx?: React.CSSProperties;
|
|
7
8
|
}): import("react").JSX.Element;
|
package/es/components/label.js
CHANGED
|
@@ -6,9 +6,10 @@ export default function CustomFormLabel({
|
|
|
6
6
|
required = false,
|
|
7
7
|
tooltip = "",
|
|
8
8
|
description = "",
|
|
9
|
+
boxSx = {},
|
|
9
10
|
...props
|
|
10
11
|
}) {
|
|
11
|
-
return /* @__PURE__ */ jsxs(Box, { sx: { mb: 1, width: "100%" }, children: [
|
|
12
|
+
return /* @__PURE__ */ jsxs(Box, { sx: { mb: 1, width: "100%", ...boxSx }, children: [
|
|
12
13
|
/* @__PURE__ */ jsxs(
|
|
13
14
|
FormLabel,
|
|
14
15
|
{
|
package/es/index.d.ts
CHANGED
|
@@ -36,6 +36,9 @@ import PaymentBeneficiaries from './components/payment-beneficiaries';
|
|
|
36
36
|
import LoadingButton from './components/loading-button';
|
|
37
37
|
import ResumeSubscription from './components/resume-subscription';
|
|
38
38
|
import DateRangePicker from './components/date-range-picker';
|
|
39
|
+
import AutoTopupModal from './components/auto-topup/modal';
|
|
40
|
+
import AutoTopup from './components/auto-topup';
|
|
41
|
+
import Collapse from './components/collapse';
|
|
39
42
|
export { PaymentThemeProvider } from './theme';
|
|
40
43
|
export * from './libs/util';
|
|
41
44
|
export * from './libs/connect';
|
|
@@ -50,4 +53,4 @@ export * from './hooks/scroll';
|
|
|
50
53
|
export * from './hooks/keyboard';
|
|
51
54
|
export * from './libs/validator';
|
|
52
55
|
export { translations, createTranslator } from './locales';
|
|
53
|
-
export { createLazyComponent, api, dayjs, FormInput, FormLabel, 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, PaymentBeneficiaries, LoadingButton, DonateDetails, ResumeSubscription, CreditGrantsList, CreditTransactionsList, DateRangePicker, CreditStatusChip, };
|
|
56
|
+
export { createLazyComponent, api, dayjs, FormInput, FormLabel, 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, PaymentBeneficiaries, LoadingButton, DonateDetails, ResumeSubscription, CreditGrantsList, CreditTransactionsList, DateRangePicker, CreditStatusChip, AutoTopupModal, AutoTopup, Collapse, };
|
package/es/index.js
CHANGED
|
@@ -36,6 +36,9 @@ import PaymentBeneficiaries from "./components/payment-beneficiaries.js";
|
|
|
36
36
|
import LoadingButton from "./components/loading-button.js";
|
|
37
37
|
import ResumeSubscription from "./components/resume-subscription.js";
|
|
38
38
|
import DateRangePicker from "./components/date-range-picker.js";
|
|
39
|
+
import AutoTopupModal from "./components/auto-topup/modal.js";
|
|
40
|
+
import AutoTopup from "./components/auto-topup/index.js";
|
|
41
|
+
import Collapse from "./components/collapse.js";
|
|
39
42
|
export { PaymentThemeProvider } from "./theme/index.js";
|
|
40
43
|
export * from "./libs/util.js";
|
|
41
44
|
export * from "./libs/connect.js";
|
|
@@ -90,5 +93,8 @@ export {
|
|
|
90
93
|
CreditGrantsList,
|
|
91
94
|
CreditTransactionsList,
|
|
92
95
|
DateRangePicker,
|
|
93
|
-
CreditStatusChip
|
|
96
|
+
CreditStatusChip,
|
|
97
|
+
AutoTopupModal,
|
|
98
|
+
AutoTopup,
|
|
99
|
+
Collapse
|
|
94
100
|
};
|
package/es/libs/util.js
CHANGED
|
@@ -917,7 +917,8 @@ export function getInvoiceDescriptionAndReason(invoice, locale = "en") {
|
|
|
917
917
|
return_stake: t("payment.invoice.reason.returnStake", locale),
|
|
918
918
|
recharge: t("payment.invoice.reason.recharge", locale),
|
|
919
919
|
stake_overdraft_protection: t("payment.invoice.reason.stake", locale),
|
|
920
|
-
overdraft_protection: t("payment.invoice.reason.fee", locale)
|
|
920
|
+
overdraft_protection: t("payment.invoice.reason.fee", locale),
|
|
921
|
+
auto_recharge: t("payment.invoice.reason.recharge", locale)
|
|
921
922
|
};
|
|
922
923
|
let invoiceType = t("payment.invoice.reason.payment", locale);
|
|
923
924
|
if (reason.includes("stake") || reason.includes("recharge") || reason === "overdraft_protection") {
|
package/es/locales/en.js
CHANGED
|
@@ -29,6 +29,8 @@ export default flat({
|
|
|
29
29
|
removed: "Resource removed",
|
|
30
30
|
confirm: "Confirm",
|
|
31
31
|
clear: "Clear",
|
|
32
|
+
show: "Show",
|
|
33
|
+
hide: "Hide",
|
|
32
34
|
selectTimeRange: "Select time range",
|
|
33
35
|
startDate: "Start date",
|
|
34
36
|
endDate: "End date",
|
|
@@ -253,6 +255,60 @@ export default flat({
|
|
|
253
255
|
}
|
|
254
256
|
}
|
|
255
257
|
},
|
|
258
|
+
autoTopup: {
|
|
259
|
+
title: "Auto Top-Up",
|
|
260
|
+
enableLabel: "Auto Top-Up",
|
|
261
|
+
purchaseConfig: "Credit Purchase Configuration",
|
|
262
|
+
triggerThreshold: "When credits are below",
|
|
263
|
+
thresholdPlaceholder: "Enter threshold amount",
|
|
264
|
+
thresholdDescription: "Credits remaining to trigger auto top-up",
|
|
265
|
+
thresholdMinError: "Threshold must be greater than 0",
|
|
266
|
+
thresholdFormatError: "Please enter a valid number",
|
|
267
|
+
creditsIncluded: "{num} {name} included",
|
|
268
|
+
purchaseBelow: "Purchase this package",
|
|
269
|
+
perPackage: "per package",
|
|
270
|
+
quantity: "Quantity",
|
|
271
|
+
selectPaymentMethod: "Select payment method",
|
|
272
|
+
paymentInformation: "Payment Information",
|
|
273
|
+
saveConfiguration: "Save Configuration",
|
|
274
|
+
saveSuccess: "Auto top-up configuration saved successfully",
|
|
275
|
+
disableSuccess: "Auto top-up disabled successfully",
|
|
276
|
+
authorizationRequired: "Payment authorization is required to complete the setup",
|
|
277
|
+
cryptoAuthorizationNote: "You will need to authorize payments from your wallet to enable automatic top-ups",
|
|
278
|
+
tip: "With auto top-up enabled, the system automatically buys the specified credit package when your balance drops below the threshold.",
|
|
279
|
+
authTitle: "Auto Top-Up Authorization",
|
|
280
|
+
authTip: "Please complete the authorization process to enable automatic top-up",
|
|
281
|
+
rechargeAmount: "Top-up Amount per Time",
|
|
282
|
+
currentPaymentMethod: "Current Payment Method",
|
|
283
|
+
changePaymentMethod: "Change Payment Method",
|
|
284
|
+
keepCurrent: "Keep Current",
|
|
285
|
+
changePaymentMethodTip: "You will be redirected to set up a new payment method when saving.",
|
|
286
|
+
noPaymentMethodSetup: "No payment method configured. Please set up a payment method first.",
|
|
287
|
+
addFunds: "Add Funds",
|
|
288
|
+
advanced: "Advanced Options",
|
|
289
|
+
enabled: "Enabled",
|
|
290
|
+
disabled: "Disabled",
|
|
291
|
+
notConfigured: "Auto Top-Up not configured",
|
|
292
|
+
setup: "Enable Auto Top-Up",
|
|
293
|
+
ruleDisplay: "When balance < {threshold}, top-up {amount} to get {credits} credits",
|
|
294
|
+
activeDescription: "Auto top-up is enabled. When Credits drop below {threshold}, the system will automatically purchase {credits} Credits for {amount}",
|
|
295
|
+
activeDescriptionWithCredits: "Auto top-up is enabled. When Credits drop below {threshold}, the system will automatically purchase {credits}.",
|
|
296
|
+
purchaseAmount: "Purchase Amount",
|
|
297
|
+
paymentMethod: "Payment Method",
|
|
298
|
+
walletBalance: "Wallet Balance",
|
|
299
|
+
paymentAddress: "Payment Address",
|
|
300
|
+
inactiveDescription: "Enable auto top-up to automatically renew when {name} are insufficient, effectively avoiding service interruptions.",
|
|
301
|
+
showDetails: "Show Method",
|
|
302
|
+
hideDetails: "Hide Method",
|
|
303
|
+
dailyLimits: {
|
|
304
|
+
maxAmount: "Daily Top-up Amount Limit",
|
|
305
|
+
maxAmountPlaceholder: "0 means unlimited",
|
|
306
|
+
maxAmountDescription: "The maximum amount of top-up you can make each day, 0 means unlimited",
|
|
307
|
+
maxAttempts: "Daily Top-up Attempts Limit",
|
|
308
|
+
maxAttemptsPlaceholder: "0 means unlimited",
|
|
309
|
+
maxAttemptsDescription: "The maximum number of top-up attempts you can make each day, 0 means unlimited"
|
|
310
|
+
}
|
|
311
|
+
},
|
|
256
312
|
customer: {
|
|
257
313
|
payments: "Payment History",
|
|
258
314
|
invoices: "Invoice History",
|
package/es/locales/zh.js
CHANGED
|
@@ -32,6 +32,8 @@ export default flat({
|
|
|
32
32
|
confirm: "\u786E\u8BA4",
|
|
33
33
|
cancel: "\u53D6\u6D88",
|
|
34
34
|
clear: "\u6E05\u7A7A",
|
|
35
|
+
show: "\u663E\u793A",
|
|
36
|
+
hide: "\u9690\u85CF",
|
|
35
37
|
selectTimeRange: "\u9009\u62E9\u65F6\u95F4\u8303\u56F4",
|
|
36
38
|
startDate: "\u5F00\u59CB\u65E5\u671F",
|
|
37
39
|
endDate: "\u7ED3\u675F\u65E5\u671F",
|
|
@@ -253,6 +255,60 @@ export default flat({
|
|
|
253
255
|
}
|
|
254
256
|
}
|
|
255
257
|
},
|
|
258
|
+
autoTopup: {
|
|
259
|
+
title: "\u81EA\u52A8\u5145\u503C",
|
|
260
|
+
enableLabel: "\u81EA\u52A8\u5145\u503C",
|
|
261
|
+
purchaseConfig: "\u8D2D\u4E70\u914D\u7F6E",
|
|
262
|
+
triggerThreshold: "\u5F53\u989D\u5EA6\u4F4E\u4E8E",
|
|
263
|
+
thresholdPlaceholder: "\u8F93\u5165\u89E6\u53D1\u9608\u503C",
|
|
264
|
+
thresholdDescription: "\u89E6\u53D1\u81EA\u52A8\u5145\u503C\u7684\u5269\u4F59\u989D\u5EA6",
|
|
265
|
+
thresholdMinError: "\u9608\u503C\u5FC5\u987B\u5927\u4E8E0",
|
|
266
|
+
thresholdFormatError: "\u8BF7\u8F93\u5165\u6709\u6548\u6570\u5B57",
|
|
267
|
+
creditsIncluded: "\u5305\u542B {num} {name}",
|
|
268
|
+
purchaseBelow: "\u8D2D\u4E70\u6B64\u5957\u9910",
|
|
269
|
+
perPackage: "\u6BCF\u5305",
|
|
270
|
+
quantity: "\u6570\u91CF",
|
|
271
|
+
selectPaymentMethod: "\u9009\u62E9\u652F\u4ED8\u65B9\u5F0F",
|
|
272
|
+
paymentInformation: "\u652F\u4ED8\u4FE1\u606F",
|
|
273
|
+
saveConfiguration: "\u4FDD\u5B58\u914D\u7F6E",
|
|
274
|
+
saveSuccess: "\u81EA\u52A8\u5145\u503C\u914D\u7F6E\u4FDD\u5B58\u6210\u529F",
|
|
275
|
+
disableSuccess: "\u5DF2\u5173\u95ED\u81EA\u52A8\u5145\u503C",
|
|
276
|
+
stripeSetupRequired: "\u9700\u8981\u4FE1\u7528\u5361\u6388\u6743\u4EE5\u8FDB\u884C\u81EA\u52A8\u652F\u4ED8",
|
|
277
|
+
cryptoAuthorizationNote: "\u60A8\u9700\u8981\u4ECE\u94B1\u5305\u6388\u6743\u652F\u4ED8\u4EE5\u542F\u7528\u81EA\u52A8\u5145\u503C",
|
|
278
|
+
tip: "\u542F\u7528\u81EA\u52A8\u5145\u503C\u540E\uFF0C\u5F53\u60A8\u7684\u989D\u5EA6\u4F4E\u4E8E\u9608\u503C\u65F6\uFF0C\u7CFB\u7EDF\u5C06\u81EA\u52A8\u8D2D\u4E70\u6307\u5B9A\u6570\u91CF\u7684\u989D\u5EA6\u5957\u9910\u3002",
|
|
279
|
+
authTitle: "\u81EA\u52A8\u5145\u503C\u6388\u6743",
|
|
280
|
+
authTip: "\u8BF7\u5B8C\u6210\u6388\u6743\u6D41\u7A0B\u4EE5\u542F\u7528\u81EA\u52A8\u5145\u503C",
|
|
281
|
+
rechargeAmount: "\u6BCF\u6B21\u5145\u503C\u91D1\u989D",
|
|
282
|
+
currentPaymentMethod: "\u5F53\u524D\u652F\u4ED8\u65B9\u5F0F",
|
|
283
|
+
changePaymentMethod: "\u66F4\u6362\u652F\u4ED8\u65B9\u5F0F",
|
|
284
|
+
keepCurrent: "\u4FDD\u6301\u5F53\u524D",
|
|
285
|
+
changePaymentMethodTip: "\u4FDD\u5B58\u65F6\u5C06\u5F15\u5BFC\u60A8\u8BBE\u7F6E\u65B0\u7684\u652F\u4ED8\u65B9\u5F0F\u3002",
|
|
286
|
+
noPaymentMethodSetup: "\u672A\u914D\u7F6E\u652F\u4ED8\u65B9\u5F0F\uFF0C\u8BF7\u5148\u8BBE\u7F6E\u652F\u4ED8\u65B9\u5F0F\u3002",
|
|
287
|
+
addFunds: "\u5145\u503C",
|
|
288
|
+
advanced: "\u9AD8\u7EA7\u9009\u9879",
|
|
289
|
+
enabled: "\u5DF2\u542F\u7528",
|
|
290
|
+
disabled: "\u5DF2\u7981\u7528",
|
|
291
|
+
notConfigured: "\u5C1A\u672A\u914D\u7F6E\u81EA\u52A8\u5145\u503C",
|
|
292
|
+
setup: "\u53BB\u542F\u7528",
|
|
293
|
+
ruleDisplay: "\u989D\u5EA6\u4F4E\u4E8E{threshold}\u65F6\uFF0C\u5145\u503C{amount}\u53EF\u83B7\u5F97{credits}\u989D\u5EA6",
|
|
294
|
+
activeDescription: "\u81EA\u52A8\u5145\u503C\u5DF2\u542F\u7528\uFF0C\u5F53 Credits \u4F4E\u4E8E {threshold} \u65F6\uFF0C\u7CFB\u7EDF\u4F1A\u81EA\u52A8\u5145\u503C\u8D2D\u4E70 {credits} Credits\uFF0C\u652F\u4ED8\u91D1\u989D\u4E3A {amount}",
|
|
295
|
+
activeDescriptionWithCredits: "\u81EA\u52A8\u5145\u503C\u5DF2\u542F\u7528\uFF0C\u5F53 Credits \u4F4E\u4E8E {threshold} \u65F6\uFF0C\u7CFB\u7EDF\u4F1A\u81EA\u52A8\u8D2D\u4E70 {credits} \u989D\u5EA6\u3002",
|
|
296
|
+
purchaseAmount: "\u8D2D\u4E70\u6240\u9700\u91D1\u989D",
|
|
297
|
+
paymentMethod: "\u652F\u4ED8\u65B9\u5F0F",
|
|
298
|
+
walletBalance: "\u94B1\u5305\u4F59\u989D",
|
|
299
|
+
paymentAddress: "\u652F\u4ED8\u5730\u5740",
|
|
300
|
+
inactiveDescription: "\u5F00\u542F\u81EA\u52A8\u5145\u503C\uFF0C\u5373\u53EF\u5728 {name} \u4E0D\u8DB3\u65F6\u81EA\u52A8\u7EED\u8D39\uFF0C\u6709\u6548\u907F\u514D\u670D\u52A1\u4E2D\u65AD\u3002",
|
|
301
|
+
showDetails: "\u5C55\u5F00\u652F\u4ED8\u4FE1\u606F",
|
|
302
|
+
hideDetails: "\u6536\u8D77",
|
|
303
|
+
dailyLimits: {
|
|
304
|
+
maxAmount: "\u6BCF\u65E5\u5145\u503C\u91D1\u989D\u4E0A\u9650",
|
|
305
|
+
maxAmountPlaceholder: "0\u8868\u793A\u65E0\u9650\u5236",
|
|
306
|
+
maxAmountDescription: "\u6BCF\u65E5\u53EF\u5145\u503C\u7684\u6700\u5927\u603B\u91D1\u989D\uFF0C0 \u8868\u793A\u65E0\u9650\u5236",
|
|
307
|
+
maxAttempts: "\u6BCF\u65E5\u5145\u503C\u6B21\u6570\u4E0A\u9650",
|
|
308
|
+
maxAttemptsPlaceholder: "0\u8868\u793A\u65E0\u9650\u5236",
|
|
309
|
+
maxAttemptsDescription: "\u6BCF\u65E5\u53EF\u5145\u503C\u7684\u6700\u5927\u6B21\u6570\uFF0C0 \u8868\u793A\u65E0\u9650\u5236"
|
|
310
|
+
}
|
|
311
|
+
},
|
|
256
312
|
customer: {
|
|
257
313
|
payments: "\u652F\u4ED8\u5386\u53F2",
|
|
258
314
|
invoices: "\u8D26\u5355\u5386\u53F2",
|
package/es/payment/form/index.js
CHANGED
|
@@ -14,6 +14,7 @@ import { fromUnitToToken } from "@ocap/util";
|
|
|
14
14
|
import DID from "@arcblock/ux/lib/DID";
|
|
15
15
|
import isEmpty from "lodash/isEmpty";
|
|
16
16
|
import { HelpOutline, OpenInNew } from "@mui/icons-material";
|
|
17
|
+
import { ReactGA } from "@arcblock/ux/lib/withTracker";
|
|
17
18
|
import FormInput from "../../components/input.js";
|
|
18
19
|
import FormLabel from "../../components/label.js";
|
|
19
20
|
import { usePaymentContext } from "../../contexts/payment.js";
|
|
@@ -113,6 +114,7 @@ export default function PaymentForm({
|
|
|
113
114
|
trigger
|
|
114
115
|
} = useFormContext();
|
|
115
116
|
const errorRef = useRef(null);
|
|
117
|
+
const processingRef = useRef(false);
|
|
116
118
|
const quantityInventoryStatus = useMemo(() => {
|
|
117
119
|
let status = true;
|
|
118
120
|
for (const item of checkoutSession.line_items) {
|
|
@@ -254,6 +256,10 @@ export default function PaymentForm({
|
|
|
254
256
|
return true;
|
|
255
257
|
}, [session?.user, method, checkoutSession]);
|
|
256
258
|
const handleConnected = async () => {
|
|
259
|
+
if (processingRef.current) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
processingRef.current = true;
|
|
257
263
|
setState({ paying: true });
|
|
258
264
|
try {
|
|
259
265
|
const result = await waitForCheckoutComplete(checkoutSession.id);
|
|
@@ -262,9 +268,19 @@ export default function PaymentForm({
|
|
|
262
268
|
onPaid(result);
|
|
263
269
|
}
|
|
264
270
|
} catch (err) {
|
|
265
|
-
|
|
271
|
+
const errorMessage = formatError(err);
|
|
272
|
+
const payFailedEvent = {
|
|
273
|
+
action: "payFailed",
|
|
274
|
+
// @ts-ignore 后续升级的话就会报错了,移除这个 lint 即可
|
|
275
|
+
mode: checkoutSession.mode,
|
|
276
|
+
errorMessage,
|
|
277
|
+
success: false
|
|
278
|
+
};
|
|
279
|
+
ReactGA.event(payFailedEvent.action, payFailedEvent);
|
|
280
|
+
Toast.error(errorMessage);
|
|
266
281
|
} finally {
|
|
267
282
|
setState({ paying: false });
|
|
283
|
+
processingRef.current = false;
|
|
268
284
|
}
|
|
269
285
|
};
|
|
270
286
|
useEffect(() => {
|