UNPKG

@blocklet/payment-react

Version:

Reusable react components for payment kit v2

259 lines (258 loc) 8.41 kB
import { jsx, jsxs } from "react/jsx-runtime"; import { Stack, Typography, TextField, Card } from "@mui/material"; import { useLocaleContext } from "@arcblock/ux/lib/Locale/context"; import { useState, useMemo } from "react"; import ProductCard from "../../payment/product-card.js"; import { formatPrice, formatNumber, formatDynamicPrice, formatUsdAmount, formatExchangeRate, formatToDatetime, formatCreditForCheckout } from "../../libs/util.js"; import QuoteDetailsPanel from "../quote-details-panel.js"; export default function AutoTopupProductCard({ product, price, currency, quantity, onQuantityChange, maxQuantity = 99, minQuantity = 1, creditCurrency, exchangeRate = null, isDynamicPricing = false, exchangeRateData = null, slippageConfig = null, slippagePercent = 0.5, onSlippageChange = void 0, disabled = false }) { const { t, locale } = useLocaleContext(); const [localQuantity, setLocalQuantity] = useState(quantity); const localQuantityNum = Number(localQuantity) || 0; const { paymentAmount, usdReferenceDisplay } = useMemo(() => { if (!isDynamicPricing || !exchangeRate || !price?.base_amount) { return { paymentAmount: formatPrice(price, currency, product?.unit_label, localQuantity, true), usdReferenceDisplay: null }; } const baseAmount = Number(price.base_amount) * localQuantityNum; const rate = Number(exchangeRate); if (rate <= 0 || !Number.isFinite(baseAmount)) { return { paymentAmount: formatPrice(price, currency, product?.unit_label, localQuantity, true), usdReferenceDisplay: null }; } const tokenAmount = baseAmount / rate; const formattedToken = formatDynamicPrice(tokenAmount, true, 6); const formattedUsd = formatUsdAmount(baseAmount.toString(), locale); return { paymentAmount: `${formattedToken} ${currency.symbol}`, usdReferenceDisplay: formattedUsd ? `\u2248 $${formattedUsd}` : null }; }, [isDynamicPricing, exchangeRate, price, currency, product?.unit_label, localQuantity, localQuantityNum, locale]); const handleQuantityChange = (newQuantity) => { if (!newQuantity) { setLocalQuantity(void 0); return; } if (newQuantity >= minQuantity && newQuantity <= maxQuantity) { setLocalQuantity(newQuantity); onQuantityChange(newQuantity); } }; const handleQuantityInputChange = (event) => { const value = parseInt(event.target.value || "0", 10); if (!Number.isNaN(value)) { handleQuantityChange(value); } }; const creditUnitAmount = Number(price.metadata?.credit_config?.credit_amount || 0); return /* @__PURE__ */ jsxs(Card, { variant: "outlined", sx: { p: 2 }, children: [ /* @__PURE__ */ jsxs( Stack, { direction: "row", spacing: 2, sx: { flexDirection: { xs: "column", sm: "row" }, alignItems: { xs: "flex-start", sm: "center" }, justifyContent: { xs: "flex-start", sm: "space-between" } }, children: [ /* @__PURE__ */ jsx( Stack, { direction: "row", spacing: 2, sx: { alignItems: "center", flex: 1 }, children: /* @__PURE__ */ jsx( ProductCard, { name: product?.name || "", description: t("payment.autoTopup.creditsIncluded", { num: formatCreditForCheckout( formatNumber(creditUnitAmount * localQuantityNum), creditCurrency?.symbol || "", locale ) }), logo: product?.images?.[0], size: 40 } ) } ), /* @__PURE__ */ jsxs( Stack, { direction: "row", spacing: 1, sx: { alignItems: "center", alignSelf: { xs: "flex-end", sm: "center" } }, children: [ /* @__PURE__ */ jsxs( Typography, { variant: "body2", sx: { color: "text.secondary", minWidth: "fit-content" }, children: [ t("common.quantity"), ":" ] } ), /* @__PURE__ */ jsx( TextField, { size: "small", value: localQuantity, onChange: handleQuantityInputChange, type: "number", sx: { "& .MuiInputBase-root": { height: 32 } }, slotProps: { htmlInput: { min: 0, max: maxQuantity, style: { textAlign: "center", padding: "4px 8px" } } } } ) ] } ) ] } ), /* @__PURE__ */ jsxs( Stack, { direction: "row", sx: { justifyContent: "space-between", alignItems: "flex-start", mt: 2, pt: 2, borderTop: "1px solid", borderColor: "divider" }, children: [ /* @__PURE__ */ jsx( Typography, { variant: "body2", sx: { color: "text.secondary" }, children: t("payment.autoTopup.rechargeAmount") } ), /* @__PURE__ */ jsxs(Stack, { sx: { alignItems: "flex-end" }, children: [ /* @__PURE__ */ jsx( Typography, { variant: "h6", sx: { fontWeight: 600, color: "text.primary" }, children: paymentAmount } ), usdReferenceDisplay && /* @__PURE__ */ jsx( Typography, { sx: { fontSize: "0.7875rem", color: "text.lighter" }, children: usdReferenceDisplay } ), isDynamicPricing && exchangeRateData?.rate && /* @__PURE__ */ jsx( QuoteDetailsPanel, { rateLine: t("payment.checkout.quote.rateLine", { symbol: currency.symbol, rate: `$${formatExchangeRate(exchangeRateData.rate) || exchangeRateData.rate}` }), rows: [ { label: t("payment.checkout.quote.detailProvider"), value: exchangeRateData?.provider_display || exchangeRateData?.provider_name || "\u2014" }, { label: t("payment.checkout.quote.detailUpdatedAt"), value: exchangeRateData?.timestamp_ms ? formatToDatetime(exchangeRateData.timestamp_ms, locale) : "\u2014" }, { label: t("payment.checkout.quote.detailSlippage"), value: slippageConfig?.mode === "rate" && slippageConfig.min_acceptable_rate ? `$${formatExchangeRate(slippageConfig.min_acceptable_rate) || slippageConfig.min_acceptable_rate}` : `${slippageConfig?.percent ?? slippagePercent}%`, isSlippage: true } ], isSubscription: true, slippageValue: slippageConfig?.percent ?? slippagePercent, slippageConfig: slippageConfig || void 0, onSlippageChange, exchangeRate: exchangeRateData?.rate, baseCurrency: "USD", disabled } ) ] }) ] } ) ] }); }