@blocklet/payment-react 1.20.10 → 1.20.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/components/promotion-code.d.ts +19 -0
- package/es/components/promotion-code.js +153 -0
- package/es/contexts/payment.d.ts +8 -0
- package/es/contexts/payment.js +10 -1
- package/es/index.d.ts +2 -1
- package/es/index.js +3 -1
- package/es/libs/util.d.ts +5 -1
- package/es/libs/util.js +23 -0
- package/es/locales/en.js +40 -15
- package/es/locales/zh.js +29 -0
- package/es/payment/form/index.js +7 -1
- package/es/payment/index.js +19 -0
- package/es/payment/product-item.js +32 -3
- package/es/payment/summary.d.ts +5 -2
- package/es/payment/summary.js +193 -16
- package/lib/components/promotion-code.d.ts +19 -0
- package/lib/components/promotion-code.js +155 -0
- package/lib/contexts/payment.d.ts +8 -0
- package/lib/contexts/payment.js +13 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.js +8 -0
- package/lib/libs/util.d.ts +5 -1
- package/lib/libs/util.js +29 -0
- package/lib/locales/en.js +40 -15
- package/lib/locales/zh.js +29 -0
- package/lib/payment/form/index.js +8 -1
- package/lib/payment/index.js +23 -0
- package/lib/payment/product-item.js +46 -0
- package/lib/payment/summary.d.ts +5 -2
- package/lib/payment/summary.js +153 -11
- package/package.json +9 -9
- package/src/components/promotion-code.tsx +184 -0
- package/src/contexts/payment.tsx +15 -0
- package/src/index.ts +2 -0
- package/src/libs/util.ts +35 -0
- package/src/locales/en.tsx +40 -15
- package/src/locales/zh.tsx +29 -0
- package/src/payment/form/index.tsx +10 -1
- package/src/payment/index.tsx +22 -0
- package/src/payment/product-item.tsx +37 -2
- package/src/payment/summary.tsx +201 -16
package/es/payment/summary.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
|
|
3
|
-
import { HelpOutline } from "@mui/icons-material";
|
|
4
|
-
import { Box, Divider, Fade, Grow, Stack, Tooltip, Typography, Collapse, IconButton } from "@mui/material";
|
|
3
|
+
import { HelpOutline, Close, LocalOffer } from "@mui/icons-material";
|
|
4
|
+
import { Box, Divider, Fade, Grow, Stack, Tooltip, Typography, Collapse, IconButton, Button } from "@mui/material";
|
|
5
5
|
import { BN, fromTokenToUnit, fromUnitToToken } from "@ocap/util";
|
|
6
6
|
import { useRequest, useSetState } from "ahooks";
|
|
7
7
|
import noop from "lodash/noop";
|
|
@@ -10,7 +10,14 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
|
|
10
10
|
import { styled } from "@mui/material/styles";
|
|
11
11
|
import Status from "../components/status.js";
|
|
12
12
|
import api from "../libs/api.js";
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
formatAmount,
|
|
15
|
+
formatCheckoutHeadlines,
|
|
16
|
+
getPriceUintAmountByCurrency,
|
|
17
|
+
formatCouponTerms,
|
|
18
|
+
formatNumber,
|
|
19
|
+
findCurrency
|
|
20
|
+
} from "../libs/util.js";
|
|
14
21
|
import PaymentAmount from "./amount.js";
|
|
15
22
|
import ProductDonation from "./product-donation.js";
|
|
16
23
|
import ProductItem from "./product-item.js";
|
|
@@ -18,6 +25,7 @@ import Livemode from "../components/livemode.js";
|
|
|
18
25
|
import { usePaymentContext } from "../contexts/payment.js";
|
|
19
26
|
import { useMobile } from "../hooks/mobile.js";
|
|
20
27
|
import LoadingButton from "../components/loading-button.js";
|
|
28
|
+
import PromotionCode from "../components/promotion-code.js";
|
|
21
29
|
const ExpandMore = styled((props) => {
|
|
22
30
|
const { expand, ...other } = props;
|
|
23
31
|
return /* @__PURE__ */ jsx(IconButton, { ...other });
|
|
@@ -84,21 +92,58 @@ export default function PaymentSummary({
|
|
|
84
92
|
action = "",
|
|
85
93
|
trialEnd = 0,
|
|
86
94
|
completed = false,
|
|
95
|
+
checkoutSession = void 0,
|
|
96
|
+
paymentMethods = [],
|
|
97
|
+
onPromotionUpdate = noop,
|
|
87
98
|
showFeatures = false,
|
|
88
99
|
...rest
|
|
89
100
|
}) {
|
|
90
101
|
const { t, locale } = useLocaleContext();
|
|
91
102
|
const { isMobile } = useMobile();
|
|
92
|
-
const settings = usePaymentContext();
|
|
103
|
+
const { paymentState, ...settings } = usePaymentContext();
|
|
93
104
|
const [state, setState] = useSetState({ loading: false, shake: false, expanded: items?.length < 3 });
|
|
94
105
|
const { data, runAsync } = useRequest(
|
|
95
106
|
() => checkoutSessionId ? fetchCrossSell(checkoutSessionId) : Promise.resolve(null)
|
|
96
107
|
);
|
|
97
|
-
const
|
|
98
|
-
const
|
|
108
|
+
const sessionDiscounts = checkoutSession?.discounts || [];
|
|
109
|
+
const allowPromotionCodes = !!checkoutSession?.allow_promotion_codes;
|
|
110
|
+
const hasDiscounts = sessionDiscounts?.length > 0;
|
|
111
|
+
const discountCurrency = paymentMethods && checkoutSession ? findCurrency(
|
|
112
|
+
paymentMethods,
|
|
113
|
+
hasDiscounts ? checkoutSession?.currency_id || currency.id : currency.id
|
|
114
|
+
) || settings.settings?.baseCurrency : currency;
|
|
115
|
+
const headlines = formatCheckoutHeadlines(items, discountCurrency, { trialEnd, trialInDays }, locale);
|
|
116
|
+
const staking = showStaking ? getStakingSetup(items, discountCurrency, billingThreshold) : "0";
|
|
117
|
+
const getAppliedPromotionCodes = () => {
|
|
118
|
+
if (!sessionDiscounts?.length) return [];
|
|
119
|
+
return sessionDiscounts.map((discount) => ({
|
|
120
|
+
id: discount.promotion_code || discount.coupon,
|
|
121
|
+
code: discount.verification_data?.code || "APPLIED",
|
|
122
|
+
discount_amount: discount.discount_amount
|
|
123
|
+
}));
|
|
124
|
+
};
|
|
125
|
+
const handlePromotionUpdate = () => {
|
|
126
|
+
onPromotionUpdate?.();
|
|
127
|
+
};
|
|
128
|
+
const handleRemovePromotion = async (sessionId) => {
|
|
129
|
+
if (paymentState.paying || paymentState.stripePaying) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
try {
|
|
133
|
+
await api.delete(`/api/checkout-sessions/${sessionId}/remove-promotion`);
|
|
134
|
+
onPromotionUpdate?.();
|
|
135
|
+
} catch (err) {
|
|
136
|
+
console.error("Failed to remove promotion code:", err);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
const discountAmount = new BN(checkoutSession?.total_details?.amount_discount || "0");
|
|
140
|
+
const subtotalAmount = fromUnitToToken(
|
|
141
|
+
new BN(fromTokenToUnit(headlines.actualAmount, discountCurrency?.decimal)).add(new BN(staking)).toString(),
|
|
142
|
+
discountCurrency?.decimal
|
|
143
|
+
);
|
|
99
144
|
const totalAmount = fromUnitToToken(
|
|
100
|
-
new BN(fromTokenToUnit(
|
|
101
|
-
|
|
145
|
+
new BN(fromTokenToUnit(subtotalAmount, discountCurrency?.decimal)).sub(discountAmount).toString(),
|
|
146
|
+
discountCurrency?.decimal
|
|
102
147
|
);
|
|
103
148
|
useBus(
|
|
104
149
|
"error.REQUIRE_CROSS_SELL",
|
|
@@ -160,9 +205,9 @@ export default function PaymentSummary({
|
|
|
160
205
|
item: x,
|
|
161
206
|
settings: donationSettings,
|
|
162
207
|
onChange: onChangeAmount,
|
|
163
|
-
currency
|
|
208
|
+
currency: discountCurrency
|
|
164
209
|
},
|
|
165
|
-
`${x.price_id}-${
|
|
210
|
+
`${x.price_id}-${discountCurrency.id}`
|
|
166
211
|
) : /* @__PURE__ */ jsx(
|
|
167
212
|
ProductItem,
|
|
168
213
|
{
|
|
@@ -170,7 +215,7 @@ export default function PaymentSummary({
|
|
|
170
215
|
items,
|
|
171
216
|
trialInDays,
|
|
172
217
|
trialEnd,
|
|
173
|
-
currency,
|
|
218
|
+
currency: discountCurrency,
|
|
174
219
|
onUpsell: handleUpsell,
|
|
175
220
|
onDownsell: handleDownsell,
|
|
176
221
|
adjustableQuantity: x.adjustable_quantity,
|
|
@@ -205,7 +250,7 @@ export default function PaymentSummary({
|
|
|
205
250
|
}
|
|
206
251
|
)
|
|
207
252
|
},
|
|
208
|
-
`${x.price_id}-${
|
|
253
|
+
`${x.price_id}-${discountCurrency.id}`
|
|
209
254
|
)
|
|
210
255
|
) }),
|
|
211
256
|
data && items.some((x) => x.price_id === data.id) === false && /* @__PURE__ */ jsx(Grow, { in: true, children: /* @__PURE__ */ jsx(
|
|
@@ -220,7 +265,7 @@ export default function PaymentSummary({
|
|
|
220
265
|
item: { quantity: 1, price: data, price_id: data.id, cross_sell: true },
|
|
221
266
|
items,
|
|
222
267
|
trialInDays,
|
|
223
|
-
currency,
|
|
268
|
+
currency: discountCurrency,
|
|
224
269
|
trialEnd,
|
|
225
270
|
onUpsell: noop,
|
|
226
271
|
onDownsell: noop,
|
|
@@ -362,14 +407,146 @@ export default function PaymentSummary({
|
|
|
362
407
|
}
|
|
363
408
|
),
|
|
364
409
|
/* @__PURE__ */ jsxs(Typography, { children: [
|
|
365
|
-
formatAmount(staking,
|
|
410
|
+
formatAmount(staking, discountCurrency.decimal),
|
|
366
411
|
" ",
|
|
367
|
-
|
|
412
|
+
discountCurrency.symbol
|
|
368
413
|
] })
|
|
369
414
|
]
|
|
370
415
|
}
|
|
371
416
|
)
|
|
372
417
|
] }),
|
|
418
|
+
(allowPromotionCodes || hasDiscounts) && /* @__PURE__ */ jsxs(
|
|
419
|
+
Stack,
|
|
420
|
+
{
|
|
421
|
+
direction: "row",
|
|
422
|
+
spacing: 1,
|
|
423
|
+
sx: {
|
|
424
|
+
justifyContent: "space-between",
|
|
425
|
+
alignItems: "center",
|
|
426
|
+
...staking > 0 && {
|
|
427
|
+
borderTop: "1px solid",
|
|
428
|
+
borderColor: "divider",
|
|
429
|
+
pt: 1,
|
|
430
|
+
mt: 1
|
|
431
|
+
}
|
|
432
|
+
},
|
|
433
|
+
children: [
|
|
434
|
+
/* @__PURE__ */ jsx(Typography, { className: "base-label", children: t("common.subtotal") }),
|
|
435
|
+
/* @__PURE__ */ jsxs(Typography, { children: [
|
|
436
|
+
formatNumber(subtotalAmount),
|
|
437
|
+
" ",
|
|
438
|
+
discountCurrency.symbol
|
|
439
|
+
] })
|
|
440
|
+
]
|
|
441
|
+
}
|
|
442
|
+
),
|
|
443
|
+
allowPromotionCodes && !hasDiscounts && /* @__PURE__ */ jsx(Box, { sx: { mt: 1 }, children: /* @__PURE__ */ jsx(
|
|
444
|
+
PromotionCode,
|
|
445
|
+
{
|
|
446
|
+
checkoutSessionId: checkoutSession.id,
|
|
447
|
+
initialAppliedCodes: getAppliedPromotionCodes(),
|
|
448
|
+
disabled: completed,
|
|
449
|
+
onUpdate: handlePromotionUpdate,
|
|
450
|
+
currencyId: currency.id
|
|
451
|
+
}
|
|
452
|
+
) }),
|
|
453
|
+
hasDiscounts && /* @__PURE__ */ jsx(
|
|
454
|
+
Box,
|
|
455
|
+
{
|
|
456
|
+
sx: {
|
|
457
|
+
py: 1.5
|
|
458
|
+
},
|
|
459
|
+
children: sessionDiscounts.map((discount) => {
|
|
460
|
+
const promotionCodeInfo = discount.promotion_code_details;
|
|
461
|
+
const couponInfo = discount.coupon_details;
|
|
462
|
+
const discountDescription = couponInfo ? formatCouponTerms(couponInfo, discountCurrency, locale) : "";
|
|
463
|
+
const notSupported = discountDescription === t("payment.checkout.coupon.noDiscount");
|
|
464
|
+
return /* @__PURE__ */ jsxs(Stack, { children: [
|
|
465
|
+
/* @__PURE__ */ jsxs(
|
|
466
|
+
Stack,
|
|
467
|
+
{
|
|
468
|
+
direction: "row",
|
|
469
|
+
spacing: 1,
|
|
470
|
+
sx: {
|
|
471
|
+
justifyContent: "space-between",
|
|
472
|
+
alignItems: "center"
|
|
473
|
+
},
|
|
474
|
+
children: [
|
|
475
|
+
/* @__PURE__ */ jsxs(
|
|
476
|
+
Stack,
|
|
477
|
+
{
|
|
478
|
+
direction: "row",
|
|
479
|
+
spacing: 1,
|
|
480
|
+
sx: {
|
|
481
|
+
alignItems: "center",
|
|
482
|
+
backgroundColor: "grey.100",
|
|
483
|
+
width: "fit-content",
|
|
484
|
+
px: 1,
|
|
485
|
+
py: 0.5,
|
|
486
|
+
borderRadius: 1
|
|
487
|
+
},
|
|
488
|
+
children: [
|
|
489
|
+
/* @__PURE__ */ jsxs(
|
|
490
|
+
Typography,
|
|
491
|
+
{
|
|
492
|
+
sx: {
|
|
493
|
+
fontWeight: "medium",
|
|
494
|
+
fontSize: "small",
|
|
495
|
+
display: "flex",
|
|
496
|
+
alignItems: "center",
|
|
497
|
+
gap: 0.5
|
|
498
|
+
},
|
|
499
|
+
children: [
|
|
500
|
+
/* @__PURE__ */ jsx(LocalOffer, { sx: { color: "warning.main", fontSize: "small" } }),
|
|
501
|
+
promotionCodeInfo?.code || discount.verification_data?.code || t("payment.checkout.discount")
|
|
502
|
+
]
|
|
503
|
+
}
|
|
504
|
+
),
|
|
505
|
+
!completed && /* @__PURE__ */ jsx(
|
|
506
|
+
Button,
|
|
507
|
+
{
|
|
508
|
+
size: "small",
|
|
509
|
+
disabled: paymentState.paying || paymentState.stripePaying,
|
|
510
|
+
onClick: () => handleRemovePromotion(checkoutSessionId),
|
|
511
|
+
sx: {
|
|
512
|
+
minWidth: "auto",
|
|
513
|
+
width: 16,
|
|
514
|
+
height: 16,
|
|
515
|
+
color: "text.secondary",
|
|
516
|
+
"&.Mui-disabled": {
|
|
517
|
+
color: "text.disabled"
|
|
518
|
+
}
|
|
519
|
+
},
|
|
520
|
+
children: /* @__PURE__ */ jsx(Close, { sx: { fontSize: 14 } })
|
|
521
|
+
}
|
|
522
|
+
)
|
|
523
|
+
]
|
|
524
|
+
}
|
|
525
|
+
),
|
|
526
|
+
/* @__PURE__ */ jsxs(Typography, { sx: { color: "text.secondary" }, children: [
|
|
527
|
+
"-",
|
|
528
|
+
formatAmount(discount.discount_amount || "0", discountCurrency.decimal),
|
|
529
|
+
" ",
|
|
530
|
+
discountCurrency.symbol
|
|
531
|
+
] })
|
|
532
|
+
]
|
|
533
|
+
}
|
|
534
|
+
),
|
|
535
|
+
discountDescription && /* @__PURE__ */ jsx(
|
|
536
|
+
Typography,
|
|
537
|
+
{
|
|
538
|
+
sx: {
|
|
539
|
+
fontSize: "small",
|
|
540
|
+
color: notSupported ? "error.main" : "text.secondary",
|
|
541
|
+
mt: 0.5
|
|
542
|
+
},
|
|
543
|
+
children: discountDescription
|
|
544
|
+
}
|
|
545
|
+
)
|
|
546
|
+
] }, discount.promotion_code || discount.coupon || `discount-${discount.discount_amount}`);
|
|
547
|
+
})
|
|
548
|
+
}
|
|
549
|
+
),
|
|
373
550
|
/* @__PURE__ */ jsxs(
|
|
374
551
|
Stack,
|
|
375
552
|
{
|
|
@@ -385,7 +562,7 @@ export default function PaymentSummary({
|
|
|
385
562
|
t("common.total"),
|
|
386
563
|
" "
|
|
387
564
|
] }),
|
|
388
|
-
/* @__PURE__ */ jsx(PaymentAmount, { amount: `${totalAmount} ${
|
|
565
|
+
/* @__PURE__ */ jsx(PaymentAmount, { amount: `${totalAmount} ${discountCurrency.symbol}`, sx: { fontSize: "16px" } })
|
|
389
566
|
]
|
|
390
567
|
}
|
|
391
568
|
),
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface AppliedPromoCode {
|
|
2
|
+
id: string;
|
|
3
|
+
code: string;
|
|
4
|
+
discount_amount?: string;
|
|
5
|
+
}
|
|
6
|
+
interface PromotionCodeProps {
|
|
7
|
+
checkoutSessionId: string;
|
|
8
|
+
initialAppliedCodes?: AppliedPromoCode[];
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
className?: string;
|
|
11
|
+
placeholder?: string;
|
|
12
|
+
currencyId: string;
|
|
13
|
+
onUpdate?: (data: {
|
|
14
|
+
appliedCodes: AppliedPromoCode[];
|
|
15
|
+
discountAmount: string;
|
|
16
|
+
}) => void;
|
|
17
|
+
}
|
|
18
|
+
export default function PromotionCode({ checkoutSessionId, initialAppliedCodes, disabled, className, placeholder, onUpdate, currencyId, }: PromotionCodeProps): import("react").JSX.Element;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
module.exports = PromotionCode;
|
|
7
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
8
|
+
var _context = require("@arcblock/ux/lib/Locale/context");
|
|
9
|
+
var _material = require("@mui/material");
|
|
10
|
+
var _iconsMaterial = require("@mui/icons-material");
|
|
11
|
+
var _react = require("react");
|
|
12
|
+
var _loadingButton = _interopRequireDefault(require("./loading-button"));
|
|
13
|
+
var _api = _interopRequireDefault(require("../libs/api"));
|
|
14
|
+
var _payment = require("../contexts/payment");
|
|
15
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
16
|
+
function PromotionCode({
|
|
17
|
+
checkoutSessionId,
|
|
18
|
+
initialAppliedCodes = [],
|
|
19
|
+
disabled = false,
|
|
20
|
+
className = "",
|
|
21
|
+
placeholder = "",
|
|
22
|
+
onUpdate = void 0,
|
|
23
|
+
currencyId
|
|
24
|
+
}) {
|
|
25
|
+
const {
|
|
26
|
+
t
|
|
27
|
+
} = (0, _context.useLocaleContext)();
|
|
28
|
+
const [showInput, setShowInput] = (0, _react.useState)(false);
|
|
29
|
+
const [code, setCode] = (0, _react.useState)("");
|
|
30
|
+
const [error, setError] = (0, _react.useState)("");
|
|
31
|
+
const [applying, setApplying] = (0, _react.useState)(false);
|
|
32
|
+
const [appliedCodes, setAppliedCodes] = (0, _react.useState)(initialAppliedCodes);
|
|
33
|
+
const {
|
|
34
|
+
session,
|
|
35
|
+
paymentState
|
|
36
|
+
} = (0, _payment.usePaymentContext)();
|
|
37
|
+
const handleLoginCheck = () => {
|
|
38
|
+
if (!session.user) {
|
|
39
|
+
session?.login(() => {
|
|
40
|
+
handleApply();
|
|
41
|
+
});
|
|
42
|
+
} else {
|
|
43
|
+
handleApply();
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const handleApply = async () => {
|
|
47
|
+
if (!code.trim()) return;
|
|
48
|
+
if (paymentState.paying || paymentState.stripePaying) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
setApplying(true);
|
|
52
|
+
setError("");
|
|
53
|
+
try {
|
|
54
|
+
const response = await _api.default.post(`/api/checkout-sessions/${checkoutSessionId}/apply-promotion`, {
|
|
55
|
+
promotion_code: code.trim(),
|
|
56
|
+
currency_id: currencyId
|
|
57
|
+
});
|
|
58
|
+
const discounts = response.data.discounts || [];
|
|
59
|
+
const appliedDiscount = discounts[0];
|
|
60
|
+
if (appliedDiscount) {
|
|
61
|
+
const newCode = {
|
|
62
|
+
id: appliedDiscount.promotion_code || appliedDiscount.coupon,
|
|
63
|
+
code: code.trim(),
|
|
64
|
+
discount_amount: appliedDiscount.discount_amount
|
|
65
|
+
};
|
|
66
|
+
setAppliedCodes([newCode]);
|
|
67
|
+
setCode("");
|
|
68
|
+
setShowInput(false);
|
|
69
|
+
onUpdate?.({
|
|
70
|
+
appliedCodes: [newCode],
|
|
71
|
+
discountAmount: appliedDiscount.discount_amount
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
} catch (err) {
|
|
75
|
+
const errorMessage = err.response?.data?.error || err.message;
|
|
76
|
+
setError(errorMessage);
|
|
77
|
+
} finally {
|
|
78
|
+
setApplying(false);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
const handleKeyPress = event => {
|
|
82
|
+
if (event.key === "Enter" && !applying && code.trim()) {
|
|
83
|
+
handleLoginCheck();
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
const isPaymentInProgress = paymentState.paying || paymentState.stripePaying;
|
|
87
|
+
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
|
|
88
|
+
className,
|
|
89
|
+
children: appliedCodes.length === 0 && !disabled && !isPaymentInProgress && (showInput ? /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
|
|
90
|
+
onBlur: () => {
|
|
91
|
+
if (!code.trim()) {
|
|
92
|
+
setShowInput(false);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.TextField, {
|
|
96
|
+
fullWidth: true,
|
|
97
|
+
value: code,
|
|
98
|
+
onChange: e => setCode(e.target.value),
|
|
99
|
+
onKeyPress: handleKeyPress,
|
|
100
|
+
placeholder: placeholder || t("payment.checkout.promotion.placeholder"),
|
|
101
|
+
variant: "outlined",
|
|
102
|
+
size: "small",
|
|
103
|
+
disabled: applying,
|
|
104
|
+
autoFocus: true,
|
|
105
|
+
slotProps: {
|
|
106
|
+
input: {
|
|
107
|
+
endAdornment: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.InputAdornment, {
|
|
108
|
+
position: "end",
|
|
109
|
+
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_loadingButton.default, {
|
|
110
|
+
size: "small",
|
|
111
|
+
onClick: handleLoginCheck,
|
|
112
|
+
loading: applying,
|
|
113
|
+
disabled: !code.trim(),
|
|
114
|
+
variant: "text",
|
|
115
|
+
sx: {
|
|
116
|
+
color: "primary.main",
|
|
117
|
+
fontSize: "small"
|
|
118
|
+
},
|
|
119
|
+
children: t("payment.checkout.promotion.apply")
|
|
120
|
+
})
|
|
121
|
+
})
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
sx: {
|
|
125
|
+
"& .MuiOutlinedInput-root": {
|
|
126
|
+
pr: 1
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}), error && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Alert, {
|
|
130
|
+
severity: "error",
|
|
131
|
+
sx: {
|
|
132
|
+
my: 1
|
|
133
|
+
},
|
|
134
|
+
children: error
|
|
135
|
+
})]
|
|
136
|
+
}) : /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
|
|
137
|
+
onClick: () => setShowInput(true),
|
|
138
|
+
startIcon: /* @__PURE__ */(0, _jsxRuntime.jsx)(_iconsMaterial.Add, {
|
|
139
|
+
fontSize: "small"
|
|
140
|
+
}),
|
|
141
|
+
variant: "text",
|
|
142
|
+
sx: {
|
|
143
|
+
fontWeight: "normal",
|
|
144
|
+
textTransform: "none",
|
|
145
|
+
justifyContent: "flex-start",
|
|
146
|
+
p: 0,
|
|
147
|
+
"&:hover": {
|
|
148
|
+
backgroundColor: "transparent",
|
|
149
|
+
textDecoration: "underline"
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
children: t("payment.checkout.promotion.add_code")
|
|
153
|
+
}))
|
|
154
|
+
});
|
|
155
|
+
}
|
|
@@ -19,6 +19,14 @@ export type PaymentContextType = {
|
|
|
19
19
|
api: Axios;
|
|
20
20
|
payable: boolean;
|
|
21
21
|
setPayable: (status: boolean) => void;
|
|
22
|
+
paymentState: {
|
|
23
|
+
paying: boolean;
|
|
24
|
+
stripePaying: boolean;
|
|
25
|
+
};
|
|
26
|
+
setPaymentState: (state: Partial<{
|
|
27
|
+
paying: boolean;
|
|
28
|
+
stripePaying: boolean;
|
|
29
|
+
}>) => void;
|
|
22
30
|
};
|
|
23
31
|
export type PaymentContextProps = {
|
|
24
32
|
session: import('@arcblock/did-connect-react/lib/types').SessionContext['session'];
|
package/lib/contexts/payment.js
CHANGED
|
@@ -145,6 +145,16 @@ function PaymentProvider({
|
|
|
145
145
|
}, [session?.user]);
|
|
146
146
|
const prefix = (0, _util.getPrefix)();
|
|
147
147
|
const [payable, setPayable] = (0, _react.useState)(true);
|
|
148
|
+
const [paymentState, setPaymentState] = (0, _react.useState)({
|
|
149
|
+
paying: false,
|
|
150
|
+
stripePaying: false
|
|
151
|
+
});
|
|
152
|
+
const updatePaymentState = state => {
|
|
153
|
+
setPaymentState(prev => ({
|
|
154
|
+
...prev,
|
|
155
|
+
...state
|
|
156
|
+
}));
|
|
157
|
+
};
|
|
148
158
|
if (error) {
|
|
149
159
|
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Alert, {
|
|
150
160
|
severity: "error",
|
|
@@ -167,7 +177,9 @@ function PaymentProvider({
|
|
|
167
177
|
setLivemode,
|
|
168
178
|
api: _api.default,
|
|
169
179
|
payable,
|
|
170
|
-
setPayable
|
|
180
|
+
setPayable,
|
|
181
|
+
paymentState,
|
|
182
|
+
setPaymentState: updatePaymentState
|
|
171
183
|
},
|
|
172
184
|
children
|
|
173
185
|
});
|
package/lib/index.d.ts
CHANGED
|
@@ -39,6 +39,7 @@ import DateRangePicker from './components/date-range-picker';
|
|
|
39
39
|
import AutoTopupModal from './components/auto-topup/modal';
|
|
40
40
|
import AutoTopup from './components/auto-topup';
|
|
41
41
|
import Collapse from './components/collapse';
|
|
42
|
+
import PromotionCode from './components/promotion-code';
|
|
42
43
|
export { PaymentThemeProvider } from './theme';
|
|
43
44
|
export * from './libs/util';
|
|
44
45
|
export * from './libs/connect';
|
|
@@ -53,4 +54,4 @@ export * from './hooks/scroll';
|
|
|
53
54
|
export * from './hooks/keyboard';
|
|
54
55
|
export * from './libs/validator';
|
|
55
56
|
export { translations, createTranslator } from './locales';
|
|
56
|
-
export { createLazyComponent, api, dayjs, FormInput, FormLabel, PhoneInput, AddressForm, StripeForm, Status, Livemode, Switch, ConfirmDialog, CheckoutForm, CheckoutTable, CheckoutDonate, CurrencySelector, Payment, PaymentSummary, PricingTable, ProductSkeleton, Amount, CustomerInvoiceList, CustomerPaymentList, TxLink, TxGas, SafeGuard, PricingItem, CountrySelect, Table, TruncatedText, Link, OverdueInvoicePayment, PaymentBeneficiaries, LoadingButton, DonateDetails, ResumeSubscription, CreditGrantsList, CreditTransactionsList, DateRangePicker, CreditStatusChip, AutoTopupModal, AutoTopup, Collapse, };
|
|
57
|
+
export { createLazyComponent, api, dayjs, FormInput, FormLabel, PhoneInput, AddressForm, StripeForm, Status, Livemode, Switch, ConfirmDialog, CheckoutForm, CheckoutTable, CheckoutDonate, CurrencySelector, Payment, PaymentSummary, PricingTable, ProductSkeleton, Amount, CustomerInvoiceList, CustomerPaymentList, TxLink, TxGas, SafeGuard, PricingItem, CountrySelect, Table, TruncatedText, Link, OverdueInvoicePayment, PaymentBeneficiaries, LoadingButton, DonateDetails, ResumeSubscription, CreditGrantsList, CreditTransactionsList, DateRangePicker, CreditStatusChip, AutoTopupModal, AutoTopup, Collapse, PromotionCode, };
|
package/lib/index.js
CHANGED
|
@@ -47,6 +47,7 @@ var _exportNames = {
|
|
|
47
47
|
AutoTopupModal: true,
|
|
48
48
|
AutoTopup: true,
|
|
49
49
|
Collapse: true,
|
|
50
|
+
PromotionCode: true,
|
|
50
51
|
PaymentThemeProvider: true,
|
|
51
52
|
translations: true,
|
|
52
53
|
createTranslator: true
|
|
@@ -243,6 +244,12 @@ Object.defineProperty(exports, "ProductSkeleton", {
|
|
|
243
244
|
return _productSkeleton.default;
|
|
244
245
|
}
|
|
245
246
|
});
|
|
247
|
+
Object.defineProperty(exports, "PromotionCode", {
|
|
248
|
+
enumerable: true,
|
|
249
|
+
get: function () {
|
|
250
|
+
return _promotionCode.default;
|
|
251
|
+
}
|
|
252
|
+
});
|
|
246
253
|
Object.defineProperty(exports, "ResumeSubscription", {
|
|
247
254
|
enumerable: true,
|
|
248
255
|
get: function () {
|
|
@@ -368,6 +375,7 @@ var _dateRangePicker = _interopRequireDefault(require("./components/date-range-p
|
|
|
368
375
|
var _modal = _interopRequireDefault(require("./components/auto-topup/modal"));
|
|
369
376
|
var _autoTopup = _interopRequireDefault(require("./components/auto-topup"));
|
|
370
377
|
var _collapse = _interopRequireDefault(require("./components/collapse"));
|
|
378
|
+
var _promotionCode = _interopRequireDefault(require("./components/promotion-code"));
|
|
371
379
|
var _theme = require("./theme");
|
|
372
380
|
var _util = require("./libs/util");
|
|
373
381
|
Object.keys(_util).forEach(function (key) {
|
package/lib/libs/util.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import type { PaymentDetails, PriceCurrency, PriceRecurring, TInvoiceExpanded, TLineItemExpanded, TPaymentCurrency, TPaymentCurrencyExpanded, TPaymentMethod, TPaymentMethodExpanded, TPrice, TProductExpanded, TSubscriptionExpanded, TSubscriptionItemExpanded } from '@blocklet/payment-types';
|
|
1
|
+
import type { PaymentDetails, PriceCurrency, PriceRecurring, TCoupon, TInvoiceExpanded, TLineItemExpanded, TPaymentCurrency, TPaymentCurrencyExpanded, TPaymentMethod, TPaymentMethodExpanded, TPrice, TProductExpanded, TSubscriptionExpanded, TSubscriptionItemExpanded } from '@blocklet/payment-types';
|
|
2
2
|
import type { ActionProps, PricingRenderProps } from '../types';
|
|
3
3
|
export declare const PAYMENT_KIT_DID = "z2qaCNvKMv5GjouKdcDWexv6WqtHbpNPQDnAk";
|
|
4
|
+
/**
|
|
5
|
+
* Format coupon discount terms for display
|
|
6
|
+
*/
|
|
7
|
+
export declare const formatCouponTerms: (coupon: TCoupon, currency: TPaymentCurrency, locale?: string) => string;
|
|
4
8
|
export declare const isPaymentKitMounted: () => any;
|
|
5
9
|
export declare const getPrefix: () => string;
|
|
6
10
|
export declare function isCrossOrigin(): boolean;
|
package/lib/libs/util.js
CHANGED
|
@@ -10,6 +10,7 @@ exports.formatAmount = formatAmount;
|
|
|
10
10
|
exports.formatAmountPrecisionLimit = formatAmountPrecisionLimit;
|
|
11
11
|
exports.formatBNStr = formatBNStr;
|
|
12
12
|
exports.formatCheckoutHeadlines = formatCheckoutHeadlines;
|
|
13
|
+
exports.formatCouponTerms = void 0;
|
|
13
14
|
exports.formatDateTime = formatDateTime;
|
|
14
15
|
exports.formatError = void 0;
|
|
15
16
|
exports.formatLineItemPricing = formatLineItemPricing;
|
|
@@ -77,6 +78,34 @@ var _locales = require("../locales");
|
|
|
77
78
|
var _dayjs = _interopRequireDefault(require("./dayjs"));
|
|
78
79
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
79
80
|
const PAYMENT_KIT_DID = exports.PAYMENT_KIT_DID = "z2qaCNvKMv5GjouKdcDWexv6WqtHbpNPQDnAk";
|
|
81
|
+
const formatCouponTerms = (coupon, currency, locale = "en") => {
|
|
82
|
+
let couponOff = "";
|
|
83
|
+
if (coupon.percent_off && coupon.percent_off > 0) {
|
|
84
|
+
couponOff = (0, _locales.t)("payment.checkout.coupon.percentage", locale, {
|
|
85
|
+
percent: coupon.percent_off
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
if (coupon.amount_off && coupon.amount_off !== "0") {
|
|
89
|
+
const {
|
|
90
|
+
symbol
|
|
91
|
+
} = currency;
|
|
92
|
+
couponOff = coupon.currency_id === currency.id ? coupon.amount_off || "" : coupon.currency_options?.[currency.id]?.amount_off || "";
|
|
93
|
+
if (couponOff) {
|
|
94
|
+
couponOff = (0, _locales.t)("payment.checkout.coupon.fixedAmount", locale, {
|
|
95
|
+
amount: formatAmount(couponOff, currency.decimal),
|
|
96
|
+
symbol
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (!couponOff) {
|
|
101
|
+
return (0, _locales.t)("payment.checkout.coupon.noDiscount");
|
|
102
|
+
}
|
|
103
|
+
return (0, _locales.t)(`payment.checkout.coupon.terms.${coupon.duration}`, locale, {
|
|
104
|
+
couponOff,
|
|
105
|
+
months: coupon.duration_in_months || 0
|
|
106
|
+
});
|
|
107
|
+
};
|
|
108
|
+
exports.formatCouponTerms = formatCouponTerms;
|
|
80
109
|
const isPaymentKitMounted = () => {
|
|
81
110
|
return (window.blocklet?.componentMountPoints || []).some(x => x.did === PAYMENT_KIT_DID);
|
|
82
111
|
};
|