import React, { useState, useCallback } from 'react'; import { Box, Typography, Stack, Button, CircularProgress, Card, CardContent, IconButton, Tooltip, SxProps, Collapse, } from '@mui/material'; import { AddOutlined, CreditCard, SettingsOutlined, AccountBalanceWalletOutlined } from '@mui/icons-material'; import { useLocaleContext } from '@arcblock/ux/lib/Locale/context'; // eslint-disable-next-line import/no-extraneous-dependencies import { useNavigate } from 'react-router-dom'; import { joinURL } from 'ufo'; import type { AutoRechargeConfig } from '@blocklet/payment-types'; import { useRequest } from 'ahooks'; import { getPrefix, formatBNStr, formatNumber, formatPrice, formatCreditAmount } from '../../libs/util'; import { createLink, handleNavigation } from '../../libs/navigation'; import { usePaymentContext } from '../../contexts/payment'; import api from '../../libs/api'; import AutoTopupModal from './modal'; import { useMobile } from '../../hooks/mobile'; export interface AutoTopupCardProps { currencyId: string; onConfigChange?: (config: AutoRechargeConfig) => void; sx?: SxProps; // 渲染模式: default=完整显示, simple=默认收起支持展开, custom=自定义渲染 mode?: 'default' | 'simple' | 'custom'; // 自定义渲染函数(custom模式下使用) children?: ( openModal: () => void, config: AutoRechargeConfig | null, paymentData: { paymentInfo: any; balanceInfo: any } | null, loading: boolean ) => React.ReactNode; } const fetchConfig = async (customerId: string, currencyId: string) => { const { data } = await api.get(`/api/auto-recharge-configs/customer/${customerId}`, { params: { currency_id: currencyId }, }); return data; }; const fetchCurrencyBalance = async (currencyId: string, payerAddress: string) => { const { data } = await api.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', }; export default function AutoTopupCard({ currencyId, onConfigChange = () => {}, sx = {}, mode = 'default', children = undefined, }: AutoTopupCardProps) { const { t } = useLocaleContext(); const navigate = useNavigate(); const { session } = usePaymentContext(); const [modalOpen, setModalOpen] = useState(false); const [paymentData, setPaymentData] = useState<{ paymentInfo: any; balanceInfo: any } | null>(null); const [quickSetupMode, setQuickSetupMode] = useState(false); // 是否是快速设置模式 // simple模式默认收起,default模式默认展开 const [expanded, setExpanded] = useState(mode === 'default'); const customerId = session?.user?.did || ''; const { isMobile } = useMobile(); const { data: config, loading, refresh, } = useRequest(() => fetchConfig(customerId, currencyId), { refreshDeps: [customerId, currencyId], ready: !!customerId && !!currencyId, onSuccess: (data) => { loadPaymentInfo(data); }, }); const loadPaymentInfo = useCallback(async (data: any) => { 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 as string) : null; setPaymentData({ paymentInfo, balanceInfo, }); } catch (error) { console.error('Failed to load payment info:', error); } }, []); const handleRecharge = (e: React.MouseEvent) => { if (!paymentData?.paymentInfo?.payer) return; const url = joinURL( getPrefix(), `/customer/recharge/${config?.recharge_currency_id}?rechargeAddress=${paymentData.paymentInfo.payer}` ); const link = createLink(url, true); handleNavigation(e, link, navigate); }; const handleConfigSuccess = (newConfig: AutoRechargeConfig) => { refresh(); onConfigChange?.(newConfig); setModalOpen(false); setQuickSetupMode(false); // 重置快速设置模式 }; const handleToggleExpanded = () => { setExpanded(!expanded); }; if (loading) { return ( ); } if (!config) { return null; } const renderPurchaseDetails = () => { const { paymentInfo, balanceInfo } = paymentData || {}; if (!paymentInfo) { return ( {t('payment.autoTopup.notConfigured')} ); } const purchaseAmount = 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 ( {t('payment.autoTopup.purchaseAmount')}: {purchaseAmount} {t('payment.autoTopup.paymentMethod')}: {cardBrand}({last4}) ); } return ( {t('payment.autoTopup.purchaseAmount')}: {purchaseAmount} {t('payment.autoTopup.walletBalance')}: {balanceInfo ? `${formatBNStr(balanceInfo?.token || '0', config?.rechargeCurrency?.decimal || 18)} ${config?.rechargeCurrency?.symbol || ''}` : '--'} {balanceInfo && !isMobile && ( {t('payment.autoTopup.addFunds')} )} {balanceInfo && isMobile && ( {t('payment.autoTopup.addFunds')} )} ); }; const openModal = () => setModalOpen(true); const renderInnerView = () => { if (mode === 'custom') { return children && typeof children === 'function' ? ( <>{children(openModal, config, paymentData, loading)}> ) : ( Please provide a valid render function {'(openModal, config, paymentData, loading) => ReactNode'} ); } return ( {/* Header */} {t('payment.autoTopup.title')} {config?.enabled ? ( {/* Main Description */} {(() => { const threshold = `${formatCreditAmount(formatNumber(config.threshold), config.currency?.symbol || '')}`; const credits = `${formatCreditAmount( formatNumber( Number(config.price.metadata?.credit_config?.credit_amount || 0) * Number(config.quantity) ), config.currency?.symbol || '' )}`; return ( {t('payment.autoTopup.activeDescriptionWithCredits', { threshold, credits })} {/* 展开收起按钮 - 仅在simple模式下显示 */} {mode === 'simple' && ( {expanded ? t('payment.autoTopup.hideDetails') : t('payment.autoTopup.showDetails')} )} ); })()} {renderPurchaseDetails()} ) : ( {t('payment.autoTopup.inactiveDescription', { name: config?.currency?.name, })} { setQuickSetupMode(true); setModalOpen(true); }} sx={{ color: 'primary.main', minWidth: 'auto', ml: 1, p: 0, fontSize: 'inherit', textTransform: 'none', '&:hover': { backgroundColor: 'transparent', textDecoration: 'underline', }, }}> {t('payment.autoTopup.setup')} )} ); }; return ( <> {renderInnerView()} {modalOpen && ( { setModalOpen(false); setQuickSetupMode(false); // 关闭时重置快速设置模式 }} currencyId={currencyId} onSuccess={handleConfigSuccess} defaultEnabled={quickSetupMode} // 传递默认启用状态 /> )} > ); }
{'(openModal, config, paymentData, loading) => ReactNode'}