UNPKG

@blocklet/payment-react

Version:

Reusable react components for payment kit v2

1,021 lines (1,019 loc) 36.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); module.exports = CustomerInvoiceList; var _jsxRuntime = require("react/jsx-runtime"); var _context = require("@arcblock/ux/lib/Locale/context"); var _Toast = _interopRequireDefault(require("@arcblock/ux/lib/Toast")); var _iconsMaterial = require("@mui/icons-material"); var _material = require("@mui/material"); var _system = require("@mui/system"); var _ahooks = require("ahooks"); var _react = _interopRequireWildcard(require("react")); var _reactRouterDom = require("react-router-dom"); var _debounce = _interopRequireDefault(require("lodash/debounce")); var _util = require("@ocap/util"); var _status = _interopRequireDefault(require("../../components/status")); var _payment = require("../../contexts/payment"); var _subscription = require("../../hooks/subscription"); var _api = _interopRequireDefault(require("../../libs/api")); var _stripePaymentAction = _interopRequireDefault(require("../../components/stripe-payment-action")); var _util2 = require("../../libs/util"); var _table = _interopRequireDefault(require("../../components/table")); var _navigation = require("../../libs/navigation"); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const groupByDate = items => { const grouped = {}; items.forEach(item => { const date = new Date(item.created_at).toLocaleDateString(); if (!grouped[date]) { grouped[date] = []; } grouped[date]?.push(item); }); return grouped; }; const fetchData = (params = {}) => { const search = new URLSearchParams(); const mergedParams = { include_quote: true, ...params }; Object.keys(mergedParams).forEach(key => { if (mergedParams[key]) { search.set(key, String(mergedParams[key])); } }); return _api.default.get(`/api/invoices?${search.toString()}`).then(res => res.data); }; const getInvoiceQuoteInfo = invoice => { const lines = invoice.lines || []; for (const line of lines) { const quote = line.metadata?.quote; if (quote?.exchange_rate) { return quote; } } return null; }; const getInvoiceLink = (invoice, action) => { if (invoice.id.startsWith("in_")) { const path = `/customer/invoice/${invoice.id}${invoice.status === "uncollectible" && action ? `?action=${action}` : ""}`; return { connect: invoice.status === "uncollectible", link: (0, _navigation.createLink)(path) }; } return { connect: false, link: (0, _navigation.createLink)((0, _util2.getTxLink)(invoice.paymentMethod, invoice.metadata?.payment_details).link, true) }; }; const linkStyle = { cursor: "pointer" }; const InvoiceTable = _react.default.memo(props => { const { pageSize, target, action, onPay, status, customer_id, currency_id, subscription_id, include_staking, include_return_staking, include_recovered_from, onTableDataChange, relatedSubscription } = props; const listKey = "invoice-table"; const { t, locale } = (0, _context.useLocaleContext)(); const navigate = (0, _reactRouterDom.useNavigate)(); const { getCurrency } = (0, _payment.usePaymentContext)(); const [search, setSearch] = (0, _react.useState)({ pageSize: pageSize || 10, page: 1 }); const { loading, data = { list: [], count: 0 }, refresh } = (0, _ahooks.useRequest)(() => fetchData({ ...search, status, customer_id, currency_id, subscription_id, include_staking, include_return_staking, include_recovered_from, ignore_zero: true }), { refreshDeps: [search, status, customer_id, currency_id, subscription_id, include_staking, include_recovered_from] }); const prevData = (0, _react.useRef)(data); (0, _react.useEffect)(() => { if (onTableDataChange) { onTableDataChange(data, prevData.current); prevData.current = data; } }, [data]); const subscription = (0, _subscription.useSubscription)("events"); const debouncedHandleInvoicePaid = (0, _debounce.default)(async () => { _Toast.default.close(); _Toast.default.success(t("payment.customer.invoice.paySuccess")); await refresh(); }, 1e3, { leading: false, trailing: true, maxWait: 5e3 }); (0, _react.useEffect)(() => { if (subscription && customer_id) { subscription.on("invoice.paid", ({ response }) => { if (response.customer_id === customer_id) { debouncedHandleInvoicePaid(); } }); } }, [subscription]); const handleLinkClick = (e, invoice) => { const { link } = getInvoiceLink(invoice, action); (0, _navigation.handleNavigation)(e, link, navigate, { target: link.external ? "_blank" : target }); }; const handleRelatedSubscriptionClick = (e, invoice) => { if (invoice.subscription_id) { (0, _navigation.handleNavigation)(e, (0, _navigation.createLink)(`/customer/subscription/${invoice.subscription_id}`), navigate); } }; const columns = [{ label: t("common.amount"), name: "total", width: 80, align: "right", options: { customBodyRenderLite: (_, index) => { const invoice = data?.list[index]; const isVoid = invoice.status === "void"; const quoteInfo = getInvoiceQuoteInfo(invoice); const providers = quoteInfo?.providers || []; const providerNames = providers.map(provider => provider.provider_name).filter(Boolean); const providerDisplay = providerNames.length > 0 ? providerNames.join(", ") : quoteInfo?.rate_provider_name || quoteInfo?.rate_provider_id || "\u2014"; const providerRates = quoteInfo?.providers?.map(provider => { const name = provider.provider_name || provider.provider_id || "\u2014"; return provider.rate ? `${name}` : name; }).filter(Boolean) || []; const rateTimestamp = quoteInfo?.rate_timestamp_ms ? (0, _util2.formatTime)(quoteInfo.rate_timestamp_ms) : "\u2014"; const formattedRate = (0, _util2.formatExchangeRate)(quoteInfo?.exchange_rate || null); const rateLine = formattedRate ? (() => { const currencyMap = { USD: "$", CNY: "\xA5" }; const currencySymbol = currencyMap[quoteInfo?.base_currency]; return `1 ${invoice.paymentCurrency.symbol} \u2248 ${currencySymbol ? `${currencySymbol}${formattedRate}` : `${formattedRate} ${quoteInfo?.base_currency || "USD"}`}`; })() : null; let usdAmount = null; if (quoteInfo?.base_amount) { usdAmount = (0, _util2.formatUsdAmount)(quoteInfo.base_amount, locale); } else if (quoteInfo?.exchange_rate && invoice.total) { const calculatedUsd = (0, _util2.getUsdAmountFromTokenUnits)(new _util.BN(invoice.total), invoice.paymentCurrency.decimal, quoteInfo.exchange_rate); if (calculatedUsd) { usdAmount = (0, _util2.formatUsdAmount)(calculatedUsd, locale); } } const tooltipContent = quoteInfo ? /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, { spacing: 0.5, sx: { p: 1 }, children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, { direction: "row", justifyContent: "space-between", spacing: 2, children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, { variant: "caption", sx: { color: "text.secondary" }, children: [t("payment.customer.invoice.quote.providers"), ":"] }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, { variant: "caption", sx: { color: "text.primary" }, children: (providerRates.length > 0 ? providerRates.join(", ") : providerDisplay) || "\u2014" })] }), rateLine && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, { direction: "row", justifyContent: "space-between", spacing: 2, children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, { variant: "caption", sx: { color: "text.secondary" }, children: [t("payment.customer.invoice.quote.exchangeRate"), ":"] }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, { variant: "caption", sx: { color: "text.primary" }, children: rateLine })] }), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, { direction: "row", justifyContent: "space-between", spacing: 2, children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, { variant: "caption", sx: { color: "text.secondary" }, children: [t("payment.customer.invoice.quote.rateTimestamp"), ":"] }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, { variant: "caption", sx: { color: "text.primary" }, children: rateTimestamp })] })] }) : null; return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, { onClick: e => handleLinkClick(e, invoice), sx: linkStyle, children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, { spacing: 0.25, alignItems: "flex-end", children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, { sx: isVoid ? { textDecoration: "line-through" } : {}, children: [(0, _util2.formatAmount)(invoice.total, invoice.paymentCurrency.decimal), "\xA0", invoice.paymentCurrency.symbol] }), (usdAmount || rateLine) && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Tooltip, { title: tooltipContent, placement: "top", arrow: true, slotProps: { tooltip: { sx: { backgroundColor: "background.paper", boxShadow: 1 } } }, children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Stack, { spacing: 0.25, alignItems: "flex-end", children: usdAmount && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, { variant: "caption", sx: { color: "text.secondary", fontSize: "0.75rem", fontWeight: 400, lineHeight: 1.2 }, children: ["\u2248 $", usdAmount] }) }) })] }) }); } } }, { label: t("common.paymentMethod"), name: "paymentMethod", options: { customBodyRenderLite: (_, index) => { const invoice = data?.list[index]; return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, { sx: { display: "flex", alignItems: "center", whiteSpace: "nowrap" }, onClick: e => handleLinkClick(e, invoice), children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Avatar, { src: invoice.paymentMethod.logo, sx: { width: 18, height: 18, mr: 1 } }), invoice.paymentMethod.name] }); } } }, { label: t("common.type"), name: "billing_reason", options: { customBodyRenderLite: (_, index) => { const invoice = data.list[index]; return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, { onClick: e => handleLinkClick(e, invoice), sx: linkStyle, children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_status.default, { label: (0, _util2.getInvoiceDescriptionAndReason)(invoice, locale)?.type }) }); } } }, { label: t("payment.customer.invoice.invoiceNumber"), name: "number", options: { customBodyRenderLite: (_, index) => { const invoice = data?.list[index]; return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, { onClick: e => handleLinkClick(e, invoice), sx: linkStyle, children: invoice?.number }); } } }, ...(relatedSubscription ? [{ label: t("common.purchaseItems"), name: "purchase_items", options: { customBodyRenderLite: (_, index) => { const invoice = data?.list[index]; const lines = invoice.lines || []; const items = lines.map(line => { const name = line.price?.product?.name || line.description; if (!name) { return null; } const quantity = Number(line.quantity || 0); const label = Number.isFinite(quantity) && quantity > 1 ? `${name} x${quantity}` : name; const lineKey = line.id || line.price?.id || line.price?.product?.id || line.description || name; return { key: String(lineKey), label }; }).filter(Boolean); if (items.length === 0 && invoice.subscription?.description) { items.push({ key: `subscription-${invoice.subscription_id || invoice.id}`, label: invoice.subscription.description }); } const isSubscription = Boolean(invoice.subscription_id); const clickableProps = isSubscription ? { onClick: e => handleRelatedSubscriptionClick(e, invoice) } : {}; if (items.length === 0) { return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, { sx: { color: "text.lighter" }, children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, { sx: { fontSize: 14 }, children: t("common.none") }) }); } return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, { ...clickableProps, sx: isSubscription ? { cursor: "pointer" } : void 0, children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Stack, { spacing: 0.5, children: items.map(item => /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, { sx: { fontSize: 14, color: isSubscription ? "text.link" : "text.primary" }, noWrap: true, children: item.label }, `${invoice.id}-item-${item.key}`)) }) }); } } }, { label: t("common.credits"), name: "credits", options: { customBodyRenderLite: (_, index) => { const invoice = data?.list[index]; const lines = invoice.lines || []; const creditItems = []; lines.forEach(line => { const lineKey = String(line.id || line.price?.id || line.price?.product?.id || line.description || invoice.id); const pushCreditItem = (suffix, label) => { creditItems.push({ key: `${lineKey}-${suffix}`, label }); }; const creditConfig = line.price?.metadata?.credit_config; const creditAmount = Number(creditConfig?.credit_amount || 0); if (creditAmount > 0) { const quantity = Number(line.quantity || 0); const totalAmount = creditAmount * (Number.isFinite(quantity) && quantity > 0 ? quantity : 1); const currencySymbol = getCurrency(creditConfig?.currency_id)?.symbol || creditConfig?.currency_id || "Credits"; pushCreditItem("amount", `+${(0, _util2.formatCreditAmount)(String(totalAmount), currencySymbol)}`); return; } const scheduleConfig = creditConfig?.schedule; const scheduledAmount = Number(scheduleConfig?.amount_per_grant || 0); if (scheduleConfig?.enabled && scheduleConfig?.delivery_mode === "schedule" && scheduledAmount > 0) { const quantity = Number(line.quantity || 0); const totalAmount = scheduledAmount * (Number.isFinite(quantity) && quantity > 0 ? quantity : 1); const currencySymbol = getCurrency(creditConfig?.currency_id)?.symbol || creditConfig?.currency_id || "Credits"; pushCreditItem("schedule", `+${(0, _util2.formatCreditAmount)(String(totalAmount), currencySymbol)}`); return; } const creditInfo = line.price?.credit; const creditInfoAmount = Number(creditInfo?.amount || 0); if (creditInfoAmount > 0) { const currencySymbol = creditInfo.currency?.symbol || "Credits"; pushCreditItem("credit", `+${(0, _util2.formatCreditAmount)(String(creditInfoAmount), currencySymbol)}`); } }); if (creditItems.length === 0) { return "-"; } return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Stack, { spacing: 0.5, children: creditItems.map(creditItem => /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, { sx: { fontSize: 14, color: "success.main" }, noWrap: true, children: creditItem.label }, `${invoice.id}-credit-${creditItem.key}`)) }); } } }] : []), { label: t("common.updatedAt"), name: "name", options: { customBodyRenderLite: (val, index) => { const invoice = data?.list[index]; const periodTooltip = invoice.subscription_id && invoice.period_start && invoice.period_end ? `${t("common.billingPeriod")}: ${(0, _util2.formatToDate)(invoice.period_start * 1e3, locale, "YYYY-MM-DD HH:mm")} ~ ${(0, _util2.formatToDate)(invoice.period_end * 1e3, locale, "YYYY-MM-DD HH:mm")}` : ""; return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Tooltip, { title: periodTooltip, arrow: true, placement: "top-start", children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, { onClick: e => handleLinkClick(e, invoice), sx: linkStyle, children: (0, _util2.formatToDate)(invoice.created_at, locale, relatedSubscription ? "YYYY-MM-DD HH:mm" : "YYYY-MM-DD HH:mm:ss") }) }); } } }, { label: t("common.status"), name: "status", options: { customBodyRenderLite: (val, index) => { const invoice = data?.list[index]; const hidePay = invoice.billing_reason === "overdraft-protection"; const { connect } = getInvoiceLink(invoice, action); const isVoid = invoice.status === "void"; if (action && !hidePay) { if (connect) { if (invoice.paymentMethod?.type === "stripe") { return /* @__PURE__ */(0, _jsxRuntime.jsx)(_stripePaymentAction.default, { invoice, paymentMethod: invoice.paymentMethod, onSuccess: () => { refresh(); }, children: (handlePay, paying) => /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, { variant: "text", size: "small", sx: { color: "text.link" }, disabled: paying, onClick: e => { e.preventDefault(); e.stopPropagation(); handlePay(); }, children: paying ? t("payment.checkout.processing") : t("payment.customer.invoice.pay") }) }); } return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, { variant: "text", size: "small", onClick: () => onPay(invoice.id), sx: { color: "text.link" }, children: t("payment.customer.invoice.pay") }); } return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, { component: "a", variant: "text", size: "small", onClick: e => handleLinkClick(e, invoice), sx: { color: "text.link" }, rel: "noreferrer", children: t("payment.customer.invoice.pay") }); } return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, { onClick: e => handleLinkClick(e, invoice), sx: linkStyle, children: isVoid ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Tooltip, { title: t("payment.customer.invoice.noPaymentRequired"), arrow: true, placement: "top", children: /* @__PURE__ */(0, _jsxRuntime.jsx)("span", { children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_status.default, { label: invoice.status, color: (0, _util2.getInvoiceStatusColor)(invoice.status) }) }) }) : /* @__PURE__ */(0, _jsxRuntime.jsx)(_status.default, { label: invoice.status, color: (0, _util2.getInvoiceStatusColor)(invoice.status) }) }); } } }]; const onTableChange = ({ page, rowsPerPage }) => { if (search.pageSize !== rowsPerPage) { setSearch(x => ({ ...x, pageSize: rowsPerPage, page: 1 })); } else if (search.page !== page + 1) { setSearch(x => ({ ...x, page: page + 1 })); } }; return /* @__PURE__ */(0, _jsxRuntime.jsx)(InvoiceTableRoot, { children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_table.default, { hasRowLink: true, durable: `__${listKey}__`, durableKeys: ["page", "rowsPerPage", "searchText"], data: data.list, columns, options: { count: data.count, page: search.page - 1, rowsPerPage: search.pageSize }, loading, onChange: onTableChange, toolbar: false, sx: { mt: 2 }, showMobile: false, mobileTDFlexDirection: "row", emptyNodeText: t("payment.customer.invoice.emptyList") }) }); }); const InvoiceTableRoot = (0, _system.styled)(_material.Box)` @media (max-width: ${({ theme }) => theme.breakpoints.values.md}px) { .MuiTable-root > .MuiTableBody-root > .MuiTableRow-root > td.MuiTableCell-root { > div { width: fit-content; flex: inherit; font-size: 14px; } } .invoice-summary { padding-right: 20px; } } `; const InvoiceList = _react.default.memo(props => { const { customer_id, subscription_id, include_recovered_from, currency_id, include_staking, status, pageSize, target, action, onPay, onTableDataChange } = props; const size = pageSize || 10; const subscription = (0, _subscription.useSubscription)("events"); const { t, locale } = (0, _context.useLocaleContext)(); const navigate = (0, _reactRouterDom.useNavigate)(); const { data, loadMore, loadingMore, loading, reloadAsync } = (0, _ahooks.useInfiniteScroll)(d => { const page = d ? Math.ceil(d.list.length / size) + 1 : 1; return fetchData({ page, pageSize: size, status, customer_id, currency_id, subscription_id, include_staking, include_recovered_from, ignore_zero: true }); }, { reloadDeps: [customer_id, subscription_id, status, include_staking, include_recovered_from] }); const prevData = (0, _react.useRef)(data); (0, _react.useEffect)(() => { if (onTableDataChange) { onTableDataChange(data, prevData.current); prevData.current = data; } }, [data]); const debouncedHandleInvoicePaid = (0, _debounce.default)(async () => { _Toast.default.close(); _Toast.default.success(t("payment.customer.invoice.paySuccess")); await reloadAsync(); }, 1e3, { leading: false, trailing: true, maxWait: 5e3 }); (0, _react.useEffect)(() => { if (subscription && customer_id) { subscription.on("invoice.paid", ({ response }) => { if (response.customer_id === customer_id) { debouncedHandleInvoicePaid(); } }); } }, [subscription]); if (loading || !data) { return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.CircularProgress, {}); } if (data && data.list.length === 0) { if (data.subscription && ["active", "trialing"].includes(data.subscription.status)) { return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, { sx: { color: "text.secondary", my: 0.5 }, children: t("payment.customer.invoice.next", { date: (0, _util2.formatToDatetime)(data.subscription.current_period_end * 1e3) }) }); } return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, { sx: { color: "text.secondary", my: 0.5 }, children: t("payment.customer.invoice.empty") }); } const hasMore = data && data.list.length < data.count; const grouped = groupByDate(data.list); const handleLinkClick = (e, link) => { (0, _navigation.handleNavigation)(e, link, navigate, { target: link.external ? "_blank" : target }); }; return /* @__PURE__ */(0, _jsxRuntime.jsxs)(Root, { direction: "column", gap: 1, sx: { mt: 1 }, children: [Object.entries(grouped).map(([date, invoices]) => /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, { children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, { sx: { fontWeight: "bold", color: "text.secondary", mt: 2, mb: 1 }, children: date }), invoices.map(invoice => { const { link, connect } = getInvoiceLink(invoice, action); const isVoid = invoice.status === "void"; const quoteInfo = getInvoiceQuoteInfo(invoice); const formattedRate = (0, _util2.formatExchangeRate)(quoteInfo?.exchange_rate || null); const rateLine = formattedRate ? `1 ${invoice.paymentCurrency.symbol} \u2248 ${formattedRate} ${quoteInfo?.base_currency || "USD"}` : null; return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, { direction: "row", sx: { gap: { xs: 0.5, sm: 1.5, md: 3 }, alignItems: "center", flexWrap: "nowrap", my: 1 }, children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, { sx: { flex: 2 }, children: /* @__PURE__ */(0, _jsxRuntime.jsx)("a", { href: link.url, target: link.external ? "_blank" : target, rel: "noreferrer", onClick: e => handleLinkClick(e, link), children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, { direction: "row", spacing: 0.5, sx: { alignItems: "center" }, children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, { component: "span", children: invoice.number }), link.external && /* @__PURE__ */(0, _jsxRuntime.jsx)(_iconsMaterial.OpenInNewOutlined, { fontSize: "small", sx: { color: "text.secondary", display: { xs: "none", md: "inline-flex" } } })] }) }) }), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, { sx: { flex: 1, textAlign: "right" }, children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, { sx: isVoid ? { textDecoration: "line-through" } : {}, children: [(0, _util2.formatAmount)(invoice.total, invoice.paymentCurrency.decimal), "\xA0", invoice.paymentCurrency.symbol] }), rateLine && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, { variant: "caption", sx: { color: "text.secondary", display: "block" }, children: rateLine })] }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Tooltip, { title: invoice.subscription_id && invoice.period_start && invoice.period_end ? `${t("common.billingPeriod")}: ${(0, _util2.formatToDate)(invoice.period_start * 1e3, locale, "YYYY-MM-DD HH:mm")} ~ ${(0, _util2.formatToDate)(invoice.period_end * 1e3, locale, "YYYY-MM-DD HH:mm")}` : "", arrow: true, placement: "top-start", children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, { sx: { flex: 1, textAlign: "right" }, children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, { children: (0, _util2.formatToDate)(invoice.created_at, locale, "HH:mm:ss") }) }) }), !action && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, { className: "invoice-description", sx: { flex: 2, textAlign: "right", display: { xs: "none", lg: "inline-flex" } }, children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, { children: invoice.description || invoice.id }) }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, { sx: { flex: 1, textAlign: "right" }, children: action ? connect ? invoice.paymentMethod?.type === "stripe" ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_stripePaymentAction.default, { invoice, paymentMethod: invoice.paymentMethod, onSuccess: async () => { await reloadAsync(); }, children: (handlePay, paying) => /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, { variant: "contained", color: "primary", size: "small", sx: { whiteSpace: "nowrap" }, disabled: paying, onClick: e => { e.preventDefault(); e.stopPropagation(); handlePay(); }, children: paying ? t("payment.checkout.processing") : t("payment.customer.invoice.pay") }) }) : /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, { variant: "contained", color: "primary", size: "small", onClick: () => onPay(invoice.id), sx: { whiteSpace: "nowrap" }, children: t("payment.customer.invoice.pay") }) : /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, { component: "a", variant: "contained", size: "small", onClick: e => handleLinkClick(e, link), sx: { whiteSpace: "nowrap" }, rel: "noreferrer", children: t("payment.customer.invoice.pay") }) : isVoid ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Tooltip, { title: t("payment.customer.invoice.noPaymentRequired"), arrow: true, placement: "top", children: /* @__PURE__ */(0, _jsxRuntime.jsx)("span", { children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_status.default, { label: invoice.status, color: (0, _util2.getInvoiceStatusColor)(invoice.status) }) }) }) : /* @__PURE__ */(0, _jsxRuntime.jsx)(_status.default, { label: invoice.status, color: (0, _util2.getInvoiceStatusColor)(invoice.status) }) })] }, invoice.id); })] }, date)), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, { children: [hasMore && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Button, { variant: "text", type: "button", color: "inherit", onClick: loadMore, disabled: loadingMore, children: loadingMore ? t("common.loadingMore", { resource: t("payment.customer.invoices") }) : t("common.loadMore", { resource: t("payment.customer.invoices") }) }), !hasMore && data.count > size && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, { sx: { color: "text.secondary" }, children: t("common.noMore", { resource: t("payment.customer.invoices") }) })] })] }); }); function CustomerInvoiceList(rawProps) { const props = Object.assign({ customer_id: "", subscription_id: "", currency_id: "", include_staking: false, include_recovered_from: false, status: "open,paid,uncollectible", pageSize: 10, target: "_self", action: "", type: "list", onTableDataChange: () => {}, relatedSubscription: false }, rawProps); const { action, type } = props; const { t, locale } = (0, _context.useLocaleContext)(); const { connect } = (0, _payment.usePaymentContext)(); const [state, setState] = (0, _ahooks.useSetState)({ paying: "" }); const onPay = invoiceId => { if (state.paying) { return; } setState({ paying: invoiceId }); connect.open({ action: "collect", saveConnect: false, locale, useSocket: (0, _util2.isCrossOrigin)() === false, messages: { scan: "", title: t(`payment.customer.invoice.${action || "pay"}`), success: t(`payment.customer.invoice.${action || "pay"}Success`), error: t(`payment.customer.invoice.${action || "pay"}Error`), confirm: "" }, extraParams: { invoiceId, action }, onSuccess: () => { connect.close(); setState({ paying: "" }); }, onClose: () => { connect.close(); setState({ paying: "" }); }, onError: err => { setState({ paying: "" }); _Toast.default.error((0, _util2.formatError)(err)); } }); }; if (type === "table") { return /* @__PURE__ */(0, _jsxRuntime.jsx)(InvoiceTable, { ...props, onPay }); } return /* @__PURE__ */(0, _jsxRuntime.jsx)(InvoiceList, { ...props, onPay }); } const Root = (0, _system.styled)(_material.Stack)` @media (max-width: ${({ theme }) => theme.breakpoints.values.md}px) { svg.MuiSvgIcon-root { display: none !important; } } a.MuiButton-root { text-decoration: none !important; } `;