UNPKG

@blocklet/payment-react

Version:

Reusable react components for payment kit v2

488 lines (487 loc) 17.1 kB
"use strict"; 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 })] }); }