@blocklet/payment-react 1.14.27 → 1.14.28
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/checkout/form.js +3 -3
- package/es/checkout/table.js +11 -3
- package/es/components/pricing-table.js +55 -14
- package/es/libs/util.d.ts +1 -0
- package/es/libs/util.js +6 -0
- package/es/locales/en.js +1 -1
- package/es/locales/zh.js +3 -3
- package/es/payment/form/address.js +1 -1
- package/es/payment/index.d.ts +1 -1
- package/es/payment/index.js +4 -1
- package/es/payment/skeleton/overview.js +3 -6
- package/es/payment/skeleton/payment.js +8 -7
- package/lib/checkout/form.js +3 -3
- package/lib/checkout/table.js +12 -2
- package/lib/components/pricing-table.js +90 -41
- package/lib/libs/util.d.ts +1 -0
- package/lib/libs/util.js +7 -0
- package/lib/locales/en.js +1 -1
- package/lib/locales/zh.js +3 -3
- package/lib/payment/form/address.js +4 -0
- package/lib/payment/index.d.ts +1 -1
- package/lib/payment/index.js +8 -1
- package/lib/payment/skeleton/overview.js +9 -14
- package/lib/payment/skeleton/payment.js +17 -9
- package/package.json +3 -3
- package/src/checkout/form.tsx +3 -3
- package/src/checkout/table.tsx +11 -3
- package/src/components/pricing-table.tsx +103 -48
- package/src/libs/util.ts +7 -0
- package/src/locales/en.tsx +1 -1
- package/src/locales/zh.tsx +3 -3
- package/src/payment/form/address.tsx +1 -1
- package/src/payment/index.tsx +4 -1
- package/src/payment/skeleton/overview.tsx +1 -2
- package/src/payment/skeleton/payment.tsx +10 -11
package/es/checkout/form.js
CHANGED
|
@@ -70,7 +70,7 @@ export default function CheckoutForm({
|
|
|
70
70
|
paymentLink: data?.paymentLink,
|
|
71
71
|
customer: data?.customer,
|
|
72
72
|
completed: state.completed,
|
|
73
|
-
error: apiError
|
|
73
|
+
error: apiError,
|
|
74
74
|
onPaid: handlePaid,
|
|
75
75
|
onError: handleError,
|
|
76
76
|
onChange,
|
|
@@ -91,7 +91,7 @@ export default function CheckoutForm({
|
|
|
91
91
|
paymentLink: data?.paymentLink,
|
|
92
92
|
customer: data?.customer,
|
|
93
93
|
completed: state.completed,
|
|
94
|
-
error: apiError
|
|
94
|
+
error: apiError,
|
|
95
95
|
onPaid: handlePaid,
|
|
96
96
|
onError: handleError,
|
|
97
97
|
onChange,
|
|
@@ -111,7 +111,7 @@ export default function CheckoutForm({
|
|
|
111
111
|
paymentLink: data?.paymentLink,
|
|
112
112
|
customer: data?.customer,
|
|
113
113
|
completed: state.completed,
|
|
114
|
-
error: apiError
|
|
114
|
+
error: apiError,
|
|
115
115
|
onPaid: handlePaid,
|
|
116
116
|
onError: handleError,
|
|
117
117
|
onChange,
|
package/es/checkout/table.js
CHANGED
|
@@ -65,7 +65,7 @@ function CheckoutTableInner({ id, mode, onPaid, onError, onChange, extraParams,
|
|
|
65
65
|
}
|
|
66
66
|
if (!sessionId && !hashSessionId) {
|
|
67
67
|
if (mode === "standalone") {
|
|
68
|
-
return /* @__PURE__ */ jsxs(Stack, { direction: "column", alignItems: "center", children: [
|
|
68
|
+
return /* @__PURE__ */ jsxs(Stack, { direction: "column", alignItems: "center", p: 2.5, children: [
|
|
69
69
|
/* @__PURE__ */ jsxs(
|
|
70
70
|
Box,
|
|
71
71
|
{
|
|
@@ -73,11 +73,19 @@ function CheckoutTableInner({ id, mode, onPaid, onError, onChange, extraParams,
|
|
|
73
73
|
display: "flex",
|
|
74
74
|
flexDirection: "column",
|
|
75
75
|
fontSize: "24px",
|
|
76
|
-
|
|
76
|
+
alignItems: "center",
|
|
77
|
+
margin: {
|
|
78
|
+
xs: "20px 0",
|
|
79
|
+
md: "20px 20px"
|
|
80
|
+
},
|
|
81
|
+
maxWidth: {
|
|
82
|
+
xs: "100%",
|
|
83
|
+
md: 400
|
|
84
|
+
},
|
|
77
85
|
textAlign: "center"
|
|
78
86
|
},
|
|
79
87
|
children: [
|
|
80
|
-
!data.livemode && /* @__PURE__ */ jsx(Livemode, { sx: { display: "flex", marginBottom: "8px" } }),
|
|
88
|
+
!data.livemode && /* @__PURE__ */ jsx(Livemode, { sx: { display: "flex", marginBottom: "8px", width: "fit-content" } }),
|
|
81
89
|
/* @__PURE__ */ jsx(
|
|
82
90
|
Typography,
|
|
83
91
|
{
|
|
@@ -21,6 +21,7 @@ import { styled } from "@mui/system";
|
|
|
21
21
|
import { useSetState } from "ahooks";
|
|
22
22
|
import { useEffect, useMemo, useState } from "react";
|
|
23
23
|
import { BN } from "@ocap/util";
|
|
24
|
+
import { isEmpty } from "lodash";
|
|
24
25
|
import { usePaymentContext } from "../contexts/payment.js";
|
|
25
26
|
import {
|
|
26
27
|
formatError,
|
|
@@ -30,12 +31,19 @@ import {
|
|
|
30
31
|
getPriceUintAmountByCurrency
|
|
31
32
|
} from "../libs/util.js";
|
|
32
33
|
import Amount from "../payment/amount.js";
|
|
34
|
+
import { useMobile } from "../hooks/mobile.js";
|
|
35
|
+
const sortOrder = {
|
|
36
|
+
year: 1,
|
|
37
|
+
month: 2,
|
|
38
|
+
day: 3,
|
|
39
|
+
hour: 4
|
|
40
|
+
};
|
|
33
41
|
const groupItemsByRecurring = (items, currency) => {
|
|
34
42
|
const grouped = {};
|
|
35
43
|
const recurring = {};
|
|
36
44
|
items.forEach((x) => {
|
|
37
45
|
const key = [x.price.recurring?.interval, x.price.recurring?.interval_count].join("-");
|
|
38
|
-
if (x.price.currency_options
|
|
46
|
+
if (x.price.currency_options?.find((c) => c.currency_id === currency.id)) {
|
|
39
47
|
recurring[key] = x.price.recurring;
|
|
40
48
|
}
|
|
41
49
|
if (!grouped[key]) {
|
|
@@ -52,11 +60,28 @@ PricingTable.defaultProps = {
|
|
|
52
60
|
};
|
|
53
61
|
export default function PricingTable({ table, alignItems, interval, mode, onSelect }) {
|
|
54
62
|
const { t, locale } = useLocaleContext();
|
|
63
|
+
const { isMobile } = useMobile();
|
|
55
64
|
const {
|
|
56
65
|
settings: { paymentMethods = [] }
|
|
57
66
|
} = usePaymentContext();
|
|
58
67
|
const [currency, setCurrency] = useState(table.currency || {});
|
|
59
68
|
const { recurring, grouped } = useMemo(() => groupItemsByRecurring(table.items, currency), [table.items, currency]);
|
|
69
|
+
const recurringKeysList = useMemo(() => {
|
|
70
|
+
if (isEmpty(recurring)) {
|
|
71
|
+
return [];
|
|
72
|
+
}
|
|
73
|
+
return Object.keys(recurring).sort((a, b) => {
|
|
74
|
+
const [aType, aValue] = a.split("-");
|
|
75
|
+
const [bType, bValue] = b.split("-");
|
|
76
|
+
if (sortOrder[aType] !== sortOrder[bType]) {
|
|
77
|
+
return sortOrder[aType] - sortOrder[bType];
|
|
78
|
+
}
|
|
79
|
+
if (aValue && bValue) {
|
|
80
|
+
return bValue - aValue;
|
|
81
|
+
}
|
|
82
|
+
return b - a;
|
|
83
|
+
});
|
|
84
|
+
}, [recurring]);
|
|
60
85
|
const [state, setState] = useSetState({ interval });
|
|
61
86
|
const currencyMap = useMemo(() => {
|
|
62
87
|
if (!paymentMethods || paymentMethods.length === 0) {
|
|
@@ -114,12 +139,12 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
|
|
|
114
139
|
gap: 20px;
|
|
115
140
|
}
|
|
116
141
|
@media (max-width: ${({ theme }) => theme.breakpoints.values.sm}px) {
|
|
117
|
-
.price-table-item {
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
.btn-row {
|
|
121
|
-
|
|
122
|
-
}
|
|
142
|
+
// .price-table-item {
|
|
143
|
+
// width: 90% !important;
|
|
144
|
+
// }
|
|
145
|
+
// .btn-row {
|
|
146
|
+
// padding: 0 20px;
|
|
147
|
+
// }
|
|
123
148
|
}
|
|
124
149
|
@media (min-width: ${({ theme }) => theme.breakpoints.values.md}px) {
|
|
125
150
|
.price-table-wrap:has(> div:nth-child(1)) {
|
|
@@ -145,8 +170,17 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
|
|
|
145
170
|
}
|
|
146
171
|
},
|
|
147
172
|
children: [
|
|
148
|
-
/* @__PURE__ */ jsxs(
|
|
149
|
-
|
|
173
|
+
/* @__PURE__ */ jsxs(Stack, { className: "btn-row", flexDirection: "row", children: [
|
|
174
|
+
recurringKeysList.length > 0 && /* @__PURE__ */ jsx(Box, { children: isMobile && recurringKeysList.length > 1 ? /* @__PURE__ */ jsx(
|
|
175
|
+
Select,
|
|
176
|
+
{
|
|
177
|
+
value: state.interval,
|
|
178
|
+
onChange: (e) => setState({ interval: e.target.value }),
|
|
179
|
+
size: "small",
|
|
180
|
+
sx: { m: 1 },
|
|
181
|
+
children: recurringKeysList.map((x) => /* @__PURE__ */ jsx(MenuItem, { value: x, children: /* @__PURE__ */ jsx(Typography, { color: x === state.interval ? "text.primary" : "text.secondary", children: formatRecurring(recurring[x], true, "", locale) }) }, x))
|
|
182
|
+
}
|
|
183
|
+
) : /* @__PURE__ */ jsx(
|
|
150
184
|
ToggleButtonGroup,
|
|
151
185
|
{
|
|
152
186
|
size: "small",
|
|
@@ -165,7 +199,7 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
|
|
|
165
199
|
}
|
|
166
200
|
},
|
|
167
201
|
exclusive: true,
|
|
168
|
-
children:
|
|
202
|
+
children: recurringKeysList.map((x) => /* @__PURE__ */ jsx(
|
|
169
203
|
ToggleButton,
|
|
170
204
|
{
|
|
171
205
|
size: "small",
|
|
@@ -186,7 +220,7 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
|
|
|
186
220
|
x
|
|
187
221
|
))
|
|
188
222
|
}
|
|
189
|
-
),
|
|
223
|
+
) }),
|
|
190
224
|
currencyList.length > 0 && /* @__PURE__ */ jsx(
|
|
191
225
|
Select,
|
|
192
226
|
{
|
|
@@ -232,7 +266,10 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
|
|
|
232
266
|
borderColor: mode === "select" && x.is_selected ? "primary.main" : "#ddd",
|
|
233
267
|
boxShadow: "0 8px 16px rgba(0, 0, 0, 20%)"
|
|
234
268
|
},
|
|
235
|
-
width:
|
|
269
|
+
width: {
|
|
270
|
+
xs: "100%",
|
|
271
|
+
md: "320px"
|
|
272
|
+
},
|
|
236
273
|
maxWidth: "360px",
|
|
237
274
|
padding: "20px",
|
|
238
275
|
position: "relative"
|
|
@@ -366,8 +403,12 @@ function Subscribe({ x, action, onSelect, currencyId }) {
|
|
|
366
403
|
fullWidth: true,
|
|
367
404
|
size: "medium",
|
|
368
405
|
variant: "contained",
|
|
369
|
-
color: x.is_highlight || x.is_selected ? "
|
|
370
|
-
sx: {
|
|
406
|
+
color: x.is_highlight || x.is_selected ? "info" : "primary",
|
|
407
|
+
sx: {
|
|
408
|
+
fontSize: "16px",
|
|
409
|
+
padding: "10px 20px",
|
|
410
|
+
lineHeight: "28px"
|
|
411
|
+
},
|
|
371
412
|
loading: state.loading === x.price_id && !state.loaded,
|
|
372
413
|
disabled: x.is_disabled,
|
|
373
414
|
onClick: () => handleSelect(x.price_id),
|
package/es/libs/util.d.ts
CHANGED
|
@@ -104,3 +104,4 @@ export declare function formatTotalPrice({ product, quantity, priceId, locale, }
|
|
|
104
104
|
export declare function formatQuantityInventory(price: TPrice, quantity: string | number, locale?: string): string;
|
|
105
105
|
export declare function formatSubscriptionStatus(status: string): string;
|
|
106
106
|
export declare function formatAmountPrecisionLimit(amount: string, locale?: string, precision?: number): string;
|
|
107
|
+
export declare function getWordBreakStyle(value: any): 'break-word' | 'break-all';
|
package/es/libs/util.js
CHANGED
|
@@ -799,3 +799,9 @@ export function formatAmountPrecisionLimit(amount, locale = "en", precision = 6)
|
|
|
799
799
|
}
|
|
800
800
|
return "";
|
|
801
801
|
}
|
|
802
|
+
export function getWordBreakStyle(value) {
|
|
803
|
+
if (typeof value === "string" && /\s/.test(value)) {
|
|
804
|
+
return "break-word";
|
|
805
|
+
}
|
|
806
|
+
return "break-all";
|
|
807
|
+
}
|
package/es/locales/en.js
CHANGED
|
@@ -193,7 +193,7 @@ export default flat({
|
|
|
193
193
|
invoices: "Invoice History",
|
|
194
194
|
details: "Details",
|
|
195
195
|
summary: "Summary",
|
|
196
|
-
|
|
196
|
+
products: "Products",
|
|
197
197
|
update: "Update Information",
|
|
198
198
|
empty: "Seems you do not have any subscriptions or payments here",
|
|
199
199
|
cancel: {
|
package/es/locales/zh.js
CHANGED
|
@@ -110,9 +110,9 @@ export default flat({
|
|
|
110
110
|
subscription: "\u67E5\u770B\u8BA2\u9605",
|
|
111
111
|
invoice: "\u67E5\u770B\u8D26\u5355"
|
|
112
112
|
},
|
|
113
|
-
paymentRequired: "\u652F\u4ED8\
|
|
113
|
+
paymentRequired: "\u652F\u4ED8\u91D1\u989D",
|
|
114
114
|
staking: {
|
|
115
|
-
title: "\u8D28\u62BC\
|
|
115
|
+
title: "\u8D28\u62BC\u91D1\u989D",
|
|
116
116
|
tooltip: "\u8D28\u62BC\u76F8\u5F53\u4E8E\u4FDD\u8BC1\u91D1\uFF0C\u7528\u4E8E\u786E\u4FDD\u672A\u6765\u7684\u8D26\u5355\u80FD\u591F\u6B63\u5E38\u6263\u6B3E\uFF0C\u5982\u679C\u4F60\u4ECE DID Wallet \u64A4\u9500\u8D28\u62BC\uFF0C\u8BA2\u9605\u4E5F\u4F1A\u88AB\u53D6\u6D88\u3002"
|
|
117
117
|
},
|
|
118
118
|
stakingConfirm: "\u5728\u6B64\u652F\u4ED8\u4E2D\uFF0C\u8D28\u62BC\u91D1\u989D\u4E0E\u4EA7\u54C1\u8D39\u7528\u5206\u5F00",
|
|
@@ -193,7 +193,7 @@ export default flat({
|
|
|
193
193
|
invoices: "\u8D26\u5355\u5386\u53F2",
|
|
194
194
|
details: "\u8D26\u6237\u8BE6\u60C5",
|
|
195
195
|
summary: "\u8BA1\u8D39\u6458\u8981",
|
|
196
|
-
|
|
196
|
+
products: "\u4EA7\u54C1\u4FE1\u606F",
|
|
197
197
|
update: "\u66F4\u65B0\u5BA2\u6237\u4FE1\u606F",
|
|
198
198
|
empty: "\u770B\u8D77\u6765\u60A8\u5728\u8FD9\u91CC\u6CA1\u6709\u4EFB\u4F55\u8BA2\u9605\u6216\u652F\u4ED8",
|
|
199
199
|
cancel: {
|
|
@@ -23,7 +23,7 @@ export default function AddressForm({ mode, stripe, sx = {} }) {
|
|
|
23
23
|
variant: "outlined",
|
|
24
24
|
placeholder: t("payment.checkout.billing.postal_code"),
|
|
25
25
|
InputProps: {
|
|
26
|
-
startAdornment: /* @__PURE__ */ jsx(InputAdornment, { position: "start", children: /* @__PURE__ */ jsx(
|
|
26
|
+
startAdornment: /* @__PURE__ */ jsx(InputAdornment, { position: "start", style: { marginRight: "2px", marginLeft: "-8px" }, children: /* @__PURE__ */ jsx(
|
|
27
27
|
Controller,
|
|
28
28
|
{
|
|
29
29
|
name: "billing_address.country",
|
package/es/payment/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ type Props = CheckoutContext & CheckoutCallbacks & {
|
|
|
6
6
|
error?: any;
|
|
7
7
|
showCheckoutSummary?: boolean;
|
|
8
8
|
};
|
|
9
|
-
declare function Payment({ checkoutSession, paymentMethods, paymentIntent, paymentLink, customer, completed, mode, onPaid, onError, onChange, goBack, action, showCheckoutSummary, }: Props): import("react").JSX.Element;
|
|
9
|
+
declare function Payment({ checkoutSession, paymentMethods, paymentIntent, paymentLink, customer, completed, error, mode, onPaid, onError, onChange, goBack, action, showCheckoutSummary, }: Props): import("react").JSX.Element;
|
|
10
10
|
declare namespace Payment {
|
|
11
11
|
var defaultProps: {
|
|
12
12
|
completed: boolean;
|
package/es/payment/index.js
CHANGED
|
@@ -209,7 +209,7 @@ export default function Payment({
|
|
|
209
209
|
paymentLink,
|
|
210
210
|
customer,
|
|
211
211
|
completed,
|
|
212
|
-
|
|
212
|
+
error,
|
|
213
213
|
mode,
|
|
214
214
|
onPaid,
|
|
215
215
|
onError,
|
|
@@ -238,6 +238,9 @@ export default function Payment({
|
|
|
238
238
|
}
|
|
239
239
|
}, [checkoutSession, livemode, setLivemode, refresh]);
|
|
240
240
|
const renderContent = () => {
|
|
241
|
+
if (error) {
|
|
242
|
+
return /* @__PURE__ */ jsx(PaymentError, { mode, title: "Oops", description: formatError(error) });
|
|
243
|
+
}
|
|
241
244
|
if (!checkoutSession || !delay) {
|
|
242
245
|
return /* @__PURE__ */ jsxs(Stack, { className: "cko-container", sx: { gap: { sm: mode === "standalone" ? 0 : mode === "inline" ? 4 : 8 } }, children: [
|
|
243
246
|
!hideSummaryCard && /* @__PURE__ */ jsx(Stack, { className: "base-card cko-overview", children: /* @__PURE__ */ jsx(Box, { className: "cko-product", children: /* @__PURE__ */ jsx(OverviewSkeleton, {}) }) }),
|
|
@@ -2,12 +2,9 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Fade, Skeleton, Stack, Typography } from "@mui/material";
|
|
3
3
|
export default function OverviewSkeleton() {
|
|
4
4
|
return /* @__PURE__ */ jsx(Fade, { in: true, children: /* @__PURE__ */ jsxs(Stack, { direction: "column", children: [
|
|
5
|
-
/* @__PURE__ */
|
|
6
|
-
|
|
7
|
-
/* @__PURE__ */ jsx(Skeleton, { variant: "text", sx: { fontSize: "2rem", width: "40%" } })
|
|
8
|
-
] }),
|
|
5
|
+
/* @__PURE__ */ jsx(Stack, { direction: "row", alignItems: "center", spacing: 2, children: /* @__PURE__ */ jsx(Skeleton, { variant: "text", sx: { fontSize: "2rem", width: "40%" } }) }),
|
|
6
|
+
/* @__PURE__ */ jsx(Skeleton, { sx: { mt: 2 }, variant: "rounded", height: 100 }),
|
|
9
7
|
/* @__PURE__ */ jsx(Typography, { mt: 2, component: "div", variant: "h4", children: /* @__PURE__ */ jsx(Skeleton, {}) }),
|
|
10
|
-
/* @__PURE__ */ jsx(Typography, { component: "div", variant: "h2", children: /* @__PURE__ */ jsx(Skeleton, {}) })
|
|
11
|
-
/* @__PURE__ */ jsx(Skeleton, { sx: { mt: 2 }, variant: "rounded", width: 200, height: 200 })
|
|
8
|
+
/* @__PURE__ */ jsx(Typography, { component: "div", variant: "h2", children: /* @__PURE__ */ jsx(Skeleton, {}) })
|
|
12
9
|
] }) });
|
|
13
10
|
}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Fade, Skeleton, Stack, Typography } from "@mui/material";
|
|
3
3
|
export default function PaymentSkeleton() {
|
|
4
|
-
return /* @__PURE__ */ jsx(Fade, { in: true, children: /* @__PURE__ */ jsxs(Stack, { direction: "column",
|
|
4
|
+
return /* @__PURE__ */ jsx(Fade, { in: true, children: /* @__PURE__ */ jsxs(Stack, { direction: "column", children: [
|
|
5
5
|
/* @__PURE__ */ jsx(Skeleton, { variant: "text", sx: { fontSize: "2rem", width: "40%" } }),
|
|
6
|
-
/* @__PURE__ */
|
|
7
|
-
|
|
8
|
-
/* @__PURE__ */ jsx(Typography, { component: "div", variant: "
|
|
6
|
+
/* @__PURE__ */ jsx(Skeleton, { sx: { mt: 2 }, variant: "rounded", height: 68 }),
|
|
7
|
+
/* @__PURE__ */ jsxs(Box, { mt: 1, children: [
|
|
8
|
+
/* @__PURE__ */ jsx(Typography, { component: "div", variant: "h4", mb: -1, children: /* @__PURE__ */ jsx(Skeleton, {}) }),
|
|
9
|
+
/* @__PURE__ */ jsx(Typography, { component: "div", children: /* @__PURE__ */ jsx(Skeleton, { height: 60 }) })
|
|
9
10
|
] }),
|
|
10
11
|
/* @__PURE__ */ jsxs(Box, { children: [
|
|
11
|
-
/* @__PURE__ */ jsx(Typography, { component: "div", variant: "h4", children: /* @__PURE__ */ jsx(Skeleton, {}) }),
|
|
12
|
-
/* @__PURE__ */ jsx(Typography, { component: "div",
|
|
12
|
+
/* @__PURE__ */ jsx(Typography, { component: "div", variant: "h4", mb: -1, children: /* @__PURE__ */ jsx(Skeleton, {}) }),
|
|
13
|
+
/* @__PURE__ */ jsx(Typography, { component: "div", children: /* @__PURE__ */ jsx(Skeleton, { height: 60 }) })
|
|
13
14
|
] }),
|
|
14
|
-
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(
|
|
15
|
+
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Skeleton, { height: 60 }) })
|
|
15
16
|
] }) });
|
|
16
17
|
}
|
package/lib/checkout/form.js
CHANGED
|
@@ -81,7 +81,7 @@ function CheckoutForm({
|
|
|
81
81
|
paymentLink: data?.paymentLink,
|
|
82
82
|
customer: data?.customer,
|
|
83
83
|
completed: state.completed,
|
|
84
|
-
error: apiError
|
|
84
|
+
error: apiError,
|
|
85
85
|
onPaid: handlePaid,
|
|
86
86
|
onError: handleError,
|
|
87
87
|
onChange,
|
|
@@ -101,7 +101,7 @@ function CheckoutForm({
|
|
|
101
101
|
paymentLink: data?.paymentLink,
|
|
102
102
|
customer: data?.customer,
|
|
103
103
|
completed: state.completed,
|
|
104
|
-
error: apiError
|
|
104
|
+
error: apiError,
|
|
105
105
|
onPaid: handlePaid,
|
|
106
106
|
onError: handleError,
|
|
107
107
|
onChange,
|
|
@@ -120,7 +120,7 @@ function CheckoutForm({
|
|
|
120
120
|
paymentLink: data?.paymentLink,
|
|
121
121
|
customer: data?.customer,
|
|
122
122
|
completed: state.completed,
|
|
123
|
-
error: apiError
|
|
123
|
+
error: apiError,
|
|
124
124
|
onPaid: handlePaid,
|
|
125
125
|
onError: handleError,
|
|
126
126
|
onChange,
|
package/lib/checkout/table.js
CHANGED
|
@@ -99,18 +99,28 @@ function CheckoutTableInner({
|
|
|
99
99
|
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
100
100
|
direction: "column",
|
|
101
101
|
alignItems: "center",
|
|
102
|
+
p: 2.5,
|
|
102
103
|
children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_system.Box, {
|
|
103
104
|
sx: {
|
|
104
105
|
display: "flex",
|
|
105
106
|
flexDirection: "column",
|
|
106
107
|
fontSize: "24px",
|
|
107
|
-
|
|
108
|
+
alignItems: "center",
|
|
109
|
+
margin: {
|
|
110
|
+
xs: "20px 0",
|
|
111
|
+
md: "20px 20px"
|
|
112
|
+
},
|
|
113
|
+
maxWidth: {
|
|
114
|
+
xs: "100%",
|
|
115
|
+
md: 400
|
|
116
|
+
},
|
|
108
117
|
textAlign: "center"
|
|
109
118
|
},
|
|
110
119
|
children: [!data.livemode && /* @__PURE__ */(0, _jsxRuntime.jsx)(_livemode.default, {
|
|
111
120
|
sx: {
|
|
112
121
|
display: "flex",
|
|
113
|
-
marginBottom: "8px"
|
|
122
|
+
marginBottom: "8px",
|
|
123
|
+
width: "fit-content"
|
|
114
124
|
}
|
|
115
125
|
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
116
126
|
color: "text.primary",
|
|
@@ -14,16 +14,24 @@ var _system = require("@mui/system");
|
|
|
14
14
|
var _ahooks = require("ahooks");
|
|
15
15
|
var _react = require("react");
|
|
16
16
|
var _util = require("@ocap/util");
|
|
17
|
+
var _lodash = require("lodash");
|
|
17
18
|
var _payment = require("../contexts/payment");
|
|
18
19
|
var _util2 = require("../libs/util");
|
|
19
20
|
var _amount = _interopRequireDefault(require("../payment/amount"));
|
|
21
|
+
var _mobile = require("../hooks/mobile");
|
|
20
22
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
23
|
+
const sortOrder = {
|
|
24
|
+
year: 1,
|
|
25
|
+
month: 2,
|
|
26
|
+
day: 3,
|
|
27
|
+
hour: 4
|
|
28
|
+
};
|
|
21
29
|
const groupItemsByRecurring = (items, currency) => {
|
|
22
30
|
const grouped = {};
|
|
23
31
|
const recurring = {};
|
|
24
32
|
items.forEach(x => {
|
|
25
33
|
const key = [x.price.recurring?.interval, x.price.recurring?.interval_count].join("-");
|
|
26
|
-
if (x.price.currency_options
|
|
34
|
+
if (x.price.currency_options?.find(c => c.currency_id === currency.id)) {
|
|
27
35
|
recurring[key] = x.price.recurring;
|
|
28
36
|
}
|
|
29
37
|
if (!grouped[key]) {
|
|
@@ -52,6 +60,9 @@ function PricingTable({
|
|
|
52
60
|
t,
|
|
53
61
|
locale
|
|
54
62
|
} = (0, _context.useLocaleContext)();
|
|
63
|
+
const {
|
|
64
|
+
isMobile
|
|
65
|
+
} = (0, _mobile.useMobile)();
|
|
55
66
|
const {
|
|
56
67
|
settings: {
|
|
57
68
|
paymentMethods = []
|
|
@@ -62,6 +73,22 @@ function PricingTable({
|
|
|
62
73
|
recurring,
|
|
63
74
|
grouped
|
|
64
75
|
} = (0, _react.useMemo)(() => groupItemsByRecurring(table.items, currency), [table.items, currency]);
|
|
76
|
+
const recurringKeysList = (0, _react.useMemo)(() => {
|
|
77
|
+
if ((0, _lodash.isEmpty)(recurring)) {
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
return Object.keys(recurring).sort((a, b) => {
|
|
81
|
+
const [aType, aValue] = a.split("-");
|
|
82
|
+
const [bType, bValue] = b.split("-");
|
|
83
|
+
if (sortOrder[aType] !== sortOrder[bType]) {
|
|
84
|
+
return sortOrder[aType] - sortOrder[bType];
|
|
85
|
+
}
|
|
86
|
+
if (aValue && bValue) {
|
|
87
|
+
return bValue - aValue;
|
|
88
|
+
}
|
|
89
|
+
return b - a;
|
|
90
|
+
});
|
|
91
|
+
}, [recurring]);
|
|
65
92
|
const [state, setState] = (0, _ahooks.useSetState)({
|
|
66
93
|
interval
|
|
67
94
|
});
|
|
@@ -127,12 +154,12 @@ function PricingTable({
|
|
|
127
154
|
@media (max-width: ${({
|
|
128
155
|
theme
|
|
129
156
|
}) => theme.breakpoints.values.sm}px) {
|
|
130
|
-
.price-table-item {
|
|
131
|
-
|
|
132
|
-
}
|
|
133
|
-
.btn-row {
|
|
134
|
-
|
|
135
|
-
}
|
|
157
|
+
// .price-table-item {
|
|
158
|
+
// width: 90% !important;
|
|
159
|
+
// }
|
|
160
|
+
// .btn-row {
|
|
161
|
+
// padding: 0 20px;
|
|
162
|
+
// }
|
|
136
163
|
}
|
|
137
164
|
@media (min-width: ${({
|
|
138
165
|
theme
|
|
@@ -158,43 +185,62 @@ function PricingTable({
|
|
|
158
185
|
sm: mode === "select" ? 3 : 5
|
|
159
186
|
}
|
|
160
187
|
},
|
|
161
|
-
children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(
|
|
188
|
+
children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
162
189
|
className: "btn-row",
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
interval:
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
children: Object.keys(recurring).map(x => /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.ToggleButton, {
|
|
190
|
+
flexDirection: "row",
|
|
191
|
+
children: [recurringKeysList.length > 0 && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
192
|
+
children: isMobile && recurringKeysList.length > 1 ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Select, {
|
|
193
|
+
value: state.interval,
|
|
194
|
+
onChange: e => setState({
|
|
195
|
+
interval: e.target.value
|
|
196
|
+
}),
|
|
197
|
+
size: "small",
|
|
198
|
+
sx: {
|
|
199
|
+
m: 1
|
|
200
|
+
},
|
|
201
|
+
children: recurringKeysList.map(x => /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.MenuItem, {
|
|
202
|
+
value: x,
|
|
203
|
+
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
204
|
+
color: x === state.interval ? "text.primary" : "text.secondary",
|
|
205
|
+
children: (0, _util2.formatRecurring)(recurring[x], true, "", locale)
|
|
206
|
+
})
|
|
207
|
+
}, x))
|
|
208
|
+
}) : /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.ToggleButtonGroup, {
|
|
183
209
|
size: "small",
|
|
184
|
-
value:
|
|
210
|
+
value: state.interval,
|
|
185
211
|
sx: {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
212
|
+
padding: "4px",
|
|
213
|
+
borderRadius: "36px",
|
|
214
|
+
height: "40px",
|
|
215
|
+
boxSizing: "border-box",
|
|
216
|
+
backgroundColor: "#f1f3f5",
|
|
217
|
+
border: 0
|
|
218
|
+
},
|
|
219
|
+
onChange: (_, value) => {
|
|
220
|
+
if (value !== null) {
|
|
221
|
+
setState({
|
|
222
|
+
interval: value
|
|
223
|
+
});
|
|
194
224
|
}
|
|
195
225
|
},
|
|
196
|
-
|
|
197
|
-
|
|
226
|
+
exclusive: true,
|
|
227
|
+
children: recurringKeysList.map(x => /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.ToggleButton, {
|
|
228
|
+
size: "small",
|
|
229
|
+
value: x,
|
|
230
|
+
sx: {
|
|
231
|
+
textTransform: "capitalize",
|
|
232
|
+
padding: "5px 12px",
|
|
233
|
+
fontSize: "13px",
|
|
234
|
+
backgroundColor: x === state.interval ? "#fff !important" : "#f1f3f5 !important",
|
|
235
|
+
border: "0px",
|
|
236
|
+
"&.Mui-selected": {
|
|
237
|
+
borderRadius: "9999px !important",
|
|
238
|
+
border: "1px solid #e5e7eb"
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
children: (0, _util2.formatRecurring)(recurring[x], true, "", locale)
|
|
242
|
+
}, x))
|
|
243
|
+
})
|
|
198
244
|
}), currencyList.length > 0 && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Select, {
|
|
199
245
|
value: currency?.id,
|
|
200
246
|
onChange: e => setCurrency(currencyList.find(v => v?.id === e.target.value)),
|
|
@@ -241,7 +287,10 @@ function PricingTable({
|
|
|
241
287
|
borderColor: mode === "select" && x.is_selected ? "primary.main" : "#ddd",
|
|
242
288
|
boxShadow: "0 8px 16px rgba(0, 0, 0, 20%)"
|
|
243
289
|
},
|
|
244
|
-
width:
|
|
290
|
+
width: {
|
|
291
|
+
xs: "100%",
|
|
292
|
+
md: "320px"
|
|
293
|
+
},
|
|
245
294
|
maxWidth: "360px",
|
|
246
295
|
padding: "20px",
|
|
247
296
|
position: "relative"
|
|
@@ -389,7 +438,7 @@ function Subscribe({
|
|
|
389
438
|
fullWidth: true,
|
|
390
439
|
size: "medium",
|
|
391
440
|
variant: "contained",
|
|
392
|
-
color: x.is_highlight || x.is_selected ? "
|
|
441
|
+
color: x.is_highlight || x.is_selected ? "info" : "primary",
|
|
393
442
|
sx: {
|
|
394
443
|
fontSize: "16px",
|
|
395
444
|
padding: "10px 20px",
|
package/lib/libs/util.d.ts
CHANGED
|
@@ -104,3 +104,4 @@ export declare function formatTotalPrice({ product, quantity, priceId, locale, }
|
|
|
104
104
|
export declare function formatQuantityInventory(price: TPrice, quantity: string | number, locale?: string): string;
|
|
105
105
|
export declare function formatSubscriptionStatus(status: string): string;
|
|
106
106
|
export declare function formatAmountPrecisionLimit(amount: string, locale?: string, precision?: number): string;
|
|
107
|
+
export declare function getWordBreakStyle(value: any): 'break-word' | 'break-all';
|
package/lib/libs/util.js
CHANGED
|
@@ -43,6 +43,7 @@ exports.getSubscriptionAction = void 0;
|
|
|
43
43
|
exports.getSubscriptionStatusColor = getSubscriptionStatusColor;
|
|
44
44
|
exports.getTxLink = exports.getSubscriptionTimeSummary = void 0;
|
|
45
45
|
exports.getWebhookStatusColor = getWebhookStatusColor;
|
|
46
|
+
exports.getWordBreakStyle = getWordBreakStyle;
|
|
46
47
|
exports.isPaymentKitMounted = void 0;
|
|
47
48
|
exports.isValidCountry = isValidCountry;
|
|
48
49
|
exports.lazyLoad = lazyLoad;
|
|
@@ -967,4 +968,10 @@ function formatAmountPrecisionLimit(amount, locale = "en", precision = 6) {
|
|
|
967
968
|
});
|
|
968
969
|
}
|
|
969
970
|
return "";
|
|
971
|
+
}
|
|
972
|
+
function getWordBreakStyle(value) {
|
|
973
|
+
if (typeof value === "string" && /\s/.test(value)) {
|
|
974
|
+
return "break-word";
|
|
975
|
+
}
|
|
976
|
+
return "break-all";
|
|
970
977
|
}
|
package/lib/locales/en.js
CHANGED
|
@@ -200,7 +200,7 @@ module.exports = (0, _flat.default)({
|
|
|
200
200
|
invoices: "Invoice History",
|
|
201
201
|
details: "Details",
|
|
202
202
|
summary: "Summary",
|
|
203
|
-
|
|
203
|
+
products: "Products",
|
|
204
204
|
update: "Update Information",
|
|
205
205
|
empty: "Seems you do not have any subscriptions or payments here",
|
|
206
206
|
cancel: {
|
package/lib/locales/zh.js
CHANGED
|
@@ -117,9 +117,9 @@ module.exports = (0, _flat.default)({
|
|
|
117
117
|
subscription: "\u67E5\u770B\u8BA2\u9605",
|
|
118
118
|
invoice: "\u67E5\u770B\u8D26\u5355"
|
|
119
119
|
},
|
|
120
|
-
paymentRequired: "\u652F\u4ED8\
|
|
120
|
+
paymentRequired: "\u652F\u4ED8\u91D1\u989D",
|
|
121
121
|
staking: {
|
|
122
|
-
title: "\u8D28\u62BC\
|
|
122
|
+
title: "\u8D28\u62BC\u91D1\u989D",
|
|
123
123
|
tooltip: "\u8D28\u62BC\u76F8\u5F53\u4E8E\u4FDD\u8BC1\u91D1\uFF0C\u7528\u4E8E\u786E\u4FDD\u672A\u6765\u7684\u8D26\u5355\u80FD\u591F\u6B63\u5E38\u6263\u6B3E\uFF0C\u5982\u679C\u4F60\u4ECE DID Wallet \u64A4\u9500\u8D28\u62BC\uFF0C\u8BA2\u9605\u4E5F\u4F1A\u88AB\u53D6\u6D88\u3002"
|
|
124
124
|
},
|
|
125
125
|
stakingConfirm: "\u5728\u6B64\u652F\u4ED8\u4E2D\uFF0C\u8D28\u62BC\u91D1\u989D\u4E0E\u4EA7\u54C1\u8D39\u7528\u5206\u5F00",
|
|
@@ -200,7 +200,7 @@ module.exports = (0, _flat.default)({
|
|
|
200
200
|
invoices: "\u8D26\u5355\u5386\u53F2",
|
|
201
201
|
details: "\u8D26\u6237\u8BE6\u60C5",
|
|
202
202
|
summary: "\u8BA1\u8D39\u6458\u8981",
|
|
203
|
-
|
|
203
|
+
products: "\u4EA7\u54C1\u4FE1\u606F",
|
|
204
204
|
update: "\u66F4\u65B0\u5BA2\u6237\u4FE1\u606F",
|
|
205
205
|
empty: "\u770B\u8D77\u6765\u60A8\u5728\u8FD9\u91CC\u6CA1\u6709\u4EFB\u4F55\u8BA2\u9605\u6216\u652F\u4ED8",
|
|
206
206
|
cancel: {
|
|
@@ -52,6 +52,10 @@ function AddressForm({
|
|
|
52
52
|
InputProps: {
|
|
53
53
|
startAdornment: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.InputAdornment, {
|
|
54
54
|
position: "start",
|
|
55
|
+
style: {
|
|
56
|
+
marginRight: "2px",
|
|
57
|
+
marginLeft: "-8px"
|
|
58
|
+
},
|
|
55
59
|
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_reactHookForm.Controller, {
|
|
56
60
|
name: "billing_address.country",
|
|
57
61
|
control,
|
package/lib/payment/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ type Props = CheckoutContext & CheckoutCallbacks & {
|
|
|
6
6
|
error?: any;
|
|
7
7
|
showCheckoutSummary?: boolean;
|
|
8
8
|
};
|
|
9
|
-
declare function Payment({ checkoutSession, paymentMethods, paymentIntent, paymentLink, customer, completed, mode, onPaid, onError, onChange, goBack, action, showCheckoutSummary, }: Props): import("react").JSX.Element;
|
|
9
|
+
declare function Payment({ checkoutSession, paymentMethods, paymentIntent, paymentLink, customer, completed, error, mode, onPaid, onError, onChange, goBack, action, showCheckoutSummary, }: Props): import("react").JSX.Element;
|
|
10
10
|
declare namespace Payment {
|
|
11
11
|
var defaultProps: {
|
|
12
12
|
completed: boolean;
|
package/lib/payment/index.js
CHANGED
|
@@ -262,7 +262,7 @@ function Payment({
|
|
|
262
262
|
paymentLink,
|
|
263
263
|
customer,
|
|
264
264
|
completed,
|
|
265
|
-
|
|
265
|
+
error,
|
|
266
266
|
mode,
|
|
267
267
|
onPaid,
|
|
268
268
|
onError,
|
|
@@ -297,6 +297,13 @@ function Payment({
|
|
|
297
297
|
}
|
|
298
298
|
}, [checkoutSession, livemode, setLivemode, refresh]);
|
|
299
299
|
const renderContent = () => {
|
|
300
|
+
if (error) {
|
|
301
|
+
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_error.default, {
|
|
302
|
+
mode,
|
|
303
|
+
title: "Oops",
|
|
304
|
+
description: (0, _util2.formatError)(error)
|
|
305
|
+
});
|
|
306
|
+
}
|
|
300
307
|
if (!checkoutSession || !delay) {
|
|
301
308
|
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
302
309
|
className: "cko-container",
|
|
@@ -11,21 +11,23 @@ function OverviewSkeleton() {
|
|
|
11
11
|
in: true,
|
|
12
12
|
children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
13
13
|
direction: "column",
|
|
14
|
-
children: [/* @__PURE__ */(0, _jsxRuntime.
|
|
14
|
+
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Stack, {
|
|
15
15
|
direction: "row",
|
|
16
16
|
alignItems: "center",
|
|
17
17
|
spacing: 2,
|
|
18
|
-
children:
|
|
19
|
-
variant: "circular",
|
|
20
|
-
width: 32,
|
|
21
|
-
height: 32
|
|
22
|
-
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
|
|
18
|
+
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
|
|
23
19
|
variant: "text",
|
|
24
20
|
sx: {
|
|
25
21
|
fontSize: "2rem",
|
|
26
22
|
width: "40%"
|
|
27
23
|
}
|
|
28
|
-
})
|
|
24
|
+
})
|
|
25
|
+
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
|
|
26
|
+
sx: {
|
|
27
|
+
mt: 2
|
|
28
|
+
},
|
|
29
|
+
variant: "rounded",
|
|
30
|
+
height: 100
|
|
29
31
|
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
30
32
|
mt: 2,
|
|
31
33
|
component: "div",
|
|
@@ -35,13 +37,6 @@ function OverviewSkeleton() {
|
|
|
35
37
|
component: "div",
|
|
36
38
|
variant: "h2",
|
|
37
39
|
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {})
|
|
38
|
-
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
|
|
39
|
-
sx: {
|
|
40
|
-
mt: 2
|
|
41
|
-
},
|
|
42
|
-
variant: "rounded",
|
|
43
|
-
width: 200,
|
|
44
|
-
height: 200
|
|
45
40
|
})]
|
|
46
41
|
})
|
|
47
42
|
});
|
|
@@ -11,38 +11,46 @@ function PaymentSkeleton() {
|
|
|
11
11
|
in: true,
|
|
12
12
|
children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
13
13
|
direction: "column",
|
|
14
|
-
spacing: 2,
|
|
15
14
|
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
|
|
16
15
|
variant: "text",
|
|
17
16
|
sx: {
|
|
18
17
|
fontSize: "2rem",
|
|
19
18
|
width: "40%"
|
|
20
19
|
}
|
|
20
|
+
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
|
|
21
|
+
sx: {
|
|
22
|
+
mt: 2
|
|
23
|
+
},
|
|
24
|
+
variant: "rounded",
|
|
25
|
+
height: 68
|
|
21
26
|
}), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
|
|
27
|
+
mt: 1,
|
|
22
28
|
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
23
29
|
component: "div",
|
|
24
30
|
variant: "h4",
|
|
31
|
+
mb: -1,
|
|
25
32
|
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {})
|
|
26
33
|
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
27
34
|
component: "div",
|
|
28
|
-
|
|
29
|
-
|
|
35
|
+
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
|
|
36
|
+
height: 60
|
|
37
|
+
})
|
|
30
38
|
})]
|
|
31
39
|
}), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
|
|
32
40
|
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
33
41
|
component: "div",
|
|
34
42
|
variant: "h4",
|
|
43
|
+
mb: -1,
|
|
35
44
|
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {})
|
|
36
45
|
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
37
46
|
component: "div",
|
|
38
|
-
|
|
39
|
-
|
|
47
|
+
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
|
|
48
|
+
height: 60
|
|
49
|
+
})
|
|
40
50
|
})]
|
|
41
51
|
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
42
|
-
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.
|
|
43
|
-
|
|
44
|
-
variant: "h4",
|
|
45
|
-
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {})
|
|
52
|
+
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
|
|
53
|
+
height: 60
|
|
46
54
|
})
|
|
47
55
|
})]
|
|
48
56
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/payment-react",
|
|
3
|
-
"version": "1.14.
|
|
3
|
+
"version": "1.14.28",
|
|
4
4
|
"description": "Reusable react components for payment kit v2",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
"@babel/core": "^7.25.2",
|
|
94
94
|
"@babel/preset-env": "^7.25.2",
|
|
95
95
|
"@babel/preset-react": "^7.24.7",
|
|
96
|
-
"@blocklet/payment-types": "1.14.
|
|
96
|
+
"@blocklet/payment-types": "1.14.28",
|
|
97
97
|
"@storybook/addon-essentials": "^7.6.20",
|
|
98
98
|
"@storybook/addon-interactions": "^7.6.20",
|
|
99
99
|
"@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": "79178aa9251fb54006f6e0fe32a14619d1e8f06e"
|
|
127
127
|
}
|
package/src/checkout/form.tsx
CHANGED
|
@@ -85,7 +85,7 @@ export default function CheckoutForm({
|
|
|
85
85
|
paymentLink={data?.paymentLink}
|
|
86
86
|
customer={data?.customer}
|
|
87
87
|
completed={state.completed}
|
|
88
|
-
error={apiError
|
|
88
|
+
error={apiError}
|
|
89
89
|
onPaid={handlePaid}
|
|
90
90
|
onError={handleError}
|
|
91
91
|
onChange={onChange}
|
|
@@ -106,7 +106,7 @@ export default function CheckoutForm({
|
|
|
106
106
|
paymentLink={data?.paymentLink}
|
|
107
107
|
customer={data?.customer}
|
|
108
108
|
completed={state.completed}
|
|
109
|
-
error={apiError
|
|
109
|
+
error={apiError}
|
|
110
110
|
onPaid={handlePaid}
|
|
111
111
|
onError={handleError}
|
|
112
112
|
onChange={onChange}
|
|
@@ -127,7 +127,7 @@ export default function CheckoutForm({
|
|
|
127
127
|
paymentLink={data?.paymentLink}
|
|
128
128
|
customer={data?.customer}
|
|
129
129
|
completed={state.completed}
|
|
130
|
-
error={apiError
|
|
130
|
+
error={apiError}
|
|
131
131
|
onPaid={handlePaid}
|
|
132
132
|
onError={handleError}
|
|
133
133
|
onChange={onChange}
|
package/src/checkout/table.tsx
CHANGED
|
@@ -83,16 +83,24 @@ function CheckoutTableInner({ id, mode, onPaid, onError, onChange, extraParams,
|
|
|
83
83
|
if (!sessionId && !hashSessionId) {
|
|
84
84
|
if (mode === 'standalone') {
|
|
85
85
|
return (
|
|
86
|
-
<Stack direction="column" alignItems="center">
|
|
86
|
+
<Stack direction="column" alignItems="center" p={2.5}>
|
|
87
87
|
<Box
|
|
88
88
|
sx={{
|
|
89
89
|
display: 'flex',
|
|
90
90
|
flexDirection: 'column',
|
|
91
91
|
fontSize: '24px',
|
|
92
|
-
|
|
92
|
+
alignItems: 'center',
|
|
93
|
+
margin: {
|
|
94
|
+
xs: '20px 0',
|
|
95
|
+
md: '20px 20px',
|
|
96
|
+
},
|
|
97
|
+
maxWidth: {
|
|
98
|
+
xs: '100%',
|
|
99
|
+
md: 400,
|
|
100
|
+
},
|
|
93
101
|
textAlign: 'center',
|
|
94
102
|
}}>
|
|
95
|
-
{!data.livemode && <Livemode sx={{ display: 'flex', marginBottom: '8px' }} />}
|
|
103
|
+
{!data.livemode && <Livemode sx={{ display: 'flex', marginBottom: '8px', width: 'fit-content' }} />}
|
|
96
104
|
<Typography
|
|
97
105
|
color="text.primary"
|
|
98
106
|
fontWeight={600}
|
|
@@ -23,6 +23,7 @@ import { useSetState } from 'ahooks';
|
|
|
23
23
|
import { useEffect, useMemo, useState } from 'react';
|
|
24
24
|
|
|
25
25
|
import { BN } from '@ocap/util';
|
|
26
|
+
import { isEmpty } from 'lodash';
|
|
26
27
|
import { usePaymentContext } from '../contexts/payment';
|
|
27
28
|
import {
|
|
28
29
|
formatError,
|
|
@@ -32,6 +33,16 @@ import {
|
|
|
32
33
|
getPriceUintAmountByCurrency,
|
|
33
34
|
} from '../libs/util';
|
|
34
35
|
import Amount from '../payment/amount';
|
|
36
|
+
import { useMobile } from '../hooks/mobile';
|
|
37
|
+
|
|
38
|
+
type SortOrder = { [key: string]: number };
|
|
39
|
+
|
|
40
|
+
const sortOrder: SortOrder = {
|
|
41
|
+
year: 1,
|
|
42
|
+
month: 2,
|
|
43
|
+
day: 3,
|
|
44
|
+
hour: 4,
|
|
45
|
+
};
|
|
35
46
|
|
|
36
47
|
const groupItemsByRecurring = (items: TPricingTableItem[], currency: { id: string; symbol: string }) => {
|
|
37
48
|
const grouped: { [key: string]: TPricingTableItem[] } = {};
|
|
@@ -39,7 +50,7 @@ const groupItemsByRecurring = (items: TPricingTableItem[], currency: { id: strin
|
|
|
39
50
|
|
|
40
51
|
items.forEach((x) => {
|
|
41
52
|
const key = [x.price.recurring?.interval, x.price.recurring?.interval_count].join('-');
|
|
42
|
-
if (x.price.currency_options
|
|
53
|
+
if (x.price.currency_options?.find((c: PriceCurrency) => c.currency_id === currency.id)) {
|
|
43
54
|
recurring[key] = x.price.recurring as PriceRecurring;
|
|
44
55
|
}
|
|
45
56
|
if (!grouped[key]) {
|
|
@@ -69,11 +80,30 @@ PricingTable.defaultProps = {
|
|
|
69
80
|
|
|
70
81
|
export default function PricingTable({ table, alignItems, interval, mode, onSelect }: Props) {
|
|
71
82
|
const { t, locale } = useLocaleContext();
|
|
83
|
+
const { isMobile } = useMobile();
|
|
72
84
|
const {
|
|
73
85
|
settings: { paymentMethods = [] },
|
|
74
86
|
} = usePaymentContext();
|
|
75
87
|
const [currency, setCurrency] = useState(table.currency || {});
|
|
76
88
|
const { recurring, grouped } = useMemo(() => groupItemsByRecurring(table.items, currency), [table.items, currency]);
|
|
89
|
+
const recurringKeysList = useMemo(() => {
|
|
90
|
+
if (isEmpty(recurring)) {
|
|
91
|
+
return [];
|
|
92
|
+
}
|
|
93
|
+
return Object.keys(recurring).sort((a, b) => {
|
|
94
|
+
const [aType, aValue] = a.split('-');
|
|
95
|
+
const [bType, bValue] = b.split('-');
|
|
96
|
+
if (sortOrder[aType] !== sortOrder[bType]) {
|
|
97
|
+
return sortOrder[aType] - sortOrder[bType];
|
|
98
|
+
}
|
|
99
|
+
if (aValue && bValue) {
|
|
100
|
+
// @ts-ignore
|
|
101
|
+
return bValue - aValue;
|
|
102
|
+
}
|
|
103
|
+
// @ts-ignore
|
|
104
|
+
return b - a;
|
|
105
|
+
});
|
|
106
|
+
}, [recurring]);
|
|
77
107
|
const [state, setState] = useSetState({ interval });
|
|
78
108
|
const currencyMap = useMemo(() => {
|
|
79
109
|
if (!paymentMethods || paymentMethods.length === 0) {
|
|
@@ -137,12 +167,12 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
|
|
|
137
167
|
gap: 20px;
|
|
138
168
|
}
|
|
139
169
|
@media (max-width: ${({ theme }) => theme.breakpoints.values.sm}px) {
|
|
140
|
-
.price-table-item {
|
|
141
|
-
|
|
142
|
-
}
|
|
143
|
-
.btn-row {
|
|
144
|
-
|
|
145
|
-
}
|
|
170
|
+
// .price-table-item {
|
|
171
|
+
// width: 90% !important;
|
|
172
|
+
// }
|
|
173
|
+
// .btn-row {
|
|
174
|
+
// padding: 0 20px;
|
|
175
|
+
// }
|
|
146
176
|
}
|
|
147
177
|
@media (min-width: ${({ theme }) => theme.breakpoints.values.md}px) {
|
|
148
178
|
.price-table-wrap:has(> div:nth-child(1)) {
|
|
@@ -167,45 +197,63 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
|
|
|
167
197
|
sm: mode === 'select' ? 3 : 5,
|
|
168
198
|
},
|
|
169
199
|
}}>
|
|
170
|
-
<
|
|
171
|
-
{
|
|
172
|
-
<
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
borderRadius: '36px',
|
|
178
|
-
height: '40px',
|
|
179
|
-
boxSizing: 'border-box',
|
|
180
|
-
backgroundColor: '#f1f3f5',
|
|
181
|
-
border: 0,
|
|
182
|
-
}}
|
|
183
|
-
onChange={(_, value) => {
|
|
184
|
-
if (value !== null) {
|
|
185
|
-
setState({ interval: value });
|
|
186
|
-
}
|
|
187
|
-
}}
|
|
188
|
-
exclusive>
|
|
189
|
-
{Object.keys(recurring).map((x) => (
|
|
190
|
-
<ToggleButton
|
|
200
|
+
<Stack className="btn-row" flexDirection="row">
|
|
201
|
+
{recurringKeysList.length > 0 && (
|
|
202
|
+
<Box>
|
|
203
|
+
{isMobile && recurringKeysList.length > 1 ? (
|
|
204
|
+
<Select
|
|
205
|
+
value={state.interval}
|
|
206
|
+
onChange={(e) => setState({ interval: e.target.value })}
|
|
191
207
|
size="small"
|
|
192
|
-
|
|
193
|
-
|
|
208
|
+
sx={{ m: 1 }}>
|
|
209
|
+
{recurringKeysList.map((x) => (
|
|
210
|
+
<MenuItem key={x} value={x}>
|
|
211
|
+
<Typography color={x === state.interval ? 'text.primary' : 'text.secondary'}>
|
|
212
|
+
{formatRecurring(recurring[x] as PriceRecurring, true, '', locale)}
|
|
213
|
+
</Typography>
|
|
214
|
+
</MenuItem>
|
|
215
|
+
))}
|
|
216
|
+
</Select>
|
|
217
|
+
) : (
|
|
218
|
+
<ToggleButtonGroup
|
|
219
|
+
size="small"
|
|
220
|
+
value={state.interval}
|
|
194
221
|
sx={{
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
222
|
+
padding: '4px',
|
|
223
|
+
borderRadius: '36px',
|
|
224
|
+
height: '40px',
|
|
225
|
+
boxSizing: 'border-box',
|
|
226
|
+
backgroundColor: '#f1f3f5',
|
|
227
|
+
border: 0,
|
|
228
|
+
}}
|
|
229
|
+
onChange={(_, value) => {
|
|
230
|
+
if (value !== null) {
|
|
231
|
+
setState({ interval: value });
|
|
232
|
+
}
|
|
233
|
+
}}
|
|
234
|
+
exclusive>
|
|
235
|
+
{recurringKeysList.map((x) => (
|
|
236
|
+
<ToggleButton
|
|
237
|
+
size="small"
|
|
238
|
+
key={x}
|
|
239
|
+
value={x}
|
|
240
|
+
sx={{
|
|
241
|
+
textTransform: 'capitalize',
|
|
242
|
+
padding: '5px 12px',
|
|
243
|
+
fontSize: '13px',
|
|
244
|
+
backgroundColor: x === state.interval ? '#fff !important' : '#f1f3f5 !important',
|
|
245
|
+
border: '0px',
|
|
246
|
+
'&.Mui-selected': {
|
|
247
|
+
borderRadius: '9999px !important',
|
|
248
|
+
border: '1px solid #e5e7eb',
|
|
249
|
+
},
|
|
250
|
+
}}>
|
|
251
|
+
{formatRecurring(recurring[x] as PriceRecurring, true, '', locale)}
|
|
252
|
+
</ToggleButton>
|
|
253
|
+
))}
|
|
254
|
+
</ToggleButtonGroup>
|
|
255
|
+
)}
|
|
256
|
+
</Box>
|
|
209
257
|
)}
|
|
210
258
|
{currencyList.length > 0 && (
|
|
211
259
|
<Select
|
|
@@ -222,7 +270,7 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
|
|
|
222
270
|
))}
|
|
223
271
|
</Select>
|
|
224
272
|
)}
|
|
225
|
-
</
|
|
273
|
+
</Stack>
|
|
226
274
|
<Stack
|
|
227
275
|
flexWrap="wrap"
|
|
228
276
|
direction="row"
|
|
@@ -258,7 +306,10 @@ export default function PricingTable({ table, alignItems, interval, mode, onSele
|
|
|
258
306
|
borderColor: mode === 'select' && x.is_selected ? 'primary.main' : '#ddd',
|
|
259
307
|
boxShadow: '0 8px 16px rgba(0, 0, 0, 20%)',
|
|
260
308
|
},
|
|
261
|
-
width:
|
|
309
|
+
width: {
|
|
310
|
+
xs: '100%',
|
|
311
|
+
md: '320px',
|
|
312
|
+
},
|
|
262
313
|
maxWidth: '360px',
|
|
263
314
|
|
|
264
315
|
padding: '20px',
|
|
@@ -377,8 +428,12 @@ function Subscribe({ x, action, onSelect, currencyId }: any) {
|
|
|
377
428
|
fullWidth
|
|
378
429
|
size="medium"
|
|
379
430
|
variant="contained"
|
|
380
|
-
color={x.is_highlight || x.is_selected ? '
|
|
381
|
-
sx={{
|
|
431
|
+
color={x.is_highlight || x.is_selected ? 'info' : 'primary'}
|
|
432
|
+
sx={{
|
|
433
|
+
fontSize: '16px',
|
|
434
|
+
padding: '10px 20px',
|
|
435
|
+
lineHeight: '28px',
|
|
436
|
+
}}
|
|
382
437
|
loading={state.loading === x.price_id && !state.loaded}
|
|
383
438
|
disabled={x.is_disabled}
|
|
384
439
|
onClick={() => handleSelect(x.price_id)}
|
package/src/libs/util.ts
CHANGED
|
@@ -1035,3 +1035,10 @@ export function formatAmountPrecisionLimit(amount: string, locale = 'en', precis
|
|
|
1035
1035
|
}
|
|
1036
1036
|
return '';
|
|
1037
1037
|
}
|
|
1038
|
+
|
|
1039
|
+
export function getWordBreakStyle(value: any): 'break-word' | 'break-all' {
|
|
1040
|
+
if (typeof value === 'string' && /\s/.test(value)) {
|
|
1041
|
+
return 'break-word';
|
|
1042
|
+
}
|
|
1043
|
+
return 'break-all';
|
|
1044
|
+
}
|
package/src/locales/en.tsx
CHANGED
|
@@ -198,7 +198,7 @@ export default flat({
|
|
|
198
198
|
invoices: 'Invoice History',
|
|
199
199
|
details: 'Details',
|
|
200
200
|
summary: 'Summary',
|
|
201
|
-
|
|
201
|
+
products: 'Products',
|
|
202
202
|
update: 'Update Information',
|
|
203
203
|
empty: 'Seems you do not have any subscriptions or payments here',
|
|
204
204
|
cancel: {
|
package/src/locales/zh.tsx
CHANGED
|
@@ -112,9 +112,9 @@ export default flat({
|
|
|
112
112
|
subscription: '查看订阅',
|
|
113
113
|
invoice: '查看账单',
|
|
114
114
|
},
|
|
115
|
-
paymentRequired: '
|
|
115
|
+
paymentRequired: '支付金额',
|
|
116
116
|
staking: {
|
|
117
|
-
title: '
|
|
117
|
+
title: '质押金额',
|
|
118
118
|
tooltip: '质押相当于保证金,用于确保未来的账单能够正常扣款,如果你从 DID Wallet 撤销质押,订阅也会被取消。',
|
|
119
119
|
},
|
|
120
120
|
stakingConfirm: '在此支付中,质押金额与产品费用分开',
|
|
@@ -195,7 +195,7 @@ export default flat({
|
|
|
195
195
|
invoices: '账单历史',
|
|
196
196
|
details: '账户详情',
|
|
197
197
|
summary: '计费摘要',
|
|
198
|
-
|
|
198
|
+
products: '产品信息',
|
|
199
199
|
update: '更新客户信息',
|
|
200
200
|
empty: '看起来您在这里没有任何订阅或支付',
|
|
201
201
|
cancel: {
|
|
@@ -33,7 +33,7 @@ export default function AddressForm({ mode, stripe, sx = {} }: Props) {
|
|
|
33
33
|
placeholder={t('payment.checkout.billing.postal_code')}
|
|
34
34
|
InputProps={{
|
|
35
35
|
startAdornment: (
|
|
36
|
-
<InputAdornment position="start">
|
|
36
|
+
<InputAdornment position="start" style={{ marginRight: '2px', marginLeft: '-8px' }}>
|
|
37
37
|
<Controller
|
|
38
38
|
name="billing_address.country"
|
|
39
39
|
control={control}
|
package/src/payment/index.tsx
CHANGED
|
@@ -248,7 +248,7 @@ export default function Payment({
|
|
|
248
248
|
paymentLink,
|
|
249
249
|
customer,
|
|
250
250
|
completed,
|
|
251
|
-
|
|
251
|
+
error,
|
|
252
252
|
mode,
|
|
253
253
|
onPaid,
|
|
254
254
|
onError,
|
|
@@ -281,6 +281,9 @@ export default function Payment({
|
|
|
281
281
|
}, [checkoutSession, livemode, setLivemode, refresh]);
|
|
282
282
|
|
|
283
283
|
const renderContent = () => {
|
|
284
|
+
if (error) {
|
|
285
|
+
return <PaymentError mode={mode} title="Oops" description={formatError(error)} />;
|
|
286
|
+
}
|
|
284
287
|
if (!checkoutSession || !delay) {
|
|
285
288
|
return (
|
|
286
289
|
<Stack className="cko-container" sx={{ gap: { sm: mode === 'standalone' ? 0 : mode === 'inline' ? 4 : 8 } }}>
|
|
@@ -5,16 +5,15 @@ export default function OverviewSkeleton() {
|
|
|
5
5
|
<Fade in>
|
|
6
6
|
<Stack direction="column">
|
|
7
7
|
<Stack direction="row" alignItems="center" spacing={2}>
|
|
8
|
-
<Skeleton variant="circular" width={32} height={32} />
|
|
9
8
|
<Skeleton variant="text" sx={{ fontSize: '2rem', width: '40%' }} />
|
|
10
9
|
</Stack>
|
|
10
|
+
<Skeleton sx={{ mt: 2 }} variant="rounded" height={100} />
|
|
11
11
|
<Typography mt={2} component="div" variant="h4">
|
|
12
12
|
<Skeleton />
|
|
13
13
|
</Typography>
|
|
14
14
|
<Typography component="div" variant="h2">
|
|
15
15
|
<Skeleton />
|
|
16
16
|
</Typography>
|
|
17
|
-
<Skeleton sx={{ mt: 2 }} variant="rounded" width={200} height={200} />
|
|
18
17
|
</Stack>
|
|
19
18
|
</Fade>
|
|
20
19
|
);
|
|
@@ -3,28 +3,27 @@ import { Box, Fade, Skeleton, Stack, Typography } from '@mui/material';
|
|
|
3
3
|
export default function PaymentSkeleton() {
|
|
4
4
|
return (
|
|
5
5
|
<Fade in>
|
|
6
|
-
<Stack direction="column"
|
|
6
|
+
<Stack direction="column">
|
|
7
7
|
<Skeleton variant="text" sx={{ fontSize: '2rem', width: '40%' }} />
|
|
8
|
-
<
|
|
9
|
-
|
|
8
|
+
<Skeleton sx={{ mt: 2 }} variant="rounded" height={68} />
|
|
9
|
+
<Box mt={1}>
|
|
10
|
+
<Typography component="div" variant="h4" mb={-1}>
|
|
10
11
|
<Skeleton />
|
|
11
12
|
</Typography>
|
|
12
|
-
<Typography component="div"
|
|
13
|
-
<Skeleton />
|
|
13
|
+
<Typography component="div">
|
|
14
|
+
<Skeleton height={60} />
|
|
14
15
|
</Typography>
|
|
15
16
|
</Box>
|
|
16
17
|
<Box>
|
|
17
|
-
<Typography component="div" variant="h4">
|
|
18
|
+
<Typography component="div" variant="h4" mb={-1}>
|
|
18
19
|
<Skeleton />
|
|
19
20
|
</Typography>
|
|
20
|
-
<Typography component="div"
|
|
21
|
-
<Skeleton />
|
|
21
|
+
<Typography component="div">
|
|
22
|
+
<Skeleton height={60} />
|
|
22
23
|
</Typography>
|
|
23
24
|
</Box>
|
|
24
25
|
<Box>
|
|
25
|
-
<
|
|
26
|
-
<Skeleton />
|
|
27
|
-
</Typography>
|
|
26
|
+
<Skeleton height={60} />
|
|
28
27
|
</Box>
|
|
29
28
|
</Stack>
|
|
30
29
|
</Fade>
|