@blocklet/payment-react 1.26.1 → 1.26.3
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-v2/components/dialogs/checkout-dialogs.js +2 -0
- package/es/checkout-v2/components/left/cross-sell-card.js +3 -3
- package/es/checkout-v2/components/left/product-item-card.js +9 -3
- package/es/checkout-v2/components/left/promotion-input.d.ts +4 -1
- package/es/checkout-v2/components/left/promotion-input.js +8 -13
- package/es/checkout-v2/components/right/customer-info-card.d.ts +2 -0
- package/es/checkout-v2/components/right/customer-info-card.js +22 -14
- package/es/checkout-v2/components/right/status-feedback.js +1 -1
- package/es/checkout-v2/components/right/submit-button.js +3 -1
- package/es/checkout-v2/layouts/checkout-layout.js +13 -3
- package/es/checkout-v2/panels/left/composite-panel.js +27 -6
- package/es/checkout-v2/panels/right/payment-panel.js +40 -9
- package/es/checkout-v2/utils/format.d.ts +1 -1
- package/es/checkout-v2/utils/format.js +1 -0
- package/es/checkout-v2/views/error-view.d.ts +1 -1
- package/es/checkout-v2/views/error-view.js +9 -0
- package/es/checkout-v2/views/success-view.js +3 -1
- package/es/components/over-due-invoice-payment.js +5 -3
- package/es/components/service-suspended-dialog.d.ts +4 -0
- package/es/components/service-suspended-dialog.js +61 -0
- package/es/libs/util.d.ts +8 -0
- package/es/libs/util.js +3 -0
- package/es/locales/en.js +4 -0
- package/es/locales/zh.js +4 -0
- package/es/payment/form/index.js +17 -0
- package/es/payment/index.js +15 -4
- package/lib/checkout-v2/components/dialogs/checkout-dialogs.js +4 -0
- package/lib/checkout-v2/components/left/cross-sell-card.js +2 -2
- package/lib/checkout-v2/components/left/product-item-card.js +9 -2
- package/lib/checkout-v2/components/left/promotion-input.d.ts +4 -1
- package/lib/checkout-v2/components/left/promotion-input.js +12 -19
- package/lib/checkout-v2/components/right/customer-info-card.d.ts +2 -0
- package/lib/checkout-v2/components/right/customer-info-card.js +19 -13
- package/lib/checkout-v2/components/right/status-feedback.js +1 -1
- package/lib/checkout-v2/components/right/submit-button.js +3 -1
- package/lib/checkout-v2/layouts/checkout-layout.js +28 -5
- package/lib/checkout-v2/panels/left/composite-panel.js +20 -5
- package/lib/checkout-v2/panels/right/payment-panel.js +46 -7
- package/lib/checkout-v2/utils/format.d.ts +1 -1
- package/lib/checkout-v2/utils/format.js +7 -0
- package/lib/checkout-v2/views/error-view.d.ts +1 -1
- package/lib/checkout-v2/views/error-view.js +9 -0
- package/lib/checkout-v2/views/success-view.js +2 -0
- package/lib/components/over-due-invoice-payment.js +12 -2
- package/lib/components/service-suspended-dialog.d.ts +4 -0
- package/lib/components/service-suspended-dialog.js +97 -0
- package/lib/libs/util.d.ts +8 -0
- package/lib/libs/util.js +4 -0
- package/lib/locales/en.js +4 -0
- package/lib/locales/zh.js +4 -0
- package/lib/payment/form/index.js +23 -0
- package/lib/payment/index.js +15 -4
- package/package.json +4 -4
- package/src/checkout-v2/components/dialogs/checkout-dialogs.tsx +4 -0
- package/src/checkout-v2/components/left/cross-sell-card.tsx +3 -3
- package/src/checkout-v2/components/left/product-item-card.tsx +18 -8
- package/src/checkout-v2/components/left/promotion-input.tsx +17 -17
- package/src/checkout-v2/components/right/customer-info-card.tsx +29 -16
- package/src/checkout-v2/components/right/status-feedback.tsx +2 -2
- package/src/checkout-v2/components/right/submit-button.tsx +2 -0
- package/src/checkout-v2/layouts/checkout-layout.tsx +25 -10
- package/src/checkout-v2/panels/left/composite-panel.tsx +28 -6
- package/src/checkout-v2/panels/right/payment-panel.tsx +32 -5
- package/src/checkout-v2/utils/format.ts +2 -0
- package/src/checkout-v2/views/error-view.tsx +11 -1
- package/src/checkout-v2/views/success-view.tsx +3 -1
- package/src/components/over-due-invoice-payment.tsx +6 -3
- package/src/components/service-suspended-dialog.tsx +64 -0
- package/src/libs/util.ts +7 -0
- package/src/locales/en.tsx +4 -0
- package/src/locales/zh.tsx +4 -0
- package/src/payment/form/index.tsx +20 -0
- package/src/payment/index.tsx +26 -4
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Button, Dialog, DialogContent, Stack, Typography } from "@mui/material";
|
|
3
|
+
import { alpha } from "@mui/material/styles";
|
|
4
|
+
import PauseCircleOutlineIcon from "@mui/icons-material/PauseCircleOutline";
|
|
5
|
+
import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
|
|
6
|
+
export default function ServiceSuspendedDialog({ open, onClose }) {
|
|
7
|
+
const { t } = useLocaleContext();
|
|
8
|
+
return /* @__PURE__ */ jsx(
|
|
9
|
+
Dialog,
|
|
10
|
+
{
|
|
11
|
+
open,
|
|
12
|
+
onClose,
|
|
13
|
+
PaperProps: {
|
|
14
|
+
sx: {
|
|
15
|
+
borderRadius: 3,
|
|
16
|
+
maxWidth: 400,
|
|
17
|
+
mx: "auto",
|
|
18
|
+
overflow: "hidden"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
children: /* @__PURE__ */ jsxs(DialogContent, { sx: { p: 0 }, children: [
|
|
22
|
+
/* @__PURE__ */ jsxs(Stack, { alignItems: "center", sx: { pt: 4, pb: 3, px: 4, textAlign: "center" }, children: [
|
|
23
|
+
/* @__PURE__ */ jsx(
|
|
24
|
+
Box,
|
|
25
|
+
{
|
|
26
|
+
sx: {
|
|
27
|
+
width: 64,
|
|
28
|
+
height: 64,
|
|
29
|
+
borderRadius: "50%",
|
|
30
|
+
display: "flex",
|
|
31
|
+
alignItems: "center",
|
|
32
|
+
justifyContent: "center",
|
|
33
|
+
bgcolor: (theme) => alpha(theme.palette.warning.main, 0.1),
|
|
34
|
+
mb: 2.5
|
|
35
|
+
},
|
|
36
|
+
children: /* @__PURE__ */ jsx(PauseCircleOutlineIcon, { sx: { fontSize: 36, color: "warning.main" } })
|
|
37
|
+
}
|
|
38
|
+
),
|
|
39
|
+
/* @__PURE__ */ jsx(Typography, { sx: { fontWeight: 700, fontSize: 18, mb: 1, color: "text.primary" }, children: t("payment.checkout.stopAcceptingOrders.title") }),
|
|
40
|
+
/* @__PURE__ */ jsx(Typography, { sx: { color: "text.secondary", fontSize: 14, lineHeight: 1.6 }, children: t("payment.checkout.stopAcceptingOrders.description") })
|
|
41
|
+
] }),
|
|
42
|
+
/* @__PURE__ */ jsx(Box, { sx: { px: 4, pb: 3 }, children: /* @__PURE__ */ jsx(
|
|
43
|
+
Button,
|
|
44
|
+
{
|
|
45
|
+
fullWidth: true,
|
|
46
|
+
variant: "contained",
|
|
47
|
+
disableElevation: true,
|
|
48
|
+
onClick: onClose,
|
|
49
|
+
sx: {
|
|
50
|
+
borderRadius: 2,
|
|
51
|
+
textTransform: "none",
|
|
52
|
+
fontWeight: 600,
|
|
53
|
+
py: 1
|
|
54
|
+
},
|
|
55
|
+
children: t("common.know")
|
|
56
|
+
}
|
|
57
|
+
) })
|
|
58
|
+
] })
|
|
59
|
+
}
|
|
60
|
+
);
|
|
61
|
+
}
|
package/es/libs/util.d.ts
CHANGED
|
@@ -194,3 +194,11 @@ export declare function getTokenBalanceLink(method: TPaymentMethod, address: str
|
|
|
194
194
|
export declare function isCreditMetered(price: TPrice): boolean;
|
|
195
195
|
export declare function showStaking(method: TPaymentMethod, currency: TPaymentCurrency, noStake: boolean): boolean;
|
|
196
196
|
export declare function formatLinkWithLocale(url: string, locale?: string): string;
|
|
197
|
+
export declare function primaryContrastColor(theme: {
|
|
198
|
+
palette: {
|
|
199
|
+
primary: {
|
|
200
|
+
main: string;
|
|
201
|
+
};
|
|
202
|
+
getContrastText: (bg: string) => string;
|
|
203
|
+
};
|
|
204
|
+
}): string;
|
package/es/libs/util.js
CHANGED
package/es/locales/en.js
CHANGED
|
@@ -380,6 +380,10 @@ export default flat({
|
|
|
380
380
|
title: "Nothing to show here",
|
|
381
381
|
description: "It seems this checkout session is not configured properly"
|
|
382
382
|
},
|
|
383
|
+
stopAcceptingOrders: {
|
|
384
|
+
title: "Service Suspended",
|
|
385
|
+
description: "New order placement is temporarily unavailable due to a system-level service suspension."
|
|
386
|
+
},
|
|
383
387
|
error: {
|
|
384
388
|
title: "Something went wrong"
|
|
385
389
|
},
|
package/es/locales/zh.js
CHANGED
|
@@ -409,6 +409,10 @@ export default flat({
|
|
|
409
409
|
title: "\u6CA1\u6709\u4EFB\u4F55\u8D2D\u4E70\u9879\u76EE",
|
|
410
410
|
description: "\u53EF\u80FD\u8FD9\u4E2A\u4ED8\u6B3E\u94FE\u63A5\u6CA1\u6709\u6B63\u786E\u914D\u7F6E"
|
|
411
411
|
},
|
|
412
|
+
stopAcceptingOrders: {
|
|
413
|
+
title: "\u6682\u505C\u670D\u52A1",
|
|
414
|
+
description: "\u56E0\u7CFB\u7EDF\u7B56\u7565\u8C03\u6574\uFF0C\u5F53\u524D\u5DF2\u6682\u505C\u65B0\u8BA2\u5355\u670D\u52A1\u3002"
|
|
415
|
+
},
|
|
412
416
|
error: {
|
|
413
417
|
title: "\u51FA\u4E86\u70B9\u95EE\u9898"
|
|
414
418
|
},
|
package/es/payment/form/index.js
CHANGED
|
@@ -48,6 +48,7 @@ import LoadingButton from "../../components/loading-button.js";
|
|
|
48
48
|
import OverdueInvoicePayment from "../../components/over-due-invoice-payment.js";
|
|
49
49
|
import { saveCurrencyPreference } from "../../libs/currency.js";
|
|
50
50
|
import ConfirmDialog from "../../components/confirm.js";
|
|
51
|
+
import ServiceSuspendedDialog from "../../components/service-suspended-dialog.js";
|
|
51
52
|
import PriceChangeConfirm from "../../components/price-change-confirm.js";
|
|
52
53
|
import { getFieldValidation, validatePostalCode } from "../../libs/validator.js";
|
|
53
54
|
const generateIdempotencyKey = (sessionId, currencyId) => {
|
|
@@ -164,6 +165,7 @@ export default function PaymentForm({
|
|
|
164
165
|
stripeContext: void 0,
|
|
165
166
|
customer,
|
|
166
167
|
customerLimited: false,
|
|
168
|
+
serviceSuspended: false,
|
|
167
169
|
stripePaying: false,
|
|
168
170
|
fastCheckoutInfo: null,
|
|
169
171
|
creditInsufficientInfo: null,
|
|
@@ -932,6 +934,10 @@ export default function PaymentForm({
|
|
|
932
934
|
shouldToast = false;
|
|
933
935
|
setState({ customerLimited: true });
|
|
934
936
|
}
|
|
937
|
+
if (errorCode === "STOP_ACCEPTING_ORDERS") {
|
|
938
|
+
shouldToast = false;
|
|
939
|
+
setState({ serviceSuspended: true });
|
|
940
|
+
}
|
|
935
941
|
}
|
|
936
942
|
if (shouldToast) {
|
|
937
943
|
Toast.error(formatError(err));
|
|
@@ -1179,6 +1185,7 @@ export default function PaymentForm({
|
|
|
1179
1185
|
}
|
|
1180
1186
|
}
|
|
1181
1187
|
),
|
|
1188
|
+
state.serviceSuspended && /* @__PURE__ */ jsx(ServiceSuspendedDialog, { open: true, onClose: () => setState({ serviceSuspended: false }) }),
|
|
1182
1189
|
FastCheckoutConfirmDialog,
|
|
1183
1190
|
CreditInsufficientDialog,
|
|
1184
1191
|
PriceUpdatedDialog,
|
|
@@ -1444,6 +1451,16 @@ export default function PaymentForm({
|
|
|
1444
1451
|
}
|
|
1445
1452
|
}
|
|
1446
1453
|
),
|
|
1454
|
+
state.serviceSuspended && /* @__PURE__ */ jsx(
|
|
1455
|
+
ConfirmDialog,
|
|
1456
|
+
{
|
|
1457
|
+
onConfirm: () => setState({ serviceSuspended: false }),
|
|
1458
|
+
onCancel: () => setState({ serviceSuspended: false }),
|
|
1459
|
+
title: t("payment.checkout.stopAcceptingOrders.title"),
|
|
1460
|
+
message: t("payment.checkout.stopAcceptingOrders.description"),
|
|
1461
|
+
confirm: t("common.confirm")
|
|
1462
|
+
}
|
|
1463
|
+
),
|
|
1447
1464
|
FastCheckoutConfirmDialog,
|
|
1448
1465
|
CreditInsufficientDialog,
|
|
1449
1466
|
PriceUpdatedDialog,
|
package/es/payment/index.js
CHANGED
|
@@ -78,6 +78,10 @@ function PaymentInner({
|
|
|
78
78
|
return Array.from(currencyIds);
|
|
79
79
|
}, [paymentMethods]);
|
|
80
80
|
const defaultCurrencyId = useMemo(() => {
|
|
81
|
+
const hasAppliedDiscount = Boolean(state.checkoutSession?.discounts?.length);
|
|
82
|
+
if (hasAppliedDiscount && state.checkoutSession.currency_id && availableCurrencyIds.includes(state.checkoutSession.currency_id)) {
|
|
83
|
+
return state.checkoutSession.currency_id;
|
|
84
|
+
}
|
|
81
85
|
if (query.currencyId && availableCurrencyIds.includes(query.currencyId)) {
|
|
82
86
|
return query.currencyId;
|
|
83
87
|
}
|
|
@@ -95,7 +99,7 @@ function PaymentInner({
|
|
|
95
99
|
return state.checkoutSession.currency_id;
|
|
96
100
|
}
|
|
97
101
|
return availableCurrencyIds?.[0];
|
|
98
|
-
}, [query.currencyId, availableCurrencyIds, session?.user, state.checkoutSession
|
|
102
|
+
}, [query.currencyId, availableCurrencyIds, session?.user, state.checkoutSession, paymentMethods]);
|
|
99
103
|
const defaultMethodId = paymentMethods.find((m) => m.payment_currencies.some((c) => c.id === defaultCurrencyId))?.id;
|
|
100
104
|
const hideSummaryCard = mode.endsWith("-minimal") || !showCheckoutSummary;
|
|
101
105
|
const methods = useForm({
|
|
@@ -122,13 +126,20 @@ function PaymentInner({
|
|
|
122
126
|
}
|
|
123
127
|
});
|
|
124
128
|
useEffect(() => {
|
|
129
|
+
const hasAppliedDiscount = Boolean(state.checkoutSession?.discounts?.length);
|
|
130
|
+
const currentCurrency = methods.getValues("payment_currency");
|
|
131
|
+
const currentMethod = methods.getValues("payment_method");
|
|
125
132
|
if (defaultCurrencyId) {
|
|
126
|
-
|
|
133
|
+
if (!hasAppliedDiscount || !currentCurrency) {
|
|
134
|
+
methods.setValue("payment_currency", defaultCurrencyId);
|
|
135
|
+
}
|
|
127
136
|
}
|
|
128
137
|
if (defaultMethodId) {
|
|
129
|
-
|
|
138
|
+
if (!hasAppliedDiscount || !currentMethod) {
|
|
139
|
+
methods.setValue("payment_method", defaultMethodId);
|
|
140
|
+
}
|
|
130
141
|
}
|
|
131
|
-
}, [defaultCurrencyId, defaultMethodId]);
|
|
142
|
+
}, [defaultCurrencyId, defaultMethodId, state.checkoutSession.discounts]);
|
|
132
143
|
useEffect(() => {
|
|
133
144
|
if (!isMobileSafari()) {
|
|
134
145
|
return () => {
|
|
@@ -11,6 +11,7 @@ var _paymentReactHeadless = require("@blocklet/payment-react-headless");
|
|
|
11
11
|
var _stripe = _interopRequireDefault(require("../../../payment/form/stripe"));
|
|
12
12
|
var _confirm = _interopRequireDefault(require("../../../components/confirm"));
|
|
13
13
|
var _priceChangeConfirm = _interopRequireDefault(require("../../../components/price-change-confirm"));
|
|
14
|
+
var _serviceSuspendedDialog = _interopRequireDefault(require("../../../components/service-suspended-dialog"));
|
|
14
15
|
var _format = require("../../utils/format");
|
|
15
16
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
16
17
|
function getRedirectUrl(session) {
|
|
@@ -118,6 +119,9 @@ function CheckoutDialogs() {
|
|
|
118
119
|
}),
|
|
119
120
|
loading: false,
|
|
120
121
|
color: "primary"
|
|
122
|
+
}), submit.context?.type === "service_suspended" && /* @__PURE__ */(0, _jsxRuntime.jsx)(_serviceSuspendedDialog.default, {
|
|
123
|
+
open: true,
|
|
124
|
+
onClose: submit.cancel
|
|
121
125
|
}), submit.status === "credit_insufficient" && submit.context?.type === "credit_insufficient" && /* @__PURE__ */(0, _jsxRuntime.jsx)(_confirm.default, {
|
|
122
126
|
onConfirm: submit.cancel,
|
|
123
127
|
onCancel: submit.cancel,
|
|
@@ -54,7 +54,7 @@ function CrossSellCard({
|
|
|
54
54
|
fontWeight: 900,
|
|
55
55
|
letterSpacing: "0.12em",
|
|
56
56
|
bgcolor: "primary.main",
|
|
57
|
-
color:
|
|
57
|
+
color: theme => (0, _format.primaryContrastColor)(theme),
|
|
58
58
|
boxShadow: "0 4px 12px rgba(45,124,243,0.2)",
|
|
59
59
|
"& .MuiChip-label": {
|
|
60
60
|
px: 1.5
|
|
@@ -236,7 +236,7 @@ function CrossSellCard({
|
|
|
236
236
|
transition: "all 0.2s",
|
|
237
237
|
"&:hover": {
|
|
238
238
|
bgcolor: "primary.main",
|
|
239
|
-
color:
|
|
239
|
+
color: theme => (0, _format.primaryContrastColor)(theme),
|
|
240
240
|
borderColor: "primary.main"
|
|
241
241
|
},
|
|
242
242
|
"&:active": {
|
|
@@ -246,7 +246,7 @@ function ProductItemCard({
|
|
|
246
246
|
fontWeight: 900,
|
|
247
247
|
letterSpacing: "0.12em",
|
|
248
248
|
bgcolor: "primary.main",
|
|
249
|
-
color:
|
|
249
|
+
color: th => (0, _format.primaryContrastColor)(th),
|
|
250
250
|
boxShadow: "0 4px 12px rgba(45,124,243,0.2)",
|
|
251
251
|
"& .MuiChip-label": {
|
|
252
252
|
px: 1.5
|
|
@@ -513,7 +513,14 @@ function ProductItemCard({
|
|
|
513
513
|
sx: {
|
|
514
514
|
mt: 1.5
|
|
515
515
|
},
|
|
516
|
-
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.
|
|
516
|
+
children: isRateLoading ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
|
|
517
|
+
variant: "rounded",
|
|
518
|
+
width: 160,
|
|
519
|
+
height: 22,
|
|
520
|
+
sx: {
|
|
521
|
+
borderRadius: "6px"
|
|
522
|
+
}
|
|
523
|
+
}) : /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Chip, {
|
|
517
524
|
icon: /* @__PURE__ */(0, _jsxRuntime.jsx)(_LocalOffer.default, {
|
|
518
525
|
sx: {
|
|
519
526
|
color: "warning.main",
|
|
@@ -12,8 +12,11 @@ interface PromotionInputProps {
|
|
|
12
12
|
};
|
|
13
13
|
discounts: any[];
|
|
14
14
|
discountAmount: string | null;
|
|
15
|
+
currency?: any;
|
|
15
16
|
/** Start with input field visible (skip the "Add promotion code" button) */
|
|
16
17
|
initialShowInput?: boolean;
|
|
18
|
+
/** Show skeleton for the discount amount while switching */
|
|
19
|
+
isAmountLoading?: boolean;
|
|
17
20
|
}
|
|
18
|
-
export default function PromotionInput({ promotion, discounts, discountAmount, initialShowInput, }: PromotionInputProps): import("react").JSX.Element | null;
|
|
21
|
+
export default function PromotionInput({ promotion, discounts, discountAmount, currency, initialShowInput, isAmountLoading, }: PromotionInputProps): import("react").JSX.Element | null;
|
|
19
22
|
export {};
|
|
@@ -11,15 +11,19 @@ var _Close = _interopRequireDefault(require("@mui/icons-material/Close"));
|
|
|
11
11
|
var _LocalOffer = _interopRequireDefault(require("@mui/icons-material/LocalOffer"));
|
|
12
12
|
var _material = require("@mui/material");
|
|
13
13
|
var _context = require("@arcblock/ux/lib/Locale/context");
|
|
14
|
+
var _util = require("../../../libs/util");
|
|
14
15
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
16
|
function PromotionInput({
|
|
16
17
|
promotion,
|
|
17
18
|
discounts,
|
|
18
19
|
discountAmount,
|
|
19
|
-
|
|
20
|
+
currency = null,
|
|
21
|
+
initialShowInput = false,
|
|
22
|
+
isAmountLoading = false
|
|
20
23
|
}) {
|
|
21
24
|
const {
|
|
22
|
-
t
|
|
25
|
+
t,
|
|
26
|
+
locale
|
|
23
27
|
} = (0, _context.useLocaleContext)();
|
|
24
28
|
const [showInput, setShowInput] = (0, _react.useState)(false);
|
|
25
29
|
const [code, setCode] = (0, _react.useState)("");
|
|
@@ -49,22 +53,7 @@ function PromotionInput({
|
|
|
49
53
|
children: discounts.map((disc, i) => {
|
|
50
54
|
const discCode = disc.promotion_code_details?.code || disc.verification_data?.code || disc.promotion_code || "";
|
|
51
55
|
const coupon = disc.coupon_details || {};
|
|
52
|
-
const
|
|
53
|
-
percent: coupon.percent_off
|
|
54
|
-
}) : `${coupon.percent_off || 0}%`;
|
|
55
|
-
let description = "";
|
|
56
|
-
if (coupon.duration === "repeating" && coupon.duration_in_months) {
|
|
57
|
-
const months = coupon.duration_in_months;
|
|
58
|
-
description = `${couponOff} for ${months} month${months > 1 ? "s" : ""}`;
|
|
59
|
-
} else if (coupon.duration === "forever") {
|
|
60
|
-
description = t("payment.checkout.coupon.terms.forever", {
|
|
61
|
-
couponOff
|
|
62
|
-
});
|
|
63
|
-
} else if (coupon.duration === "once") {
|
|
64
|
-
description = t("payment.checkout.coupon.terms.once", {
|
|
65
|
-
couponOff
|
|
66
|
-
});
|
|
67
|
-
}
|
|
56
|
+
const description = coupon && currency ? (0, _util.formatCouponTerms)(coupon, currency, locale) : "";
|
|
68
57
|
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
69
58
|
direction: "row",
|
|
70
59
|
justifyContent: "space-between",
|
|
@@ -116,7 +105,11 @@ function PromotionInput({
|
|
|
116
105
|
}
|
|
117
106
|
})
|
|
118
107
|
})]
|
|
119
|
-
}), /* @__PURE__ */(0, _jsxRuntime.
|
|
108
|
+
}), isAmountLoading ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Skeleton, {
|
|
109
|
+
variant: "text",
|
|
110
|
+
width: 80,
|
|
111
|
+
height: 22
|
|
112
|
+
}) : /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, {
|
|
120
113
|
sx: {
|
|
121
114
|
color: "text.primary",
|
|
122
115
|
fontWeight: 600,
|
|
@@ -9,7 +9,9 @@ interface CustomerInfoCardProps {
|
|
|
9
9
|
values: Record<string, any>;
|
|
10
10
|
onChange: (field: string, value: string | boolean | Record<string, string>) => void;
|
|
11
11
|
errors: Partial<Record<string, string>>;
|
|
12
|
+
checkValid: () => Promise<boolean>;
|
|
12
13
|
validateField: (field: string) => Promise<void>;
|
|
14
|
+
prefetched: boolean;
|
|
13
15
|
};
|
|
14
16
|
isLoggedIn: boolean;
|
|
15
17
|
}
|
|
@@ -31,16 +31,22 @@ function CustomerInfoCard({
|
|
|
31
31
|
t
|
|
32
32
|
} = (0, _context.useLocaleContext)();
|
|
33
33
|
const labels = fieldLabelMap(t);
|
|
34
|
-
const
|
|
35
|
-
const [
|
|
36
|
-
const
|
|
34
|
+
const [showEditForm, setShowEditForm] = (0, _react.useState)(false);
|
|
35
|
+
const [ready, setReady] = (0, _react.useState)(false);
|
|
36
|
+
const checkedRef = (0, _react.useRef)(false);
|
|
37
37
|
(0, _react.useEffect)(() => {
|
|
38
|
-
if (
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
38
|
+
if (checkedRef.current) return;
|
|
39
|
+
if (!form.prefetched && !form.values.customer_name && !form.values.customer_email) return;
|
|
40
|
+
checkedRef.current = true;
|
|
41
|
+
form.checkValid().then(valid => {
|
|
42
|
+
setShowEditForm(!valid);
|
|
43
|
+
setReady(true);
|
|
44
|
+
});
|
|
45
|
+
}, [form.prefetched]);
|
|
46
|
+
const handleChange = (0, _react.useCallback)((field, value) => form.onChange(field, value), [form.onChange]
|
|
47
|
+
// eslint-disable-line react-hooks/exhaustive-deps
|
|
48
|
+
);
|
|
49
|
+
if (!isLoggedIn || !ready) return null;
|
|
44
50
|
if (!showEditForm) {
|
|
45
51
|
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
|
|
46
52
|
sx: {
|
|
@@ -177,8 +183,8 @@ function CustomerInfoCard({
|
|
|
177
183
|
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_phoneField.default, {
|
|
178
184
|
value: value || "",
|
|
179
185
|
country: form.values.billing_address?.country || "",
|
|
180
|
-
onChange: phone =>
|
|
181
|
-
onCountryChange: c =>
|
|
186
|
+
onChange: phone => handleChange("customer_phone", phone),
|
|
187
|
+
onCountryChange: c => handleChange("billing_address.country", c),
|
|
182
188
|
onBlur: () => form.validateField(name),
|
|
183
189
|
label,
|
|
184
190
|
error: form.errors[name]
|
|
@@ -199,7 +205,7 @@ function CustomerInfoCard({
|
|
|
199
205
|
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.InputBase, {
|
|
200
206
|
fullWidth: true,
|
|
201
207
|
value: value || "",
|
|
202
|
-
onChange: e =>
|
|
208
|
+
onChange: e => handleChange(name, e.target.value),
|
|
203
209
|
onBlur: () => form.validateField(name),
|
|
204
210
|
startAdornment: isPostalCode ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.InputAdornment, {
|
|
205
211
|
position: "start",
|
|
@@ -209,7 +215,7 @@ function CustomerInfoCard({
|
|
|
209
215
|
},
|
|
210
216
|
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_countrySelect.default, {
|
|
211
217
|
value: form.values.billing_address?.country || "",
|
|
212
|
-
onChange: v =>
|
|
218
|
+
onChange: v => handleChange("billing_address.country", v),
|
|
213
219
|
sx: {
|
|
214
220
|
".MuiOutlinedInput-notchedOutline": {
|
|
215
221
|
borderColor: "transparent !important"
|
|
@@ -21,7 +21,7 @@ function StatusFeedback({
|
|
|
21
21
|
if (status === prevStatusRef.current) return;
|
|
22
22
|
prevStatusRef.current = status;
|
|
23
23
|
if (status === "failed" && context?.type === "error") {
|
|
24
|
-
if (context.code === "CUSTOMER_LIMITED") return;
|
|
24
|
+
if (context.code === "CUSTOMER_LIMITED" || context.code === "STOP_ACCEPTING_ORDERS") return;
|
|
25
25
|
_Toast.default.error(context.message || "Payment failed");
|
|
26
26
|
onReset();
|
|
27
27
|
}
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
module.exports = SubmitButton;
|
|
7
7
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
8
8
|
var _material = require("@mui/material");
|
|
9
|
+
var _format = require("../../utils/format");
|
|
9
10
|
function SubmitButton({
|
|
10
11
|
canSubmit,
|
|
11
12
|
isProcessing,
|
|
@@ -28,7 +29,8 @@ function SubmitButton({
|
|
|
28
29
|
py: 1.5,
|
|
29
30
|
fontSize: "1.3rem",
|
|
30
31
|
fontWeight: 600,
|
|
31
|
-
textTransform: "none"
|
|
32
|
+
textTransform: "none",
|
|
33
|
+
color: theme => (0, _format.primaryContrastColor)(theme)
|
|
32
34
|
},
|
|
33
35
|
children: isProcessing ? processingLabel : label
|
|
34
36
|
});
|
|
@@ -47,7 +47,23 @@ const fadeIn = {
|
|
|
47
47
|
md: "fadeIn 0.6s cubic-bezier(0.16, 1, 0.3, 1) 0.15s both"
|
|
48
48
|
}
|
|
49
49
|
};
|
|
50
|
-
const
|
|
50
|
+
const isSafari = typeof navigator !== "undefined" && /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent);
|
|
51
|
+
const slideInFromRight = isSafari ? {
|
|
52
|
+
"@keyframes panelFadeIn": {
|
|
53
|
+
from: {
|
|
54
|
+
opacity: 0,
|
|
55
|
+
transform: "translateX(24px)"
|
|
56
|
+
},
|
|
57
|
+
to: {
|
|
58
|
+
opacity: 1,
|
|
59
|
+
transform: "none"
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
animation: {
|
|
63
|
+
xs: "none",
|
|
64
|
+
md: "panelFadeIn 0.5s cubic-bezier(0.16, 1, 0.3, 1) both"
|
|
65
|
+
}
|
|
66
|
+
} : {
|
|
51
67
|
"@keyframes slideInRight": {
|
|
52
68
|
from: {
|
|
53
69
|
transform: "translateX(100%)"
|
|
@@ -117,6 +133,7 @@ function CheckoutLayout({
|
|
|
117
133
|
children: [!hideLeft && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
118
134
|
sx: {
|
|
119
135
|
flex: 1,
|
|
136
|
+
minWidth: 0,
|
|
120
137
|
bgcolor: t => t.palette.mode === "dark" ? "background.default" : "#f8faff",
|
|
121
138
|
p: {
|
|
122
139
|
xs: 3,
|
|
@@ -205,9 +222,12 @@ function CheckoutLayout({
|
|
|
205
222
|
}
|
|
206
223
|
}), !hideLeft && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
207
224
|
sx: {
|
|
225
|
+
flex: {
|
|
226
|
+
xs: "none",
|
|
227
|
+
md: "0 0 50%"
|
|
228
|
+
},
|
|
208
229
|
width: {
|
|
209
|
-
xs: "100%"
|
|
210
|
-
md: "50%"
|
|
230
|
+
xs: "100%"
|
|
211
231
|
},
|
|
212
232
|
height: {
|
|
213
233
|
xs: "auto",
|
|
@@ -246,9 +266,12 @@ function CheckoutLayout({
|
|
|
246
266
|
})
|
|
247
267
|
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
248
268
|
sx: {
|
|
269
|
+
flex: hideLeft ? "none" : {
|
|
270
|
+
xs: "none",
|
|
271
|
+
md: "0 0 50%"
|
|
272
|
+
},
|
|
249
273
|
width: hideLeft ? "100%" : {
|
|
250
|
-
xs: "100%"
|
|
251
|
-
md: "50%"
|
|
274
|
+
xs: "100%"
|
|
252
275
|
},
|
|
253
276
|
height: hideLeft ? "100vh" : {
|
|
254
277
|
xs: "auto",
|
|
@@ -61,6 +61,9 @@ function CompositePanel() {
|
|
|
61
61
|
const canUpsell = nonCrossSellItems.length <= 1;
|
|
62
62
|
const hasTopUpsell = canUpsell && !!upsellPrimaryItem && ["subscription", "setup"].includes(mode);
|
|
63
63
|
const isUpselled = !!upsellPrimaryItem?.upsell_price;
|
|
64
|
+
const [upsellSwitching, setUpsellSwitching] = (0, _react.useState)(false);
|
|
65
|
+
const [pendingUpsell, setPendingUpsell] = (0, _react.useState)(null);
|
|
66
|
+
const visualIsUpselled = pendingUpsell !== null ? pendingUpsell : isUpselled;
|
|
64
67
|
const currentInterval = hasTopUpsell ? upsellPrimaryItem.price?.recurring?.interval : null;
|
|
65
68
|
const upsellInterval = hasTopUpsell ? upsellTarget?.recurring?.interval : null;
|
|
66
69
|
let upsellSavings = 0;
|
|
@@ -88,7 +91,7 @@ function CompositePanel() {
|
|
|
88
91
|
const isMultiItem = lineItems.items.length > 1;
|
|
89
92
|
const activeSx = {
|
|
90
93
|
bgcolor: "primary.main",
|
|
91
|
-
color:
|
|
94
|
+
color: theme => (0, _format.primaryContrastColor)(theme),
|
|
92
95
|
boxShadow: "0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -2px rgba(0,0,0,0.1)"
|
|
93
96
|
};
|
|
94
97
|
const inactiveSx = {
|
|
@@ -277,15 +280,21 @@ function CompositePanel() {
|
|
|
277
280
|
},
|
|
278
281
|
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
279
282
|
onClick: async () => {
|
|
280
|
-
if (isUpselled) {
|
|
283
|
+
if (isUpselled && !upsellSwitching) {
|
|
284
|
+
setPendingUpsell(false);
|
|
285
|
+
setUpsellSwitching(true);
|
|
281
286
|
try {
|
|
282
287
|
await lineItems.downsell(upsellPrimaryItem.upsell_price?.id || upsellPrimaryItem.price_id);
|
|
283
288
|
} catch (err) {
|
|
289
|
+
setPendingUpsell(null);
|
|
284
290
|
_Toast.default.error(err?.response?.data?.error || err?.message || "Failed");
|
|
291
|
+
} finally {
|
|
292
|
+
setUpsellSwitching(false);
|
|
293
|
+
setPendingUpsell(null);
|
|
285
294
|
}
|
|
286
295
|
}
|
|
287
296
|
},
|
|
288
|
-
sx: capsuleBtnSx(!
|
|
297
|
+
sx: capsuleBtnSx(!visualIsUpselled),
|
|
289
298
|
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
290
299
|
component: "span",
|
|
291
300
|
sx: {
|
|
@@ -298,15 +307,21 @@ function CompositePanel() {
|
|
|
298
307
|
})
|
|
299
308
|
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
300
309
|
onClick: async () => {
|
|
301
|
-
if (!isUpselled) {
|
|
310
|
+
if (!isUpselled && !upsellSwitching) {
|
|
311
|
+
setPendingUpsell(true);
|
|
312
|
+
setUpsellSwitching(true);
|
|
302
313
|
try {
|
|
303
314
|
await lineItems.upsell(upsellPrimaryItem.price_id, upsellTarget.id);
|
|
304
315
|
} catch (err) {
|
|
316
|
+
setPendingUpsell(null);
|
|
305
317
|
_Toast.default.error(err?.response?.data?.error || err?.message || "Failed");
|
|
318
|
+
} finally {
|
|
319
|
+
setUpsellSwitching(false);
|
|
320
|
+
setPendingUpsell(null);
|
|
306
321
|
}
|
|
307
322
|
}
|
|
308
323
|
},
|
|
309
|
-
sx: capsuleBtnSx(
|
|
324
|
+
sx: capsuleBtnSx(visualIsUpselled),
|
|
310
325
|
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
311
326
|
component: "span",
|
|
312
327
|
sx: {
|
|
@@ -561,7 +561,9 @@ function PaymentPanel() {
|
|
|
561
561
|
remove: promotion.remove
|
|
562
562
|
},
|
|
563
563
|
discounts,
|
|
564
|
-
discountAmount: pricing.discount
|
|
564
|
+
discountAmount: pricing.discount,
|
|
565
|
+
currency,
|
|
566
|
+
isAmountLoading
|
|
565
567
|
})]
|
|
566
568
|
}), (() => {
|
|
567
569
|
const totalStr = pricing.total || "0";
|
|
@@ -710,7 +712,7 @@ function PaymentPanel() {
|
|
|
710
712
|
})]
|
|
711
713
|
})]
|
|
712
714
|
});
|
|
713
|
-
})(), /* @__PURE__ */(0, _jsxRuntime.
|
|
715
|
+
})(), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Button, {
|
|
714
716
|
variant: "contained",
|
|
715
717
|
size: "large",
|
|
716
718
|
fullWidth: true,
|
|
@@ -720,15 +722,51 @@ function PaymentPanel() {
|
|
|
720
722
|
size: 20,
|
|
721
723
|
color: "inherit"
|
|
722
724
|
}) : null,
|
|
723
|
-
endIcon: !isProcessing ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_ArrowForward.default, {}) : void 0,
|
|
724
725
|
sx: {
|
|
725
726
|
py: 1.5,
|
|
726
727
|
fontSize: "1.1rem",
|
|
727
728
|
fontWeight: 600,
|
|
728
729
|
textTransform: "none",
|
|
729
|
-
borderRadius: "12px"
|
|
730
|
+
borderRadius: "12px",
|
|
731
|
+
color: theme => (0, _format.primaryContrastColor)(theme),
|
|
732
|
+
position: "relative",
|
|
733
|
+
overflow: "hidden",
|
|
734
|
+
"&:hover": {
|
|
735
|
+
bgcolor: "primary.main"
|
|
736
|
+
},
|
|
737
|
+
"&:hover .arrow-icon": {
|
|
738
|
+
transform: "translateX(4px)"
|
|
739
|
+
},
|
|
740
|
+
"&:hover .shine-layer": {
|
|
741
|
+
transform: "translateX(100%)"
|
|
742
|
+
}
|
|
730
743
|
},
|
|
731
|
-
children:
|
|
744
|
+
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
745
|
+
component: "span",
|
|
746
|
+
sx: {
|
|
747
|
+
position: "relative",
|
|
748
|
+
zIndex: 1
|
|
749
|
+
},
|
|
750
|
+
children: isProcessing ? `${t("payment.checkout.processing")}...` : buttonLabel
|
|
751
|
+
}), !isProcessing && /* @__PURE__ */(0, _jsxRuntime.jsx)(_ArrowForward.default, {
|
|
752
|
+
className: "arrow-icon",
|
|
753
|
+
sx: {
|
|
754
|
+
ml: 1,
|
|
755
|
+
position: "relative",
|
|
756
|
+
zIndex: 1,
|
|
757
|
+
transition: "transform 0.2s ease"
|
|
758
|
+
}
|
|
759
|
+
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
760
|
+
className: "shine-layer",
|
|
761
|
+
sx: {
|
|
762
|
+
position: "absolute",
|
|
763
|
+
inset: 0,
|
|
764
|
+
background: "linear-gradient(90deg, transparent, rgba(255,255,255,0.12), transparent)",
|
|
765
|
+
transform: "translateX(-100%)",
|
|
766
|
+
transition: "transform 0.7s ease",
|
|
767
|
+
pointerEvents: "none"
|
|
768
|
+
}
|
|
769
|
+
})]
|
|
732
770
|
}), isMobile && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
733
771
|
direction: "row",
|
|
734
772
|
alignItems: "center",
|
|
@@ -818,7 +856,8 @@ function PaymentPanel() {
|
|
|
818
856
|
remove: promotion.remove
|
|
819
857
|
},
|
|
820
858
|
discounts,
|
|
821
|
-
discountAmount: pricing.discount
|
|
859
|
+
discountAmount: pricing.discount,
|
|
860
|
+
currency
|
|
822
861
|
})]
|
|
823
862
|
}), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
|
|
824
863
|
sx: {
|
|
@@ -828,7 +867,7 @@ function PaymentPanel() {
|
|
|
828
867
|
mode,
|
|
829
868
|
subscription,
|
|
830
869
|
staking: pricing.staking,
|
|
831
|
-
appName: session?.
|
|
870
|
+
appName: (0, _util.getStatementDescriptor)(session?.line_items || [])
|
|
832
871
|
}), !isMobile && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
833
872
|
direction: "row",
|
|
834
873
|
alignItems: "center",
|