@blocklet/payment-react
Version:
Reusable react components for payment kit v2
488 lines (487 loc) • 17.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
module.exports = AutoTopupCard;
var _jsxRuntime = require("react/jsx-runtime");
var _react = require("react");
var _material = require("@mui/material");
var _iconsMaterial = require("@mui/icons-material");
var _context = require("@arcblock/ux/lib/Locale/context");
var _reactRouterDom = require("react-router-dom");
var _ufo = require("ufo");
var _ahooks = require("ahooks");
var _util = require("../../libs/util");
var _navigation = require("../../libs/navigation");
var _payment = require("../../contexts/payment");
var _api = _interopRequireDefault(require("../../libs/api"));
var _modal = _interopRequireDefault(require("./modal"));
var _mobile = require("../../hooks/mobile");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const fetchConfig = async (customerId, currencyId) => {
const {
data
} = await _api.default.get(`/api/auto-recharge-configs/customer/${customerId}`, {
params: {
currency_id: currencyId
}
});
return data;
};
const fetchCurrencyBalance = async (currencyId, payerAddress) => {
const {
data
} = await _api.default.get("/api/customers/payer-token", {
params: {
currencyId,
payerAddress
}
});
return data;
};
const cardStyle = {
height: "100%",
width: "100%",
border: "1px solid",
borderColor: "divider",
boxShadow: 1,
borderRadius: 1,
backgroundColor: "background.default"
};
function AutoTopupCard({
currencyId,
onConfigChange = () => {},
sx = {},
mode = "default",
children = void 0
}) {
const {
t
} = (0, _context.useLocaleContext)();
const navigate = (0, _reactRouterDom.useNavigate)();
const {
session
} = (0, _payment.usePaymentContext)();
const [modalOpen, setModalOpen] = (0, _react.useState)(false);
const [paymentData, setPaymentData] = (0, _react.useState)(null);
const [quickSetupMode, setQuickSetupMode] = (0, _react.useState)(false);
const [expanded, setExpanded] = (0, _react.useState)(mode === "default");
const customerId = session?.user?.did || "";
const {
isMobile
} = (0, _mobile.useMobile)();
const {
data: config,
loading,
refresh
} = (0, _ahooks.useRequest)(() => fetchConfig(customerId, currencyId), {
refreshDeps: [customerId, currencyId],
ready: !!customerId && !!currencyId,
onSuccess: data => {
loadPaymentInfo(data);
}
});
const loadPaymentInfo = (0, _react.useCallback)(async data => {
if (!data?.recharge_currency_id) return;
try {
const paymentMethodType = data?.paymentMethod?.type;
const paymentInfo = data?.payment_settings?.payment_method_options?.[paymentMethodType];
const balanceInfo = paymentInfo?.payer && paymentMethodType !== "stripe" ? await fetchCurrencyBalance(data.recharge_currency_id, paymentInfo.payer) : null;
setPaymentData({
paymentInfo,
balanceInfo
});
} catch (error) {
console.error("Failed to load payment info:", error);
}
}, []);
const handleRecharge = e => {
if (!paymentData?.paymentInfo?.payer) return;
const url = (0, _ufo.joinURL)((0, _util.getPrefix)(), `/customer/recharge/${config?.recharge_currency_id}?rechargeAddress=${paymentData.paymentInfo.payer}`);
const link = (0, _navigation.createLink)(url, true);
(0, _navigation.handleNavigation)(e, link, navigate);
};
const handleConfigSuccess = newConfig => {
refresh();
onConfigChange?.(newConfig);
setModalOpen(false);
setQuickSetupMode(false);
};
const handleToggleExpanded = () => {
setExpanded(!expanded);
};
if (loading) {
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Card, {
sx: {
...cardStyle,
...sx
},
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.CardContent, {
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
sx: {
display: "flex",
justifyContent: "center",
alignItems: "center",
minHeight: 80
},
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.CircularProgress, {
size: 24
})
})
})
});
}
if (!config) {
return null;
}
const renderPurchaseDetails = () => {
const {
paymentInfo,
balanceInfo
} = paymentData || {};
if (!paymentInfo) {
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
variant: "body2",
sx: {
color: "text.secondary"
},
children: t("payment.autoTopup.notConfigured")
});
}
const purchaseAmount = (0, _util.formatPrice)(config.price, config.rechargeCurrency, config.price.product?.unit_label, config.quantity, true);
if (config?.paymentMethod?.type === "stripe") {
const cardBrand = (paymentInfo?.card_brand || "Card").charAt(0).toUpperCase() + (paymentInfo?.card_brand || "Card").slice(1).toLowerCase();
const last4 = paymentInfo?.card_last4;
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
spacing: 1,
className: "auto-topup-method-info",
children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
sx: {
display: "flex",
alignItems: "center",
gap: 0.5,
justifyContent: {
xs: "space-between",
sm: "flex-start"
}
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, {
variant: "body2",
sx: {
color: "text.secondary"
},
children: [t("payment.autoTopup.purchaseAmount"), "\uFF1A"]
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
variant: "body2",
sx: {
fontWeight: 600,
color: "text.primary"
},
children: purchaseAmount
})]
}), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
sx: {
display: "flex",
alignItems: "center",
gap: 0.5,
justifyContent: {
xs: "space-between",
sm: "flex-start"
}
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, {
variant: "body2",
sx: {
color: "text.secondary"
},
children: [t("payment.autoTopup.paymentMethod"), "\uFF1A"]
}), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
direction: "row",
spacing: 1,
sx: {
alignItems: "center"
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_iconsMaterial.CreditCard, {
fontSize: "small",
sx: {
color: "text.secondary"
}
}), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, {
variant: "body2",
sx: {
color: "text.primary",
fontWeight: 500
},
children: [cardBrand, "(", last4, ")"]
})]
})]
})]
});
}
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
spacing: 1,
className: "auto-topup-method-info",
children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
sx: {
display: "flex",
alignItems: "center",
gap: 0.5,
justifyContent: {
xs: "space-between",
sm: "flex-start"
}
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, {
variant: "body2",
sx: {
color: "text.secondary"
},
children: [t("payment.autoTopup.purchaseAmount"), "\uFF1A"]
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
variant: "body2",
sx: {
fontWeight: 600,
color: "text.primary"
},
children: purchaseAmount
})]
}), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
sx: {
display: "flex",
alignItems: "center",
justifyContent: {
xs: "space-between",
sm: "flex-start"
}
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, {
variant: "body2",
sx: {
color: "text.secondary",
whiteSpace: "nowrap"
},
children: [t("payment.autoTopup.walletBalance"), "\uFF1A"]
}), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
direction: "row",
spacing: 1,
sx: {
alignItems: "center"
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Tooltip, {
title: paymentInfo?.payer ? `${t("payment.autoTopup.paymentAddress")}: ${paymentInfo.payer}` : "",
placement: "top",
children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
sx: {
display: "flex",
alignItems: "center",
gap: 0.5
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_iconsMaterial.AccountBalanceWalletOutlined, {
sx: {
fontSize: 16,
color: "text.secondary"
}
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
variant: "body2",
sx: {
fontWeight: 600,
color: "text.primary"
},
children: balanceInfo ? `${(0, _util.formatBNStr)(balanceInfo?.token || "0", config?.rechargeCurrency?.decimal || 18)} ${config?.rechargeCurrency?.symbol || ""}` : "--"
})]
})
}), balanceInfo && !isMobile && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Button, {
size: "small",
variant: "text",
onClick: handleRecharge,
className: "auto-topup-add-funds-button",
sx: {
color: "primary.main",
display: "flex",
alignItems: "center"
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_iconsMaterial.AddOutlined, {
fontSize: "small"
}), t("payment.autoTopup.addFunds")]
})]
})]
}), balanceInfo && isMobile && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Button, {
size: "small",
variant: "text",
onClick: handleRecharge,
className: "auto-topup-add-funds-button",
sx: {
color: "primary.main",
display: "flex",
alignItems: "center",
justifyContent: "flex-end"
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_iconsMaterial.AddOutlined, {
fontSize: "small"
}), t("payment.autoTopup.addFunds")]
})]
});
};
const openModal = () => setModalOpen(true);
const renderInnerView = () => {
if (mode === "custom") {
return children && typeof children === "function" ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
children: children(openModal, config, paymentData, loading)
}) : /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, {
children: ["Please provide a valid render function", /* @__PURE__ */(0, _jsxRuntime.jsx)("pre", {
children: "(openModal, config, paymentData, loading) => ReactNode"
})]
});
}
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Card, {
sx: {
...cardStyle,
...sx
},
children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.CardContent, {
children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
direction: "row",
className: "auto-topup-header",
sx: {
justifyContent: "space-between",
alignItems: "center",
borderBottom: "1px solid",
borderColor: "divider",
pb: 1.5
},
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
variant: "subtitle2",
sx: {
fontWeight: 600,
color: "text.primary"
},
children: t("payment.autoTopup.title")
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
sx: {
display: "flex",
alignItems: "center",
gap: 0.5
},
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.IconButton, {
size: "small",
onClick: openModal,
sx: {
p: 0.5,
color: "text.secondary",
"&:hover": {
bgcolor: "grey.50",
color: "text.primary"
}
},
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_iconsMaterial.SettingsOutlined, {
fontSize: "small"
})
})
})]
}), config?.enabled ? /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
spacing: 1.5,
className: "auto-topup-content",
sx: {
pt: 1.5
},
children: [(() => {
const threshold = `${(0, _util.formatNumber)(config.threshold)} ${config.currency?.symbol || ""}`;
const credits = `${(0, _util.formatNumber)(Number(config.price.metadata?.credit_config?.credit_amount || 0) * Number(config.quantity))} ${config.currency?.name || ""}`;
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, {
variant: "body2",
sx: {
color: "text.secondary"
},
children: [t("payment.autoTopup.activeDescriptionWithCredits", {
threshold,
credits
}), mode === "simple" && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
component: "span",
size: "small",
variant: "text",
onClick: handleToggleExpanded,
sx: {
color: "primary.main",
minWidth: "auto",
ml: 1,
p: 0,
fontSize: "inherit",
textTransform: "none",
"&:hover": {
backgroundColor: "transparent",
textDecoration: "underline"
}
},
children: expanded ? t("payment.autoTopup.hideDetails") : t("payment.autoTopup.showDetails")
})]
});
})(), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Collapse, {
in: mode === "default" || expanded,
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
sx: {
bgcolor: "grey.50",
borderRadius: 1,
p: 1.5
},
children: renderPurchaseDetails()
})
})]
}) : /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Stack, {
className: "auto-topup-content",
sx: {
minHeight: 80,
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
pt: 1.5,
gap: 2
},
children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, {
variant: "body2",
sx: {
color: "text.secondary",
textAlign: "left"
},
children: [t("payment.autoTopup.inactiveDescription", {
name: config?.currency?.name
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, {
component: "span",
variant: "text",
size: "small",
onClick: () => {
setQuickSetupMode(true);
setModalOpen(true);
},
sx: {
color: "primary.main",
minWidth: "auto",
ml: 1,
p: 0,
fontSize: "inherit",
textTransform: "none",
"&:hover": {
backgroundColor: "transparent",
textDecoration: "underline"
}
},
children: t("payment.autoTopup.setup")
})]
})
})]
})
});
};
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
children: [renderInnerView(), modalOpen && /* @__PURE__ */(0, _jsxRuntime.jsx)(_modal.default, {
open: modalOpen,
onClose: () => {
setModalOpen(false);
setQuickSetupMode(false);
},
currencyId,
onSuccess: handleConfigSuccess,
defaultEnabled: quickSetupMode
})]
});
}