@blocklet/payment-react 1.13.296 → 1.13.298
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/pricing-item.d.ts +16 -0
- package/es/components/pricing-item.js +43 -0
- package/es/index.d.ts +2 -1
- package/es/index.js +3 -1
- package/es/libs/util.d.ts +8 -1
- package/es/libs/util.js +36 -0
- package/es/locales/en.js +1 -1
- package/es/locales/zh.js +1 -1
- package/es/types/index.d.ts +6 -0
- package/lib/components/pricing-item.d.ts +16 -0
- package/lib/components/pricing-item.js +61 -0
- package/lib/index.d.ts +2 -1
- package/lib/index.js +8 -0
- package/lib/libs/util.d.ts +8 -1
- package/lib/libs/util.js +49 -0
- package/lib/locales/en.js +1 -1
- package/lib/locales/zh.js +1 -1
- package/lib/types/index.d.ts +6 -0
- package/package.json +3 -3
- package/src/components/pricing-item.tsx +57 -0
- package/src/index.ts +2 -0
- package/src/libs/util.ts +48 -0
- package/src/locales/en.tsx +1 -1
- package/src/locales/zh.tsx +1 -1
- package/src/types/index.ts +7 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { TProductExpanded } from '@blocklet/payment-types';
|
|
3
|
+
import { PricingRenderProps } from '../types';
|
|
4
|
+
export type PricingItemProps = {
|
|
5
|
+
productId: string;
|
|
6
|
+
quantity: number;
|
|
7
|
+
priceId: string | undefined;
|
|
8
|
+
children?: (pricing: PricingRenderProps, product?: TProductExpanded | undefined) => React.ReactNode;
|
|
9
|
+
};
|
|
10
|
+
declare function PricingItem({ productId, quantity, children, priceId }: PricingItemProps): import("react").JSX.Element;
|
|
11
|
+
declare namespace PricingItem {
|
|
12
|
+
var defaultProps: {
|
|
13
|
+
children: null;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export default PricingItem;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useRequest } from "ahooks";
|
|
3
|
+
import { CircularProgress, Typography } from "@mui/material";
|
|
4
|
+
import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
|
|
5
|
+
import { useMemo } from "react";
|
|
6
|
+
import Toast from "@arcblock/ux/lib/Toast";
|
|
7
|
+
import { Box } from "@mui/system";
|
|
8
|
+
import api from "../libs/api.js";
|
|
9
|
+
import { formatError, formatTotalPrice } from "../libs/util.js";
|
|
10
|
+
const fetchProduct = (productId) => {
|
|
11
|
+
return api.get(`/api/products/${productId}`).then((res) => res.data);
|
|
12
|
+
};
|
|
13
|
+
function PricingItem({ productId, quantity, children, priceId }) {
|
|
14
|
+
const { locale } = useLocaleContext();
|
|
15
|
+
const { data: productInfo, loading = false } = useRequest(() => fetchProduct(productId), {
|
|
16
|
+
refreshDeps: [productId],
|
|
17
|
+
onSuccess: (res) => {
|
|
18
|
+
if (!res) {
|
|
19
|
+
Toast.error(formatError(new Error("Product not found")));
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
onError: (err) => {
|
|
23
|
+
Toast.error(formatError(err));
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
const pricing = useMemo(
|
|
27
|
+
() => formatTotalPrice({
|
|
28
|
+
product: productInfo,
|
|
29
|
+
quantity,
|
|
30
|
+
priceId,
|
|
31
|
+
locale
|
|
32
|
+
}),
|
|
33
|
+
[productInfo, quantity, priceId, locale]
|
|
34
|
+
);
|
|
35
|
+
if (loading) {
|
|
36
|
+
return /* @__PURE__ */ jsx(CircularProgress, {});
|
|
37
|
+
}
|
|
38
|
+
return /* @__PURE__ */ jsx(Box, { children: children ? children(pricing, productInfo) : /* @__PURE__ */ jsx(Typography, { children: pricing?.totalPrice }) });
|
|
39
|
+
}
|
|
40
|
+
PricingItem.defaultProps = {
|
|
41
|
+
children: null
|
|
42
|
+
};
|
|
43
|
+
export default PricingItem;
|
package/es/index.d.ts
CHANGED
|
@@ -22,9 +22,10 @@ import StripeForm from './payment/form/stripe';
|
|
|
22
22
|
import Payment from './payment/index';
|
|
23
23
|
import ProductSkeleton from './payment/product-skeleton';
|
|
24
24
|
import PaymentSummary from './payment/summary';
|
|
25
|
+
import PricingItem from './components/pricing-item';
|
|
25
26
|
export * from './libs/util';
|
|
26
27
|
export * from './libs/connect';
|
|
27
28
|
export * from './contexts/payment';
|
|
28
29
|
export * from './hooks/subscription';
|
|
29
30
|
export { translations, createTranslator } from './locales';
|
|
30
|
-
export { api, dayjs, FormInput, PhoneInput, AddressForm, StripeForm, Status, Livemode, Switch, ConfirmDialog, CheckoutForm, CheckoutTable, CheckoutDonate, CurrencySelector, Payment, PaymentSummary, PricingTable, ProductSkeleton, Amount, CustomerInvoiceList, CustomerPaymentList, TxLink, TxGas, SafeGuard, };
|
|
31
|
+
export { api, dayjs, FormInput, PhoneInput, AddressForm, StripeForm, Status, Livemode, Switch, ConfirmDialog, CheckoutForm, CheckoutTable, CheckoutDonate, CurrencySelector, Payment, PaymentSummary, PricingTable, ProductSkeleton, Amount, CustomerInvoiceList, CustomerPaymentList, TxLink, TxGas, SafeGuard, PricingItem, };
|
package/es/index.js
CHANGED
|
@@ -22,6 +22,7 @@ import StripeForm from "./payment/form/stripe.js";
|
|
|
22
22
|
import Payment from "./payment/index.js";
|
|
23
23
|
import ProductSkeleton from "./payment/product-skeleton.js";
|
|
24
24
|
import PaymentSummary from "./payment/summary.js";
|
|
25
|
+
import PricingItem from "./components/pricing-item.js";
|
|
25
26
|
export * from "./libs/util.js";
|
|
26
27
|
export * from "./libs/connect.js";
|
|
27
28
|
export * from "./contexts/payment.js";
|
|
@@ -51,5 +52,6 @@ export {
|
|
|
51
52
|
CustomerPaymentList,
|
|
52
53
|
TxLink,
|
|
53
54
|
TxGas,
|
|
54
|
-
SafeGuard
|
|
55
|
+
SafeGuard,
|
|
56
|
+
PricingItem
|
|
55
57
|
};
|
package/es/libs/util.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import type { PaymentDetails, PriceCurrency, PriceRecurring, TLineItemExpanded, TPaymentCurrency, TPaymentCurrencyExpanded, TPaymentMethod, TPaymentMethodExpanded, TPrice, TSubscriptionExpanded, TSubscriptionItemExpanded } from '@blocklet/payment-types';
|
|
2
|
+
import type { PaymentDetails, PriceCurrency, PriceRecurring, TLineItemExpanded, TPaymentCurrency, TPaymentCurrencyExpanded, TPaymentMethod, TPaymentMethodExpanded, TPrice, TProductExpanded, TSubscriptionExpanded, TSubscriptionItemExpanded } from '@blocklet/payment-types';
|
|
3
|
+
import { PricingRenderProps } from '../types';
|
|
3
4
|
export declare const PAYMENT_KIT_DID = "z2qaCNvKMv5GjouKdcDWexv6WqtHbpNPQDnAk";
|
|
4
5
|
export declare const isPaymentKitMounted: () => any;
|
|
5
6
|
export declare const getPrefix: () => string;
|
|
@@ -69,3 +70,9 @@ export declare const getTxLink: (method: TPaymentMethod, details: PaymentDetails
|
|
|
69
70
|
};
|
|
70
71
|
export declare function getQueryParams(url: string): Record<string, string>;
|
|
71
72
|
export declare function lazyLoad(lazyRun: () => void): void;
|
|
73
|
+
export declare function formatTotalPrice({ product, quantity, priceId, locale, }: {
|
|
74
|
+
product: TProductExpanded;
|
|
75
|
+
quantity: number;
|
|
76
|
+
priceId?: string;
|
|
77
|
+
locale: string;
|
|
78
|
+
}): PricingRenderProps;
|
package/es/libs/util.js
CHANGED
|
@@ -636,3 +636,39 @@ export function lazyLoad(lazyRun) {
|
|
|
636
636
|
lazyRun();
|
|
637
637
|
}, 0);
|
|
638
638
|
}
|
|
639
|
+
export function formatTotalPrice({
|
|
640
|
+
product,
|
|
641
|
+
quantity = 1,
|
|
642
|
+
priceId,
|
|
643
|
+
locale = "en"
|
|
644
|
+
}) {
|
|
645
|
+
const { prices = [], default_price_id: defaultPriceId } = product ?? { prices: [], default_price_id: "" };
|
|
646
|
+
const price = prices?.find((x) => x.id === (priceId || defaultPriceId));
|
|
647
|
+
if (!price || !product) {
|
|
648
|
+
return {
|
|
649
|
+
totalPrice: "0",
|
|
650
|
+
unitPrice: "",
|
|
651
|
+
quantity: t("common.qty", locale, { count: quantity }),
|
|
652
|
+
totalAmount: "0"
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
const unitValue = new BN(price.custom_unit_amount || price.unit_amount);
|
|
656
|
+
const currency = price?.currency ?? {};
|
|
657
|
+
const total = `${fromUnitToToken(unitValue.mul(new BN(quantity)), currency.decimal)} ${currency.symbol}`;
|
|
658
|
+
const unit = `${fromUnitToToken(unitValue, currency.decimal)} ${currency.symbol}`;
|
|
659
|
+
const appendUnit = (v, alt) => {
|
|
660
|
+
if (product.unit_label) {
|
|
661
|
+
return `${v}/${price.product.unit_label}`;
|
|
662
|
+
}
|
|
663
|
+
if (price.recurring?.usage_type === "metered" || quantity === 1) {
|
|
664
|
+
return alt;
|
|
665
|
+
}
|
|
666
|
+
return quantity ? t("common.each", locale, { unit }) : "";
|
|
667
|
+
};
|
|
668
|
+
return {
|
|
669
|
+
totalPrice: total,
|
|
670
|
+
unitPrice: appendUnit(total, ""),
|
|
671
|
+
quantity: t("common.qty", locale, { count: quantity }),
|
|
672
|
+
totalAmount: unitValue.mul(new BN(quantity)).toString()
|
|
673
|
+
};
|
|
674
|
+
}
|
package/es/locales/en.js
CHANGED
|
@@ -113,7 +113,7 @@ export default flat({
|
|
|
113
113
|
between: "Please enter an amount between {min} and {max}.",
|
|
114
114
|
custom: "Custom Amount",
|
|
115
115
|
select: "Select Amount",
|
|
116
|
-
summary: "{total} supporters {totalAmount}{symbol}",
|
|
116
|
+
summary: "{total} supporters {totalAmount} {symbol}",
|
|
117
117
|
empty: "No supporters yet"
|
|
118
118
|
},
|
|
119
119
|
cardPay: "{action} with card",
|
package/es/locales/zh.js
CHANGED
|
@@ -113,7 +113,7 @@ export default flat({
|
|
|
113
113
|
between: "\u91D1\u989D\u5FC5\u987B\u5927\u4E8E {min} \u4E14\u5C0F\u4E8E {max}",
|
|
114
114
|
custom: "\u8F93\u5165\u91D1\u989D",
|
|
115
115
|
select: "\u9009\u62E9\u91D1\u989D",
|
|
116
|
-
summary: "\u5171\u6709 {total} \u4EBA\u652F\u6301 {totalAmount}{symbol}",
|
|
116
|
+
summary: "\u5171\u6709 {total} \u4EBA\u652F\u6301 {totalAmount} {symbol}",
|
|
117
117
|
empty: "\u2764\uFE0F \u652F\u6301\u4E00\u4E0B"
|
|
118
118
|
},
|
|
119
119
|
cardPay: "\u4F7F\u7528\u5361\u7247{action}",
|
package/es/types/index.d.ts
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { TProductExpanded } from '@blocklet/payment-types';
|
|
3
|
+
import { PricingRenderProps } from '../types';
|
|
4
|
+
export type PricingItemProps = {
|
|
5
|
+
productId: string;
|
|
6
|
+
quantity: number;
|
|
7
|
+
priceId: string | undefined;
|
|
8
|
+
children?: (pricing: PricingRenderProps, product?: TProductExpanded | undefined) => React.ReactNode;
|
|
9
|
+
};
|
|
10
|
+
declare function PricingItem({ productId, quantity, children, priceId }: PricingItemProps): import("react").JSX.Element;
|
|
11
|
+
declare namespace PricingItem {
|
|
12
|
+
var defaultProps: {
|
|
13
|
+
children: null;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export default PricingItem;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
8
|
+
var _ahooks = require("ahooks");
|
|
9
|
+
var _material = require("@mui/material");
|
|
10
|
+
var _context = require("@arcblock/ux/lib/Locale/context");
|
|
11
|
+
var _react = require("react");
|
|
12
|
+
var _Toast = _interopRequireDefault(require("@arcblock/ux/lib/Toast"));
|
|
13
|
+
var _system = require("@mui/system");
|
|
14
|
+
var _api = _interopRequireDefault(require("../libs/api"));
|
|
15
|
+
var _util = require("../libs/util");
|
|
16
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
|
+
const fetchProduct = productId => {
|
|
18
|
+
return _api.default.get(`/api/products/${productId}`).then(res => res.data);
|
|
19
|
+
};
|
|
20
|
+
function PricingItem({
|
|
21
|
+
productId,
|
|
22
|
+
quantity,
|
|
23
|
+
children,
|
|
24
|
+
priceId
|
|
25
|
+
}) {
|
|
26
|
+
const {
|
|
27
|
+
locale
|
|
28
|
+
} = (0, _context.useLocaleContext)();
|
|
29
|
+
const {
|
|
30
|
+
data: productInfo,
|
|
31
|
+
loading = false
|
|
32
|
+
} = (0, _ahooks.useRequest)(() => fetchProduct(productId), {
|
|
33
|
+
refreshDeps: [productId],
|
|
34
|
+
onSuccess: res => {
|
|
35
|
+
if (!res) {
|
|
36
|
+
_Toast.default.error((0, _util.formatError)(new Error("Product not found")));
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
onError: err => {
|
|
40
|
+
_Toast.default.error((0, _util.formatError)(err));
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
const pricing = (0, _react.useMemo)(() => (0, _util.formatTotalPrice)({
|
|
44
|
+
product: productInfo,
|
|
45
|
+
quantity,
|
|
46
|
+
priceId,
|
|
47
|
+
locale
|
|
48
|
+
}), [productInfo, quantity, priceId, locale]);
|
|
49
|
+
if (loading) {
|
|
50
|
+
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.CircularProgress, {});
|
|
51
|
+
}
|
|
52
|
+
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_system.Box, {
|
|
53
|
+
children: children ? children(pricing, productInfo) : /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
54
|
+
children: pricing?.totalPrice
|
|
55
|
+
})
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
PricingItem.defaultProps = {
|
|
59
|
+
children: null
|
|
60
|
+
};
|
|
61
|
+
module.exports = PricingItem;
|
package/lib/index.d.ts
CHANGED
|
@@ -22,9 +22,10 @@ import StripeForm from './payment/form/stripe';
|
|
|
22
22
|
import Payment from './payment/index';
|
|
23
23
|
import ProductSkeleton from './payment/product-skeleton';
|
|
24
24
|
import PaymentSummary from './payment/summary';
|
|
25
|
+
import PricingItem from './components/pricing-item';
|
|
25
26
|
export * from './libs/util';
|
|
26
27
|
export * from './libs/connect';
|
|
27
28
|
export * from './contexts/payment';
|
|
28
29
|
export * from './hooks/subscription';
|
|
29
30
|
export { translations, createTranslator } from './locales';
|
|
30
|
-
export { api, dayjs, FormInput, PhoneInput, AddressForm, StripeForm, Status, Livemode, Switch, ConfirmDialog, CheckoutForm, CheckoutTable, CheckoutDonate, CurrencySelector, Payment, PaymentSummary, PricingTable, ProductSkeleton, Amount, CustomerInvoiceList, CustomerPaymentList, TxLink, TxGas, SafeGuard, };
|
|
31
|
+
export { api, dayjs, FormInput, PhoneInput, AddressForm, StripeForm, Status, Livemode, Switch, ConfirmDialog, CheckoutForm, CheckoutTable, CheckoutDonate, CurrencySelector, Payment, PaymentSummary, PricingTable, ProductSkeleton, Amount, CustomerInvoiceList, CustomerPaymentList, TxLink, TxGas, SafeGuard, PricingItem, };
|
package/lib/index.js
CHANGED
|
@@ -28,6 +28,7 @@ var _exportNames = {
|
|
|
28
28
|
Payment: true,
|
|
29
29
|
ProductSkeleton: true,
|
|
30
30
|
PaymentSummary: true,
|
|
31
|
+
PricingItem: true,
|
|
31
32
|
translations: true,
|
|
32
33
|
createTranslator: true
|
|
33
34
|
};
|
|
@@ -115,6 +116,12 @@ Object.defineProperty(exports, "PhoneInput", {
|
|
|
115
116
|
return _phone.default;
|
|
116
117
|
}
|
|
117
118
|
});
|
|
119
|
+
Object.defineProperty(exports, "PricingItem", {
|
|
120
|
+
enumerable: true,
|
|
121
|
+
get: function () {
|
|
122
|
+
return _pricingItem.default;
|
|
123
|
+
}
|
|
124
|
+
});
|
|
118
125
|
Object.defineProperty(exports, "PricingTable", {
|
|
119
126
|
enumerable: true,
|
|
120
127
|
get: function () {
|
|
@@ -211,6 +218,7 @@ var _stripe = _interopRequireDefault(require("./payment/form/stripe"));
|
|
|
211
218
|
var _index = _interopRequireDefault(require("./payment/index"));
|
|
212
219
|
var _productSkeleton = _interopRequireDefault(require("./payment/product-skeleton"));
|
|
213
220
|
var _summary = _interopRequireDefault(require("./payment/summary"));
|
|
221
|
+
var _pricingItem = _interopRequireDefault(require("./components/pricing-item"));
|
|
214
222
|
var _util = require("./libs/util");
|
|
215
223
|
Object.keys(_util).forEach(function (key) {
|
|
216
224
|
if (key === "default" || key === "__esModule") return;
|
package/lib/libs/util.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import type { PaymentDetails, PriceCurrency, PriceRecurring, TLineItemExpanded, TPaymentCurrency, TPaymentCurrencyExpanded, TPaymentMethod, TPaymentMethodExpanded, TPrice, TSubscriptionExpanded, TSubscriptionItemExpanded } from '@blocklet/payment-types';
|
|
2
|
+
import type { PaymentDetails, PriceCurrency, PriceRecurring, TLineItemExpanded, TPaymentCurrency, TPaymentCurrencyExpanded, TPaymentMethod, TPaymentMethodExpanded, TPrice, TProductExpanded, TSubscriptionExpanded, TSubscriptionItemExpanded } from '@blocklet/payment-types';
|
|
3
|
+
import { PricingRenderProps } from '../types';
|
|
3
4
|
export declare const PAYMENT_KIT_DID = "z2qaCNvKMv5GjouKdcDWexv6WqtHbpNPQDnAk";
|
|
4
5
|
export declare const isPaymentKitMounted: () => any;
|
|
5
6
|
export declare const getPrefix: () => string;
|
|
@@ -69,3 +70,9 @@ export declare const getTxLink: (method: TPaymentMethod, details: PaymentDetails
|
|
|
69
70
|
};
|
|
70
71
|
export declare function getQueryParams(url: string): Record<string, string>;
|
|
71
72
|
export declare function lazyLoad(lazyRun: () => void): void;
|
|
73
|
+
export declare function formatTotalPrice({ product, quantity, priceId, locale, }: {
|
|
74
|
+
product: TProductExpanded;
|
|
75
|
+
quantity: number;
|
|
76
|
+
priceId?: string;
|
|
77
|
+
locale: string;
|
|
78
|
+
}): PricingRenderProps;
|
package/lib/libs/util.js
CHANGED
|
@@ -20,6 +20,7 @@ exports.formatSubscriptionProduct = formatSubscriptionProduct;
|
|
|
20
20
|
exports.formatTime = formatTime;
|
|
21
21
|
exports.formatToDate = formatToDate;
|
|
22
22
|
exports.formatToDatetime = formatToDatetime;
|
|
23
|
+
exports.formatTotalPrice = formatTotalPrice;
|
|
23
24
|
exports.formatUpsellSaving = formatUpsellSaving;
|
|
24
25
|
exports.getCheckoutAmount = getCheckoutAmount;
|
|
25
26
|
exports.getInvoiceStatusColor = getInvoiceStatusColor;
|
|
@@ -756,4 +757,52 @@ function lazyLoad(lazyRun) {
|
|
|
756
757
|
setTimeout(() => {
|
|
757
758
|
lazyRun();
|
|
758
759
|
}, 0);
|
|
760
|
+
}
|
|
761
|
+
function formatTotalPrice({
|
|
762
|
+
product,
|
|
763
|
+
quantity = 1,
|
|
764
|
+
priceId,
|
|
765
|
+
locale = "en"
|
|
766
|
+
}) {
|
|
767
|
+
const {
|
|
768
|
+
prices = [],
|
|
769
|
+
default_price_id: defaultPriceId
|
|
770
|
+
} = product ?? {
|
|
771
|
+
prices: [],
|
|
772
|
+
default_price_id: ""
|
|
773
|
+
};
|
|
774
|
+
const price = prices?.find(x => x.id === (priceId || defaultPriceId));
|
|
775
|
+
if (!price || !product) {
|
|
776
|
+
return {
|
|
777
|
+
totalPrice: "0",
|
|
778
|
+
unitPrice: "",
|
|
779
|
+
quantity: (0, _locales.t)("common.qty", locale, {
|
|
780
|
+
count: quantity
|
|
781
|
+
}),
|
|
782
|
+
totalAmount: "0"
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
const unitValue = new _util.BN(price.custom_unit_amount || price.unit_amount);
|
|
786
|
+
const currency = price?.currency ?? {};
|
|
787
|
+
const total = `${(0, _util.fromUnitToToken)(unitValue.mul(new _util.BN(quantity)), currency.decimal)} ${currency.symbol}`;
|
|
788
|
+
const unit = `${(0, _util.fromUnitToToken)(unitValue, currency.decimal)} ${currency.symbol}`;
|
|
789
|
+
const appendUnit = (v, alt) => {
|
|
790
|
+
if (product.unit_label) {
|
|
791
|
+
return `${v}/${price.product.unit_label}`;
|
|
792
|
+
}
|
|
793
|
+
if (price.recurring?.usage_type === "metered" || quantity === 1) {
|
|
794
|
+
return alt;
|
|
795
|
+
}
|
|
796
|
+
return quantity ? (0, _locales.t)("common.each", locale, {
|
|
797
|
+
unit
|
|
798
|
+
}) : "";
|
|
799
|
+
};
|
|
800
|
+
return {
|
|
801
|
+
totalPrice: total,
|
|
802
|
+
unitPrice: appendUnit(total, ""),
|
|
803
|
+
quantity: (0, _locales.t)("common.qty", locale, {
|
|
804
|
+
count: quantity
|
|
805
|
+
}),
|
|
806
|
+
totalAmount: unitValue.mul(new _util.BN(quantity)).toString()
|
|
807
|
+
};
|
|
759
808
|
}
|
package/lib/locales/en.js
CHANGED
|
@@ -120,7 +120,7 @@ module.exports = (0, _flat.default)({
|
|
|
120
120
|
between: "Please enter an amount between {min} and {max}.",
|
|
121
121
|
custom: "Custom Amount",
|
|
122
122
|
select: "Select Amount",
|
|
123
|
-
summary: "{total} supporters {totalAmount}{symbol}",
|
|
123
|
+
summary: "{total} supporters {totalAmount} {symbol}",
|
|
124
124
|
empty: "No supporters yet"
|
|
125
125
|
},
|
|
126
126
|
cardPay: "{action} with card",
|
package/lib/locales/zh.js
CHANGED
|
@@ -120,7 +120,7 @@ module.exports = (0, _flat.default)({
|
|
|
120
120
|
between: "\u91D1\u989D\u5FC5\u987B\u5927\u4E8E {min} \u4E14\u5C0F\u4E8E {max}",
|
|
121
121
|
custom: "\u8F93\u5165\u91D1\u989D",
|
|
122
122
|
select: "\u9009\u62E9\u91D1\u989D",
|
|
123
|
-
summary: "\u5171\u6709 {total} \u4EBA\u652F\u6301 {totalAmount}{symbol}",
|
|
123
|
+
summary: "\u5171\u6709 {total} \u4EBA\u652F\u6301 {totalAmount} {symbol}",
|
|
124
124
|
empty: "\u2764\uFE0F \u652F\u6301\u4E00\u4E0B"
|
|
125
125
|
},
|
|
126
126
|
cardPay: "\u4F7F\u7528\u5361\u7247{action}",
|
package/lib/types/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/payment-react",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.298",
|
|
4
4
|
"description": "Reusable react components for payment kit v2",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"@babel/core": "^7.24.7",
|
|
92
92
|
"@babel/preset-env": "^7.24.7",
|
|
93
93
|
"@babel/preset-react": "^7.24.7",
|
|
94
|
-
"@blocklet/payment-types": "1.13.
|
|
94
|
+
"@blocklet/payment-types": "1.13.298",
|
|
95
95
|
"@storybook/addon-essentials": "^7.6.19",
|
|
96
96
|
"@storybook/addon-interactions": "^7.6.19",
|
|
97
97
|
"@storybook/addon-links": "^7.6.19",
|
|
@@ -120,5 +120,5 @@
|
|
|
120
120
|
"vite-plugin-babel": "^1.2.0",
|
|
121
121
|
"vite-plugin-node-polyfills": "^0.21.0"
|
|
122
122
|
},
|
|
123
|
-
"gitHead": "
|
|
123
|
+
"gitHead": "85dd6105a19723e06405eebb4bcc6ffddc2cd7aa"
|
|
124
124
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { useRequest } from 'ahooks';
|
|
2
|
+
import { CircularProgress, Typography } from '@mui/material';
|
|
3
|
+
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
4
|
+
import type { TProductExpanded } from '@blocklet/payment-types';
|
|
5
|
+
import { useMemo } from 'react';
|
|
6
|
+
import Toast from '@arcblock/ux/lib/Toast';
|
|
7
|
+
import { Box } from '@mui/system';
|
|
8
|
+
import api from '../libs/api';
|
|
9
|
+
import { formatError, formatTotalPrice } from '../libs/util';
|
|
10
|
+
import { PricingRenderProps } from '../types';
|
|
11
|
+
|
|
12
|
+
const fetchProduct = (productId: string): Promise<TProductExpanded> => {
|
|
13
|
+
return api.get(`/api/products/${productId}`).then((res) => res.data);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type PricingItemProps = {
|
|
17
|
+
productId: string;
|
|
18
|
+
quantity: number;
|
|
19
|
+
priceId: string | undefined;
|
|
20
|
+
children?: (pricing: PricingRenderProps, product?: TProductExpanded | undefined) => React.ReactNode;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
function PricingItem({ productId, quantity, children, priceId }: PricingItemProps) {
|
|
24
|
+
const { locale } = useLocaleContext();
|
|
25
|
+
|
|
26
|
+
const { data: productInfo, loading = false } = useRequest(() => fetchProduct(productId), {
|
|
27
|
+
refreshDeps: [productId],
|
|
28
|
+
onSuccess: (res) => {
|
|
29
|
+
if (!res) {
|
|
30
|
+
Toast.error(formatError(new Error('Product not found')));
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
onError: (err: any) => {
|
|
34
|
+
Toast.error(formatError(err));
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const pricing: PricingRenderProps = useMemo(
|
|
39
|
+
() =>
|
|
40
|
+
formatTotalPrice({
|
|
41
|
+
product: productInfo!,
|
|
42
|
+
quantity,
|
|
43
|
+
priceId,
|
|
44
|
+
locale,
|
|
45
|
+
}),
|
|
46
|
+
[productInfo, quantity, priceId, locale]
|
|
47
|
+
);
|
|
48
|
+
if (loading) {
|
|
49
|
+
return <CircularProgress />;
|
|
50
|
+
}
|
|
51
|
+
return <Box>{children ? children(pricing, productInfo) : <Typography>{pricing?.totalPrice}</Typography>}</Box>;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
PricingItem.defaultProps = {
|
|
55
|
+
children: null,
|
|
56
|
+
};
|
|
57
|
+
export default PricingItem;
|
package/src/index.ts
CHANGED
|
@@ -22,6 +22,7 @@ import StripeForm from './payment/form/stripe';
|
|
|
22
22
|
import Payment from './payment/index';
|
|
23
23
|
import ProductSkeleton from './payment/product-skeleton';
|
|
24
24
|
import PaymentSummary from './payment/summary';
|
|
25
|
+
import PricingItem from './components/pricing-item';
|
|
25
26
|
|
|
26
27
|
export * from './libs/util';
|
|
27
28
|
export * from './libs/connect';
|
|
@@ -55,4 +56,5 @@ export {
|
|
|
55
56
|
TxLink,
|
|
56
57
|
TxGas,
|
|
57
58
|
SafeGuard,
|
|
59
|
+
PricingItem,
|
|
58
60
|
};
|
package/src/libs/util.ts
CHANGED
|
@@ -10,6 +10,7 @@ import type {
|
|
|
10
10
|
TPaymentMethod,
|
|
11
11
|
TPaymentMethodExpanded,
|
|
12
12
|
TPrice,
|
|
13
|
+
TProductExpanded,
|
|
13
14
|
TSubscriptionExpanded,
|
|
14
15
|
TSubscriptionItemExpanded,
|
|
15
16
|
} from '@blocklet/payment-types';
|
|
@@ -23,6 +24,7 @@ import { joinURL } from 'ufo';
|
|
|
23
24
|
|
|
24
25
|
import { t } from '../locales';
|
|
25
26
|
import dayjs from './dayjs';
|
|
27
|
+
import { PricingRenderProps } from '../types';
|
|
26
28
|
|
|
27
29
|
export const PAYMENT_KIT_DID = 'z2qaCNvKMv5GjouKdcDWexv6WqtHbpNPQDnAk';
|
|
28
30
|
|
|
@@ -824,3 +826,49 @@ export function lazyLoad(lazyRun: () => void) {
|
|
|
824
826
|
lazyRun();
|
|
825
827
|
}, 0);
|
|
826
828
|
}
|
|
829
|
+
|
|
830
|
+
export function formatTotalPrice({
|
|
831
|
+
product,
|
|
832
|
+
quantity = 1,
|
|
833
|
+
priceId,
|
|
834
|
+
locale = 'en',
|
|
835
|
+
}: {
|
|
836
|
+
product: TProductExpanded;
|
|
837
|
+
quantity: number;
|
|
838
|
+
priceId?: string;
|
|
839
|
+
locale: string;
|
|
840
|
+
}): PricingRenderProps {
|
|
841
|
+
const { prices = [], default_price_id: defaultPriceId } = product ?? { prices: [], default_price_id: '' };
|
|
842
|
+
const price = prices?.find((x) => x.id === (priceId || defaultPriceId));
|
|
843
|
+
if (!price || !product) {
|
|
844
|
+
return {
|
|
845
|
+
totalPrice: '0',
|
|
846
|
+
unitPrice: '',
|
|
847
|
+
quantity: t('common.qty', locale, { count: quantity }),
|
|
848
|
+
totalAmount: '0',
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
const unitValue = new BN(price.custom_unit_amount || price.unit_amount);
|
|
852
|
+
const currency: TPaymentCurrency = price?.currency ?? {};
|
|
853
|
+
|
|
854
|
+
const total = `${fromUnitToToken(unitValue.mul(new BN(quantity)), currency.decimal)} ${currency.symbol}`;
|
|
855
|
+
|
|
856
|
+
const unit = `${fromUnitToToken(unitValue, currency.decimal)} ${currency.symbol}`;
|
|
857
|
+
|
|
858
|
+
const appendUnit = (v: string, alt: string) => {
|
|
859
|
+
if (product.unit_label) {
|
|
860
|
+
return `${v}/${price.product.unit_label}`;
|
|
861
|
+
}
|
|
862
|
+
if (price.recurring?.usage_type === 'metered' || quantity === 1) {
|
|
863
|
+
return alt;
|
|
864
|
+
}
|
|
865
|
+
return quantity ? t('common.each', locale, { unit }) : '';
|
|
866
|
+
};
|
|
867
|
+
|
|
868
|
+
return {
|
|
869
|
+
totalPrice: total,
|
|
870
|
+
unitPrice: appendUnit(total, ''),
|
|
871
|
+
quantity: t('common.qty', locale, { count: quantity }),
|
|
872
|
+
totalAmount: unitValue.mul(new BN(quantity)).toString(),
|
|
873
|
+
};
|
|
874
|
+
}
|
package/src/locales/en.tsx
CHANGED
|
@@ -116,7 +116,7 @@ export default flat({
|
|
|
116
116
|
between: 'Please enter an amount between {min} and {max}.',
|
|
117
117
|
custom: 'Custom Amount',
|
|
118
118
|
select: 'Select Amount',
|
|
119
|
-
summary: '{total} supporters {totalAmount}{symbol}',
|
|
119
|
+
summary: '{total} supporters {totalAmount} {symbol}',
|
|
120
120
|
empty: 'No supporters yet',
|
|
121
121
|
},
|
|
122
122
|
cardPay: '{action} with card',
|
package/src/locales/zh.tsx
CHANGED
|
@@ -115,7 +115,7 @@ export default flat({
|
|
|
115
115
|
between: '金额必须大于 {min} 且小于 {max}',
|
|
116
116
|
custom: '输入金额',
|
|
117
117
|
select: '选择金额',
|
|
118
|
-
summary: '共有 {total} 人支持 {totalAmount}{symbol}',
|
|
118
|
+
summary: '共有 {total} 人支持 {totalAmount} {symbol}',
|
|
119
119
|
empty: '❤️ 支持一下',
|
|
120
120
|
},
|
|
121
121
|
cardPay: '使用卡片{action}',
|
package/src/types/index.ts
CHANGED