@blocklet/payment-react 1.20.8 → 1.20.10
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/libs/util.js +2 -0
- package/es/locales/en.js +1 -1
- package/es/locales/zh.js +1 -1
- package/es/payment/index.js +3 -1
- package/es/payment/product-item.d.ts +2 -1
- package/es/payment/product-item.js +63 -1
- package/es/payment/progress-item.d.ts +2 -0
- package/es/payment/progress-item.js +28 -2
- package/es/payment/success.js +12 -4
- package/es/payment/summary.d.ts +2 -1
- package/es/payment/summary.js +2 -0
- package/lib/libs/util.js +2 -0
- package/lib/locales/en.js +1 -1
- package/lib/locales/zh.js +1 -1
- package/lib/payment/index.js +3 -1
- package/lib/payment/product-item.d.ts +2 -1
- package/lib/payment/product-item.js +46 -1
- package/lib/payment/progress-item.d.ts +2 -0
- package/lib/payment/progress-item.js +47 -2
- package/lib/payment/success.js +16 -4
- package/lib/payment/summary.d.ts +2 -1
- package/lib/payment/summary.js +2 -0
- package/package.json +3 -3
- package/src/libs/util.ts +2 -0
- package/src/locales/en.tsx +2 -1
- package/src/locales/zh.tsx +1 -1
- package/src/payment/index.tsx +3 -0
- package/src/payment/product-item.tsx +54 -1
- package/src/payment/progress-item.tsx +37 -3
- package/src/payment/success.tsx +18 -4
- package/src/payment/summary.tsx +3 -0
package/es/libs/util.js
CHANGED
package/es/locales/en.js
CHANGED
|
@@ -184,7 +184,7 @@ export default flat({
|
|
|
184
184
|
progress: "Progress {progress}%",
|
|
185
185
|
delivered: "Installation completed",
|
|
186
186
|
failed: "Processing failed",
|
|
187
|
-
|
|
187
|
+
failedMsg: "An exception occurred during installation. We will automatically process a refund for you. We apologize for the inconvenience caused. Thank you for your understanding!"
|
|
188
188
|
},
|
|
189
189
|
confirm: {
|
|
190
190
|
withStake: "By confirming, you allow {payee} to charge your account for future payments and, if necessary, slash your stake. You can cancel your subscription or withdraw your stake at any time.",
|
package/es/locales/zh.js
CHANGED
|
@@ -184,7 +184,7 @@ export default flat({
|
|
|
184
184
|
progress: "\u8FDB\u5EA6 {progress}%",
|
|
185
185
|
delivered: "\u5B89\u88C5\u6210\u529F",
|
|
186
186
|
failed: "\u5B89\u88C5\u5931\u8D25",
|
|
187
|
-
|
|
187
|
+
failedMsg: "\u5F88\u62B1\u6B49\uFF0C\u5B89\u88C5\u8FC7\u7A0B\u4E2D\u9047\u5230\u4E86\u4E00\u4E9B\u95EE\u9898\u3002\u6211\u4EEC\u6B63\u5728\u5904\u7406\u8FD9\u4E2A\u95EE\u9898\uFF0C\u7A0D\u540E\u4F1A\u81EA\u52A8\u4E3A\u60A8\u9000\u6B3E\u3002\u611F\u8C22\u60A8\u7684\u8010\u5FC3\u7B49\u5F85\uFF01"
|
|
188
188
|
},
|
|
189
189
|
confirm: {
|
|
190
190
|
withStake: "\u786E\u8BA4\u8BA2\u9605\uFF0C\u5373\u8868\u793A\u60A8\u6388\u6743 {payee} \u4ECE\u60A8\u7684\u8D26\u6237\u6263\u53D6\u672A\u6765\u6B3E\u9879\uFF0C\u5E76\u5728\u5FC5\u8981\u65F6\u7F5A\u6CA1\u8D28\u62BC\u3002\u60A8\u53EF\u968F\u65F6\u53D6\u6D88\u8BA2\u9605\u6216\u64A4\u9500\u8D28\u62BC\u3002",
|
package/es/payment/index.js
CHANGED
|
@@ -211,6 +211,7 @@ function PaymentInner({
|
|
|
211
211
|
trialInDays = 0;
|
|
212
212
|
trialEnd = 0;
|
|
213
213
|
}
|
|
214
|
+
const showFeatures = `${paymentLink?.metadata?.show_product_features}` === "true";
|
|
214
215
|
return /* @__PURE__ */ jsx(FormProvider, { ...methods, children: /* @__PURE__ */ jsxs(Stack, { className: "cko-container", sx: { gap: { sm: mode === "standalone" ? 0 : mode === "inline" ? 4 : 8 } }, children: [
|
|
215
216
|
!hideSummaryCard && /* @__PURE__ */ jsx(Fade, { in: true, children: /* @__PURE__ */ jsxs(Stack, { className: "base-card cko-overview", direction: "column", children: [
|
|
216
217
|
/* @__PURE__ */ jsx(
|
|
@@ -236,7 +237,8 @@ function PaymentInner({
|
|
|
236
237
|
crossSellBehavior: state.checkoutSession.cross_sell_behavior,
|
|
237
238
|
donationSettings: paymentLink?.donation_settings,
|
|
238
239
|
action,
|
|
239
|
-
completed
|
|
240
|
+
completed,
|
|
241
|
+
showFeatures
|
|
240
242
|
}
|
|
241
243
|
),
|
|
242
244
|
mode === "standalone" && !isMobile && /* @__PURE__ */ jsx(CheckoutFooter, { className: "cko-footer", sx: { color: "text.lighter" } })
|
|
@@ -17,6 +17,7 @@ type Props = {
|
|
|
17
17
|
};
|
|
18
18
|
onQuantityChange?: (itemId: string, quantity: number) => void;
|
|
19
19
|
completed?: boolean;
|
|
20
|
+
showFeatures?: boolean;
|
|
20
21
|
};
|
|
21
|
-
export default function ProductItem({ item, items, trialInDays, trialEnd, currency, mode, children, onUpsell, onDownsell, completed, adjustableQuantity, onQuantityChange, }: Props): JSX.Element;
|
|
22
|
+
export default function ProductItem({ item, items, trialInDays, trialEnd, currency, mode, children, onUpsell, onDownsell, completed, adjustableQuantity, onQuantityChange, showFeatures, }: Props): JSX.Element;
|
|
22
23
|
export {};
|
|
@@ -30,7 +30,8 @@ export default function ProductItem({
|
|
|
30
30
|
completed = false,
|
|
31
31
|
adjustableQuantity = { enabled: false },
|
|
32
32
|
onQuantityChange = () => {
|
|
33
|
-
}
|
|
33
|
+
},
|
|
34
|
+
showFeatures = false
|
|
34
35
|
}) {
|
|
35
36
|
const { t, locale } = useLocaleContext();
|
|
36
37
|
const { settings, setPayable } = usePaymentContext();
|
|
@@ -114,6 +115,7 @@ export default function ProductItem({
|
|
|
114
115
|
return pricing.primary;
|
|
115
116
|
}, [trialInDays, trialEnd, pricing, item, locale]);
|
|
116
117
|
const quantityInventoryError = formatQuantityInventory(item.price, localQuantityNum, locale);
|
|
118
|
+
const features = item.price.product?.features || [];
|
|
117
119
|
return /* @__PURE__ */ jsxs(
|
|
118
120
|
Stack,
|
|
119
121
|
{
|
|
@@ -181,6 +183,66 @@ export default function ProductItem({
|
|
|
181
183
|
]
|
|
182
184
|
}
|
|
183
185
|
),
|
|
186
|
+
showFeatures && features.length > 0 && /* @__PURE__ */ jsx(
|
|
187
|
+
Box,
|
|
188
|
+
{
|
|
189
|
+
sx: {
|
|
190
|
+
display: "flex",
|
|
191
|
+
alignItems: "center",
|
|
192
|
+
justifyContent: "flex-start",
|
|
193
|
+
flexWrap: "wrap",
|
|
194
|
+
gap: 1.5,
|
|
195
|
+
width: "100%",
|
|
196
|
+
mt: 1.5
|
|
197
|
+
},
|
|
198
|
+
children: features.map((feature) => /* @__PURE__ */ jsxs(
|
|
199
|
+
Box,
|
|
200
|
+
{
|
|
201
|
+
sx: {
|
|
202
|
+
display: "flex",
|
|
203
|
+
alignItems: "center",
|
|
204
|
+
justifyContent: "center",
|
|
205
|
+
gap: 0.5,
|
|
206
|
+
px: 1,
|
|
207
|
+
py: 0.5,
|
|
208
|
+
bgcolor: "action.hover",
|
|
209
|
+
borderRadius: 1,
|
|
210
|
+
border: "1px solid",
|
|
211
|
+
borderColor: "divider"
|
|
212
|
+
},
|
|
213
|
+
children: [
|
|
214
|
+
/* @__PURE__ */ jsx(
|
|
215
|
+
Box,
|
|
216
|
+
{
|
|
217
|
+
sx: {
|
|
218
|
+
bgcolor: "success.main",
|
|
219
|
+
width: 4,
|
|
220
|
+
height: 4,
|
|
221
|
+
borderRadius: "50%"
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
),
|
|
225
|
+
/* @__PURE__ */ jsx(
|
|
226
|
+
Typography,
|
|
227
|
+
{
|
|
228
|
+
component: "span",
|
|
229
|
+
variant: "caption",
|
|
230
|
+
sx: {
|
|
231
|
+
color: "text.primary",
|
|
232
|
+
fontSize: "0.75rem",
|
|
233
|
+
fontWeight: 500,
|
|
234
|
+
textTransform: "capitalize",
|
|
235
|
+
whiteSpace: "nowrap"
|
|
236
|
+
},
|
|
237
|
+
children: feature.name
|
|
238
|
+
}
|
|
239
|
+
)
|
|
240
|
+
]
|
|
241
|
+
},
|
|
242
|
+
feature.name
|
|
243
|
+
))
|
|
244
|
+
}
|
|
245
|
+
),
|
|
184
246
|
quantityInventoryError ? /* @__PURE__ */ jsx(
|
|
185
247
|
Status,
|
|
186
248
|
{
|
|
@@ -50,11 +50,37 @@ export function VendorProgressItem({ vendor }) {
|
|
|
50
50
|
}
|
|
51
51
|
};
|
|
52
52
|
}, [startAnimation]);
|
|
53
|
-
const isCompleted = displayProgress >=
|
|
53
|
+
const isCompleted = displayProgress >= 100;
|
|
54
|
+
const isFailed = vendor.status === "failed";
|
|
55
|
+
const nameText = vendor.name || vendor.title;
|
|
56
|
+
if (isFailed) {
|
|
57
|
+
return /* @__PURE__ */ jsxs(Box, { sx: { mb: 2 }, children: [
|
|
58
|
+
/* @__PURE__ */ jsxs(Box, { sx: { display: "flex", justifyContent: "space-between", alignItems: "center", mb: 1 }, children: [
|
|
59
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", sx: { color: "text.secondary" }, children: nameText ? `${nameText} - ${t("payment.checkout.vendor.failed")}` : t("payment.checkout.vendor.failed") }),
|
|
60
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", sx: { color: "error.main", fontWeight: 500 }, children: t("payment.checkout.vendor.progress", { progress: 0 }) })
|
|
61
|
+
] }),
|
|
62
|
+
/* @__PURE__ */ jsx(
|
|
63
|
+
LinearProgress,
|
|
64
|
+
{
|
|
65
|
+
variant: "determinate",
|
|
66
|
+
value: 100,
|
|
67
|
+
sx: {
|
|
68
|
+
height: 8,
|
|
69
|
+
borderRadius: 4,
|
|
70
|
+
backgroundColor: "grey.200",
|
|
71
|
+
"& .MuiLinearProgress-bar": {
|
|
72
|
+
borderRadius: 4,
|
|
73
|
+
backgroundColor: "error.main"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
)
|
|
78
|
+
] });
|
|
79
|
+
}
|
|
54
80
|
const statusText = isCompleted ? t("payment.checkout.vendor.delivered") : t("payment.checkout.vendor.processing");
|
|
55
81
|
return /* @__PURE__ */ jsxs(Box, { sx: { mb: 2 }, children: [
|
|
56
82
|
/* @__PURE__ */ jsxs(Box, { sx: { display: "flex", justifyContent: "space-between", alignItems: "center", mb: 1 }, children: [
|
|
57
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", sx: { color: "text.secondary" }, children:
|
|
83
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", sx: { color: "text.secondary" }, children: nameText ? `${nameText} - ${statusText}` : statusText }),
|
|
58
84
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", sx: { color: "text.secondary", fontWeight: 500 }, children: t("payment.checkout.vendor.progress", { progress: displayProgress }) })
|
|
59
85
|
] }),
|
|
60
86
|
/* @__PURE__ */ jsx(
|
package/es/payment/success.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
|
|
3
3
|
import { Box, Grow, Link, Paper, Stack, styled, Typography } from "@mui/material";
|
|
4
|
-
import { useEffect, useState } from "react";
|
|
4
|
+
import { useEffect, useRef, useState } from "react";
|
|
5
5
|
import { joinURL } from "ufo";
|
|
6
6
|
import { Button } from "@arcblock/ux";
|
|
7
7
|
import { usePaymentContext } from "../contexts/payment.js";
|
|
@@ -22,17 +22,24 @@ export default function PaymentSuccess({
|
|
|
22
22
|
const { prefix, api } = usePaymentContext();
|
|
23
23
|
const [vendorStatus, setVendorStatus] = useState(null);
|
|
24
24
|
const [isAllCompleted, setIsAllCompleted] = useState(false);
|
|
25
|
+
const [hasFailed, setHasFailed] = useState(false);
|
|
26
|
+
const timerRef = useRef(Date.now());
|
|
25
27
|
let next = null;
|
|
26
28
|
useEffect(() => {
|
|
27
29
|
if (!hasVendor || !sessionId) return void 0;
|
|
28
30
|
const fetchVendorStatus = async (interval2) => {
|
|
29
31
|
try {
|
|
30
32
|
const response = await api.get(joinURL(prefix, `/api/vendors/order/${sessionId}/status`), {});
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
+
const needCheckError = Date.now() - timerRef.current > 6 * 1e3;
|
|
34
|
+
const allCompleted = response.data?.vendors?.every((vendor) => vendor.progress >= 100);
|
|
35
|
+
const hasAnyFailed = response.data?.vendors?.some(
|
|
36
|
+
(vendor) => vendor.status === "failed" || needCheckError && !!vendor.error
|
|
37
|
+
);
|
|
38
|
+
if (hasAnyFailed || allCompleted) {
|
|
33
39
|
clearInterval(interval2);
|
|
34
40
|
}
|
|
35
|
-
|
|
41
|
+
setHasFailed(hasAnyFailed);
|
|
42
|
+
setIsAllCompleted(!hasAnyFailed && allCompleted);
|
|
36
43
|
setVendorStatus(response.data);
|
|
37
44
|
} catch (error) {
|
|
38
45
|
console.error("Failed to fetch vendor status:", error);
|
|
@@ -62,6 +69,7 @@ export default function PaymentSuccess({
|
|
|
62
69
|
},
|
|
63
70
|
children: [
|
|
64
71
|
vendorStatus.vendors?.map((vendor, index) => /* @__PURE__ */ jsx(VendorProgressItem, { vendor }, vendor.title || `vendor-${index}`)),
|
|
72
|
+
hasFailed ? /* @__PURE__ */ jsx(Typography, { variant: "h6", sx: { color: "warning.main", mb: 1 }, children: t("payment.checkout.vendor.failedMsg") }) : null,
|
|
65
73
|
pageInfo?.success_message?.[locale] && isAllCompleted ? /* @__PURE__ */ jsx(Typography, { variant: "h6", sx: { color: "text.primary", mb: 1 }, children: pageInfo?.success_message?.[locale] }) : null
|
|
66
74
|
]
|
|
67
75
|
}
|
package/es/payment/summary.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ type Props = {
|
|
|
17
17
|
donationSettings?: DonationSettings;
|
|
18
18
|
action?: string;
|
|
19
19
|
completed?: boolean;
|
|
20
|
+
showFeatures?: boolean;
|
|
20
21
|
};
|
|
21
|
-
export default function PaymentSummary({ items, currency, trialInDays, billingThreshold, onUpsell, onDownsell, onQuantityChange, onApplyCrossSell, onCancelCrossSell, onChangeAmount, checkoutSessionId, crossSellBehavior, showStaking, donationSettings, action, trialEnd, completed, ...rest }: Props): import("react").JSX.Element;
|
|
22
|
+
export default function PaymentSummary({ items, currency, trialInDays, billingThreshold, onUpsell, onDownsell, onQuantityChange, onApplyCrossSell, onCancelCrossSell, onChangeAmount, checkoutSessionId, crossSellBehavior, showStaking, donationSettings, action, trialEnd, completed, showFeatures, ...rest }: Props): import("react").JSX.Element;
|
|
22
23
|
export {};
|
package/es/payment/summary.js
CHANGED
|
@@ -84,6 +84,7 @@ export default function PaymentSummary({
|
|
|
84
84
|
action = "",
|
|
85
85
|
trialEnd = 0,
|
|
86
86
|
completed = false,
|
|
87
|
+
showFeatures = false,
|
|
87
88
|
...rest
|
|
88
89
|
}) {
|
|
89
90
|
const { t, locale } = useLocaleContext();
|
|
@@ -174,6 +175,7 @@ export default function PaymentSummary({
|
|
|
174
175
|
onDownsell: handleDownsell,
|
|
175
176
|
adjustableQuantity: x.adjustable_quantity,
|
|
176
177
|
completed,
|
|
178
|
+
showFeatures,
|
|
177
179
|
onQuantityChange: handleQuantityChange,
|
|
178
180
|
children: x.cross_sell && /* @__PURE__ */ jsxs(
|
|
179
181
|
Stack,
|
package/lib/libs/util.js
CHANGED
package/lib/locales/en.js
CHANGED
|
@@ -191,7 +191,7 @@ module.exports = (0, _flat.default)({
|
|
|
191
191
|
progress: "Progress {progress}%",
|
|
192
192
|
delivered: "Installation completed",
|
|
193
193
|
failed: "Processing failed",
|
|
194
|
-
|
|
194
|
+
failedMsg: "An exception occurred during installation. We will automatically process a refund for you. We apologize for the inconvenience caused. Thank you for your understanding!"
|
|
195
195
|
},
|
|
196
196
|
confirm: {
|
|
197
197
|
withStake: "By confirming, you allow {payee} to charge your account for future payments and, if necessary, slash your stake. You can cancel your subscription or withdraw your stake at any time.",
|
package/lib/locales/zh.js
CHANGED
|
@@ -191,7 +191,7 @@ module.exports = (0, _flat.default)({
|
|
|
191
191
|
progress: "\u8FDB\u5EA6 {progress}%",
|
|
192
192
|
delivered: "\u5B89\u88C5\u6210\u529F",
|
|
193
193
|
failed: "\u5B89\u88C5\u5931\u8D25",
|
|
194
|
-
|
|
194
|
+
failedMsg: "\u5F88\u62B1\u6B49\uFF0C\u5B89\u88C5\u8FC7\u7A0B\u4E2D\u9047\u5230\u4E86\u4E00\u4E9B\u95EE\u9898\u3002\u6211\u4EEC\u6B63\u5728\u5904\u7406\u8FD9\u4E2A\u95EE\u9898\uFF0C\u7A0D\u540E\u4F1A\u81EA\u52A8\u4E3A\u60A8\u9000\u6B3E\u3002\u611F\u8C22\u60A8\u7684\u8010\u5FC3\u7B49\u5F85\uFF01"
|
|
195
195
|
},
|
|
196
196
|
confirm: {
|
|
197
197
|
withStake: "\u786E\u8BA4\u8BA2\u9605\uFF0C\u5373\u8868\u793A\u60A8\u6388\u6743 {payee} \u4ECE\u60A8\u7684\u8D26\u6237\u6263\u53D6\u672A\u6765\u6B3E\u9879\uFF0C\u5E76\u5728\u5FC5\u8981\u65F6\u7F5A\u6CA1\u8D28\u62BC\u3002\u60A8\u53EF\u968F\u65F6\u53D6\u6D88\u8BA2\u9605\u6216\u64A4\u9500\u8D28\u62BC\u3002",
|
package/lib/payment/index.js
CHANGED
|
@@ -257,6 +257,7 @@ function PaymentInner({
|
|
|
257
257
|
trialInDays = 0;
|
|
258
258
|
trialEnd = 0;
|
|
259
259
|
}
|
|
260
|
+
const showFeatures = `${paymentLink?.metadata?.show_product_features}` === "true";
|
|
260
261
|
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_reactHookForm.FormProvider, {
|
|
261
262
|
...methods,
|
|
262
263
|
children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
@@ -290,7 +291,8 @@ function PaymentInner({
|
|
|
290
291
|
crossSellBehavior: state.checkoutSession.cross_sell_behavior,
|
|
291
292
|
donationSettings: paymentLink?.donation_settings,
|
|
292
293
|
action,
|
|
293
|
-
completed
|
|
294
|
+
completed,
|
|
295
|
+
showFeatures
|
|
294
296
|
}), mode === "standalone" && !isMobile && /* @__PURE__ */(0, _jsxRuntime.jsx)(_footer.default, {
|
|
295
297
|
className: "cko-footer",
|
|
296
298
|
sx: {
|
|
@@ -17,6 +17,7 @@ type Props = {
|
|
|
17
17
|
};
|
|
18
18
|
onQuantityChange?: (itemId: string, quantity: number) => void;
|
|
19
19
|
completed?: boolean;
|
|
20
|
+
showFeatures?: boolean;
|
|
20
21
|
};
|
|
21
|
-
export default function ProductItem({ item, items, trialInDays, trialEnd, currency, mode, children, onUpsell, onDownsell, completed, adjustableQuantity, onQuantityChange, }: Props): JSX.Element;
|
|
22
|
+
export default function ProductItem({ item, items, trialInDays, trialEnd, currency, mode, children, onUpsell, onDownsell, completed, adjustableQuantity, onQuantityChange, showFeatures, }: Props): JSX.Element;
|
|
22
23
|
export {};
|
|
@@ -30,7 +30,8 @@ function ProductItem({
|
|
|
30
30
|
adjustableQuantity = {
|
|
31
31
|
enabled: false
|
|
32
32
|
},
|
|
33
|
-
onQuantityChange = () => {}
|
|
33
|
+
onQuantityChange = () => {},
|
|
34
|
+
showFeatures = false
|
|
34
35
|
}) {
|
|
35
36
|
const {
|
|
36
37
|
t,
|
|
@@ -123,6 +124,7 @@ function ProductItem({
|
|
|
123
124
|
return pricing.primary;
|
|
124
125
|
}, [trialInDays, trialEnd, pricing, item, locale]);
|
|
125
126
|
const quantityInventoryError = (0, _util.formatQuantityInventory)(item.price, localQuantityNum, locale);
|
|
127
|
+
const features = item.price.product?.features || [];
|
|
126
128
|
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
127
129
|
direction: "column",
|
|
128
130
|
spacing: 1,
|
|
@@ -181,6 +183,49 @@ function ProductItem({
|
|
|
181
183
|
children: pricing.secondary
|
|
182
184
|
})]
|
|
183
185
|
})]
|
|
186
|
+
}), showFeatures && features.length > 0 && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
187
|
+
sx: {
|
|
188
|
+
display: "flex",
|
|
189
|
+
alignItems: "center",
|
|
190
|
+
justifyContent: "flex-start",
|
|
191
|
+
flexWrap: "wrap",
|
|
192
|
+
gap: 1.5,
|
|
193
|
+
width: "100%",
|
|
194
|
+
mt: 1.5
|
|
195
|
+
},
|
|
196
|
+
children: features.map(feature => /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
|
|
197
|
+
sx: {
|
|
198
|
+
display: "flex",
|
|
199
|
+
alignItems: "center",
|
|
200
|
+
justifyContent: "center",
|
|
201
|
+
gap: 0.5,
|
|
202
|
+
px: 1,
|
|
203
|
+
py: 0.5,
|
|
204
|
+
bgcolor: "action.hover",
|
|
205
|
+
borderRadius: 1,
|
|
206
|
+
border: "1px solid",
|
|
207
|
+
borderColor: "divider"
|
|
208
|
+
},
|
|
209
|
+
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
210
|
+
sx: {
|
|
211
|
+
bgcolor: "success.main",
|
|
212
|
+
width: 4,
|
|
213
|
+
height: 4,
|
|
214
|
+
borderRadius: "50%"
|
|
215
|
+
}
|
|
216
|
+
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
217
|
+
component: "span",
|
|
218
|
+
variant: "caption",
|
|
219
|
+
sx: {
|
|
220
|
+
color: "text.primary",
|
|
221
|
+
fontSize: "0.75rem",
|
|
222
|
+
fontWeight: 500,
|
|
223
|
+
textTransform: "capitalize",
|
|
224
|
+
whiteSpace: "nowrap"
|
|
225
|
+
},
|
|
226
|
+
children: feature.name
|
|
227
|
+
})]
|
|
228
|
+
}, feature.name))
|
|
184
229
|
}), quantityInventoryError ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_status.default, {
|
|
185
230
|
label: quantityInventoryError,
|
|
186
231
|
variant: "outlined",
|
|
@@ -60,7 +60,52 @@ function VendorProgressItem({
|
|
|
60
60
|
}
|
|
61
61
|
};
|
|
62
62
|
}, [startAnimation]);
|
|
63
|
-
const isCompleted = displayProgress >=
|
|
63
|
+
const isCompleted = displayProgress >= 100;
|
|
64
|
+
const isFailed = vendor.status === "failed";
|
|
65
|
+
const nameText = vendor.name || vendor.title;
|
|
66
|
+
if (isFailed) {
|
|
67
|
+
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
|
|
68
|
+
sx: {
|
|
69
|
+
mb: 2
|
|
70
|
+
},
|
|
71
|
+
children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
|
|
72
|
+
sx: {
|
|
73
|
+
display: "flex",
|
|
74
|
+
justifyContent: "space-between",
|
|
75
|
+
alignItems: "center",
|
|
76
|
+
mb: 1
|
|
77
|
+
},
|
|
78
|
+
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
79
|
+
variant: "body2",
|
|
80
|
+
sx: {
|
|
81
|
+
color: "text.secondary"
|
|
82
|
+
},
|
|
83
|
+
children: nameText ? `${nameText} - ${t("payment.checkout.vendor.failed")}` : t("payment.checkout.vendor.failed")
|
|
84
|
+
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
85
|
+
variant: "body2",
|
|
86
|
+
sx: {
|
|
87
|
+
color: "error.main",
|
|
88
|
+
fontWeight: 500
|
|
89
|
+
},
|
|
90
|
+
children: t("payment.checkout.vendor.progress", {
|
|
91
|
+
progress: 0
|
|
92
|
+
})
|
|
93
|
+
})]
|
|
94
|
+
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.LinearProgress, {
|
|
95
|
+
variant: "determinate",
|
|
96
|
+
value: 100,
|
|
97
|
+
sx: {
|
|
98
|
+
height: 8,
|
|
99
|
+
borderRadius: 4,
|
|
100
|
+
backgroundColor: "grey.200",
|
|
101
|
+
"& .MuiLinearProgress-bar": {
|
|
102
|
+
borderRadius: 4,
|
|
103
|
+
backgroundColor: "error.main"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
})]
|
|
107
|
+
});
|
|
108
|
+
}
|
|
64
109
|
const statusText = isCompleted ? t("payment.checkout.vendor.delivered") : t("payment.checkout.vendor.processing");
|
|
65
110
|
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
|
|
66
111
|
sx: {
|
|
@@ -78,7 +123,7 @@ function VendorProgressItem({
|
|
|
78
123
|
sx: {
|
|
79
124
|
color: "text.secondary"
|
|
80
125
|
},
|
|
81
|
-
children:
|
|
126
|
+
children: nameText ? `${nameText} - ${statusText}` : statusText
|
|
82
127
|
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
83
128
|
variant: "body2",
|
|
84
129
|
sx: {
|
package/lib/payment/success.js
CHANGED
|
@@ -34,17 +34,22 @@ function PaymentSuccess({
|
|
|
34
34
|
} = (0, _payment.usePaymentContext)();
|
|
35
35
|
const [vendorStatus, setVendorStatus] = (0, _react.useState)(null);
|
|
36
36
|
const [isAllCompleted, setIsAllCompleted] = (0, _react.useState)(false);
|
|
37
|
+
const [hasFailed, setHasFailed] = (0, _react.useState)(false);
|
|
38
|
+
const timerRef = (0, _react.useRef)(Date.now());
|
|
37
39
|
let next = null;
|
|
38
40
|
(0, _react.useEffect)(() => {
|
|
39
41
|
if (!hasVendor || !sessionId) return void 0;
|
|
40
42
|
const fetchVendorStatus = async interval2 => {
|
|
41
43
|
try {
|
|
42
44
|
const response = await api.get((0, _ufo.joinURL)(prefix, `/api/vendors/order/${sessionId}/status`), {});
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
+
const needCheckError = Date.now() - timerRef.current > 6 * 1e3;
|
|
46
|
+
const allCompleted = response.data?.vendors?.every(vendor => vendor.progress >= 100);
|
|
47
|
+
const hasAnyFailed = response.data?.vendors?.some(vendor => vendor.status === "failed" || needCheckError && !!vendor.error);
|
|
48
|
+
if (hasAnyFailed || allCompleted) {
|
|
45
49
|
clearInterval(interval2);
|
|
46
50
|
}
|
|
47
|
-
|
|
51
|
+
setHasFailed(hasAnyFailed);
|
|
52
|
+
setIsAllCompleted(!hasAnyFailed && allCompleted);
|
|
48
53
|
setVendorStatus(response.data);
|
|
49
54
|
} catch (error) {
|
|
50
55
|
console.error("Failed to fetch vendor status:", error);
|
|
@@ -72,7 +77,14 @@ function PaymentSuccess({
|
|
|
72
77
|
},
|
|
73
78
|
children: [vendorStatus.vendors?.map((vendor, index) => /* @__PURE__ */(0, _jsxRuntime.jsx)(_progressItem.VendorProgressItem, {
|
|
74
79
|
vendor
|
|
75
|
-
}, vendor.title || `vendor-${index}`)),
|
|
80
|
+
}, vendor.title || `vendor-${index}`)), hasFailed ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
81
|
+
variant: "h6",
|
|
82
|
+
sx: {
|
|
83
|
+
color: "warning.main",
|
|
84
|
+
mb: 1
|
|
85
|
+
},
|
|
86
|
+
children: t("payment.checkout.vendor.failedMsg")
|
|
87
|
+
}) : null, pageInfo?.success_message?.[locale] && isAllCompleted ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
76
88
|
variant: "h6",
|
|
77
89
|
sx: {
|
|
78
90
|
color: "text.primary",
|
package/lib/payment/summary.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ type Props = {
|
|
|
17
17
|
donationSettings?: DonationSettings;
|
|
18
18
|
action?: string;
|
|
19
19
|
completed?: boolean;
|
|
20
|
+
showFeatures?: boolean;
|
|
20
21
|
};
|
|
21
|
-
export default function PaymentSummary({ items, currency, trialInDays, billingThreshold, onUpsell, onDownsell, onQuantityChange, onApplyCrossSell, onCancelCrossSell, onChangeAmount, checkoutSessionId, crossSellBehavior, showStaking, donationSettings, action, trialEnd, completed, ...rest }: Props): import("react").JSX.Element;
|
|
22
|
+
export default function PaymentSummary({ items, currency, trialInDays, billingThreshold, onUpsell, onDownsell, onQuantityChange, onApplyCrossSell, onCancelCrossSell, onChangeAmount, checkoutSessionId, crossSellBehavior, showStaking, donationSettings, action, trialEnd, completed, showFeatures, ...rest }: Props): import("react").JSX.Element;
|
|
22
23
|
export {};
|
package/lib/payment/summary.js
CHANGED
|
@@ -101,6 +101,7 @@ function PaymentSummary({
|
|
|
101
101
|
action = "",
|
|
102
102
|
trialEnd = 0,
|
|
103
103
|
completed = false,
|
|
104
|
+
showFeatures = false,
|
|
104
105
|
...rest
|
|
105
106
|
}) {
|
|
106
107
|
const {
|
|
@@ -204,6 +205,7 @@ function PaymentSummary({
|
|
|
204
205
|
onDownsell: handleDownsell,
|
|
205
206
|
adjustableQuantity: x.adjustable_quantity,
|
|
206
207
|
completed,
|
|
208
|
+
showFeatures,
|
|
207
209
|
onQuantityChange: handleQuantityChange,
|
|
208
210
|
children: x.cross_sell && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
209
211
|
direction: "row",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/payment-react",
|
|
3
|
-
"version": "1.20.
|
|
3
|
+
"version": "1.20.10",
|
|
4
4
|
"description": "Reusable react components for payment kit v2",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
"@babel/core": "^7.27.4",
|
|
95
95
|
"@babel/preset-env": "^7.27.2",
|
|
96
96
|
"@babel/preset-react": "^7.27.1",
|
|
97
|
-
"@blocklet/payment-types": "1.20.
|
|
97
|
+
"@blocklet/payment-types": "1.20.10",
|
|
98
98
|
"@storybook/addon-essentials": "^7.6.20",
|
|
99
99
|
"@storybook/addon-interactions": "^7.6.20",
|
|
100
100
|
"@storybook/addon-links": "^7.6.20",
|
|
@@ -125,5 +125,5 @@
|
|
|
125
125
|
"vite-plugin-babel": "^1.3.1",
|
|
126
126
|
"vite-plugin-node-polyfills": "^0.23.0"
|
|
127
127
|
},
|
|
128
|
-
"gitHead": "
|
|
128
|
+
"gitHead": "1659d63120ced92167ec8681e51db96801b910ec"
|
|
129
129
|
}
|
package/src/libs/util.ts
CHANGED
package/src/locales/en.tsx
CHANGED
|
@@ -187,7 +187,8 @@ export default flat({
|
|
|
187
187
|
progress: 'Progress {progress}%',
|
|
188
188
|
delivered: 'Installation completed',
|
|
189
189
|
failed: 'Processing failed',
|
|
190
|
-
|
|
190
|
+
failedMsg:
|
|
191
|
+
'An exception occurred during installation. We will automatically process a refund for you. We apologize for the inconvenience caused. Thank you for your understanding!',
|
|
191
192
|
},
|
|
192
193
|
confirm: {
|
|
193
194
|
withStake:
|
package/src/locales/zh.tsx
CHANGED
package/src/payment/index.tsx
CHANGED
|
@@ -262,6 +262,8 @@ function PaymentInner({
|
|
|
262
262
|
trialEnd = 0;
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
+
const showFeatures = `${paymentLink?.metadata?.show_product_features}` === 'true';
|
|
266
|
+
|
|
265
267
|
return (
|
|
266
268
|
<FormProvider {...methods}>
|
|
267
269
|
<Stack className="cko-container" sx={{ gap: { sm: mode === 'standalone' ? 0 : mode === 'inline' ? 4 : 8 } }}>
|
|
@@ -290,6 +292,7 @@ function PaymentInner({
|
|
|
290
292
|
donationSettings={paymentLink?.donation_settings}
|
|
291
293
|
action={action}
|
|
292
294
|
completed={completed}
|
|
295
|
+
showFeatures={showFeatures}
|
|
293
296
|
/>
|
|
294
297
|
{mode === 'standalone' && !isMobile && (
|
|
295
298
|
<CheckoutFooter className="cko-footer" sx={{ color: 'text.lighter' }} />
|
|
@@ -37,6 +37,7 @@ type Props = {
|
|
|
37
37
|
};
|
|
38
38
|
onQuantityChange?: (itemId: string, quantity: number) => void;
|
|
39
39
|
completed?: boolean;
|
|
40
|
+
showFeatures?: boolean;
|
|
40
41
|
};
|
|
41
42
|
|
|
42
43
|
export default function ProductItem({
|
|
@@ -52,6 +53,7 @@ export default function ProductItem({
|
|
|
52
53
|
completed = false,
|
|
53
54
|
adjustableQuantity = { enabled: false },
|
|
54
55
|
onQuantityChange = () => {},
|
|
56
|
+
showFeatures = false,
|
|
55
57
|
}: Props) {
|
|
56
58
|
const { t, locale } = useLocaleContext();
|
|
57
59
|
const { settings, setPayable } = usePaymentContext();
|
|
@@ -153,6 +155,7 @@ export default function ProductItem({
|
|
|
153
155
|
}, [trialInDays, trialEnd, pricing, item, locale]);
|
|
154
156
|
|
|
155
157
|
const quantityInventoryError = formatQuantityInventory(item.price, localQuantityNum, locale);
|
|
158
|
+
const features = item.price.product?.features || [];
|
|
156
159
|
|
|
157
160
|
return (
|
|
158
161
|
<Stack
|
|
@@ -182,7 +185,7 @@ export default function ProductItem({
|
|
|
182
185
|
<ProductCard
|
|
183
186
|
logo={item.price.product?.images[0]}
|
|
184
187
|
name={item.price.product?.name}
|
|
185
|
-
// description={item.price.product?.description}
|
|
188
|
+
// description={showDescription ? item.price.product?.description : undefined}
|
|
186
189
|
extra={
|
|
187
190
|
<Box
|
|
188
191
|
sx={{
|
|
@@ -209,6 +212,56 @@ export default function ProductItem({
|
|
|
209
212
|
)}
|
|
210
213
|
</Stack>
|
|
211
214
|
</Stack>
|
|
215
|
+
{showFeatures && features.length > 0 && (
|
|
216
|
+
<Box
|
|
217
|
+
sx={{
|
|
218
|
+
display: 'flex',
|
|
219
|
+
alignItems: 'center',
|
|
220
|
+
justifyContent: 'flex-start',
|
|
221
|
+
flexWrap: 'wrap',
|
|
222
|
+
gap: 1.5,
|
|
223
|
+
width: '100%',
|
|
224
|
+
mt: 1.5,
|
|
225
|
+
}}>
|
|
226
|
+
{features.map((feature) => (
|
|
227
|
+
<Box
|
|
228
|
+
key={feature.name}
|
|
229
|
+
sx={{
|
|
230
|
+
display: 'flex',
|
|
231
|
+
alignItems: 'center',
|
|
232
|
+
justifyContent: 'center',
|
|
233
|
+
gap: 0.5,
|
|
234
|
+
px: 1,
|
|
235
|
+
py: 0.5,
|
|
236
|
+
bgcolor: 'action.hover',
|
|
237
|
+
borderRadius: 1,
|
|
238
|
+
border: '1px solid',
|
|
239
|
+
borderColor: 'divider',
|
|
240
|
+
}}>
|
|
241
|
+
<Box
|
|
242
|
+
sx={{
|
|
243
|
+
bgcolor: 'success.main',
|
|
244
|
+
width: 4,
|
|
245
|
+
height: 4,
|
|
246
|
+
borderRadius: '50%',
|
|
247
|
+
}}
|
|
248
|
+
/>
|
|
249
|
+
<Typography
|
|
250
|
+
component="span"
|
|
251
|
+
variant="caption"
|
|
252
|
+
sx={{
|
|
253
|
+
color: 'text.primary',
|
|
254
|
+
fontSize: '0.75rem',
|
|
255
|
+
fontWeight: 500,
|
|
256
|
+
textTransform: 'capitalize',
|
|
257
|
+
whiteSpace: 'nowrap',
|
|
258
|
+
}}>
|
|
259
|
+
{feature.name}
|
|
260
|
+
</Typography>
|
|
261
|
+
</Box>
|
|
262
|
+
))}
|
|
263
|
+
</Box>
|
|
264
|
+
)}
|
|
212
265
|
{quantityInventoryError ? (
|
|
213
266
|
<Status
|
|
214
267
|
label={quantityInventoryError}
|
|
@@ -4,6 +4,8 @@ import { useCallback, useEffect, useRef, useState } from 'react';
|
|
|
4
4
|
|
|
5
5
|
interface VendorStatus {
|
|
6
6
|
success: boolean;
|
|
7
|
+
name?: string;
|
|
8
|
+
key?: string;
|
|
7
9
|
status: 'delivered' | 'pending' | 'failed';
|
|
8
10
|
progress: number;
|
|
9
11
|
message: string;
|
|
@@ -75,14 +77,46 @@ export function VendorProgressItem({ vendor }: { vendor: VendorStatus }) {
|
|
|
75
77
|
};
|
|
76
78
|
}, [startAnimation]);
|
|
77
79
|
|
|
78
|
-
const isCompleted = displayProgress >=
|
|
79
|
-
const
|
|
80
|
+
const isCompleted = displayProgress >= 100;
|
|
81
|
+
const isFailed = vendor.status === 'failed';
|
|
82
|
+
|
|
83
|
+
const nameText = vendor.name || vendor.title;
|
|
84
|
+
|
|
85
|
+
// 如果是失败状态,显示错误 UI
|
|
86
|
+
if (isFailed) {
|
|
87
|
+
return (
|
|
88
|
+
<Box sx={{ mb: 2 }}>
|
|
89
|
+
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 1 }}>
|
|
90
|
+
<Typography variant="body2" sx={{ color: 'text.secondary' }}>
|
|
91
|
+
{nameText ? `${nameText} - ${t('payment.checkout.vendor.failed')}` : t('payment.checkout.vendor.failed')}
|
|
92
|
+
</Typography>
|
|
93
|
+
<Typography variant="body2" sx={{ color: 'error.main', fontWeight: 500 }}>
|
|
94
|
+
{t('payment.checkout.vendor.progress', { progress: 0 })}
|
|
95
|
+
</Typography>
|
|
96
|
+
</Box>
|
|
97
|
+
<LinearProgress
|
|
98
|
+
variant="determinate"
|
|
99
|
+
value={100}
|
|
100
|
+
sx={{
|
|
101
|
+
height: 8,
|
|
102
|
+
borderRadius: 4,
|
|
103
|
+
backgroundColor: 'grey.200',
|
|
104
|
+
'& .MuiLinearProgress-bar': {
|
|
105
|
+
borderRadius: 4,
|
|
106
|
+
backgroundColor: 'error.main',
|
|
107
|
+
},
|
|
108
|
+
}}
|
|
109
|
+
/>
|
|
110
|
+
</Box>
|
|
111
|
+
);
|
|
112
|
+
}
|
|
80
113
|
|
|
114
|
+
const statusText = isCompleted ? t('payment.checkout.vendor.delivered') : t('payment.checkout.vendor.processing');
|
|
81
115
|
return (
|
|
82
116
|
<Box sx={{ mb: 2 }}>
|
|
83
117
|
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 1 }}>
|
|
84
118
|
<Typography variant="body2" sx={{ color: 'text.secondary' }}>
|
|
85
|
-
{
|
|
119
|
+
{nameText ? `${nameText} - ${statusText}` : statusText}
|
|
86
120
|
</Typography>
|
|
87
121
|
<Typography variant="body2" sx={{ color: 'text.secondary', fontWeight: 500 }}>
|
|
88
122
|
{t('payment.checkout.vendor.progress', { progress: displayProgress })}
|
package/src/payment/success.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
2
2
|
import { Box, Grow, Link, Paper, Stack, styled, Typography } from '@mui/material';
|
|
3
|
-
import { useEffect, useState } from 'react';
|
|
3
|
+
import { useEffect, useRef, useState } from 'react';
|
|
4
4
|
import { joinURL } from 'ufo';
|
|
5
5
|
|
|
6
6
|
import { Button } from '@arcblock/ux';
|
|
@@ -52,6 +52,8 @@ export default function PaymentSuccess({
|
|
|
52
52
|
const { prefix, api } = usePaymentContext();
|
|
53
53
|
const [vendorStatus, setVendorStatus] = useState<VendorResponse | null>(null);
|
|
54
54
|
const [isAllCompleted, setIsAllCompleted] = useState(false);
|
|
55
|
+
const [hasFailed, setHasFailed] = useState(false);
|
|
56
|
+
const timerRef = useRef(Date.now());
|
|
55
57
|
let next: any = null;
|
|
56
58
|
|
|
57
59
|
// Fetch vendor status when hasVendor is true
|
|
@@ -61,11 +63,18 @@ export default function PaymentSuccess({
|
|
|
61
63
|
const fetchVendorStatus = async (interval?: NodeJS.Timeout) => {
|
|
62
64
|
try {
|
|
63
65
|
const response = await api.get(joinURL(prefix, `/api/vendors/order/${sessionId}/status`), {});
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
+
const needCheckError = Date.now() - timerRef.current > 6 * 1000;
|
|
67
|
+
|
|
68
|
+
const allCompleted = response.data?.vendors?.every((vendor: any) => vendor.progress >= 100);
|
|
69
|
+
const hasAnyFailed = response.data?.vendors?.some(
|
|
70
|
+
(vendor: any) => vendor.status === 'failed' || (needCheckError && !!vendor.error)
|
|
71
|
+
);
|
|
72
|
+
if (hasAnyFailed || allCompleted) {
|
|
66
73
|
clearInterval(interval);
|
|
67
74
|
}
|
|
68
|
-
|
|
75
|
+
|
|
76
|
+
setHasFailed(hasAnyFailed);
|
|
77
|
+
setIsAllCompleted(!hasAnyFailed && allCompleted);
|
|
69
78
|
setVendorStatus(response.data);
|
|
70
79
|
} catch (error) {
|
|
71
80
|
console.error('Failed to fetch vendor status:', error);
|
|
@@ -102,6 +111,11 @@ export default function PaymentSuccess({
|
|
|
102
111
|
{vendorStatus.vendors?.map((vendor, index) => (
|
|
103
112
|
<VendorProgressItem key={vendor.title || `vendor-${index}`} vendor={vendor} />
|
|
104
113
|
))}
|
|
114
|
+
{hasFailed ? (
|
|
115
|
+
<Typography variant="h6" sx={{ color: 'warning.main', mb: 1 }}>
|
|
116
|
+
{t('payment.checkout.vendor.failedMsg')}
|
|
117
|
+
</Typography>
|
|
118
|
+
) : null}
|
|
105
119
|
{pageInfo?.success_message?.[locale] && isAllCompleted ? (
|
|
106
120
|
<Typography variant="h6" sx={{ color: 'text.primary', mb: 1 }}>
|
|
107
121
|
{pageInfo?.success_message?.[locale]}
|
package/src/payment/summary.tsx
CHANGED
|
@@ -71,6 +71,7 @@ type Props = {
|
|
|
71
71
|
donationSettings?: DonationSettings; // only include backend part
|
|
72
72
|
action?: string;
|
|
73
73
|
completed?: boolean;
|
|
74
|
+
showFeatures?: boolean;
|
|
74
75
|
};
|
|
75
76
|
|
|
76
77
|
async function fetchCrossSell(id: string) {
|
|
@@ -138,6 +139,7 @@ export default function PaymentSummary({
|
|
|
138
139
|
action = '',
|
|
139
140
|
trialEnd = 0,
|
|
140
141
|
completed = false,
|
|
142
|
+
showFeatures = false,
|
|
141
143
|
...rest
|
|
142
144
|
}: Props) {
|
|
143
145
|
const { t, locale } = useLocaleContext();
|
|
@@ -233,6 +235,7 @@ export default function PaymentSummary({
|
|
|
233
235
|
onDownsell={handleDownsell}
|
|
234
236
|
adjustableQuantity={x.adjustable_quantity}
|
|
235
237
|
completed={completed}
|
|
238
|
+
showFeatures={showFeatures}
|
|
236
239
|
onQuantityChange={handleQuantityChange}>
|
|
237
240
|
{x.cross_sell && (
|
|
238
241
|
<Stack
|