/* eslint-disable @typescript-eslint/indent */ /* eslint-disable react/require-default-props */ /* eslint-disable react/no-unused-prop-types */ /* eslint-disable @typescript-eslint/naming-convention */ /* eslint-disable no-nested-ternary */ /* eslint-disable react/no-unstable-nested-components */ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context'; import type { Paginated, TCreditGrantExpanded } from '@blocklet/payment-types'; import { Box, Typography, Chip } from '@mui/material'; import { useRequest } from 'ahooks'; import React, { useEffect, useRef, useState } from 'react'; // eslint-disable-next-line import/no-extraneous-dependencies import { useNavigate } from 'react-router-dom'; import { styled } from '@mui/system'; import { formatToDate, formatCreditAmount, formatBNStr } from '../../libs/util'; import { usePaymentContext } from '../../contexts/payment'; import api from '../../libs/api'; import Table from '../../components/table'; import { createLink, handleNavigation } from '../../libs/navigation'; type Result = Paginated; const fetchData = (params: Record = {}): Promise => { const search = new URLSearchParams(); Object.keys(params).forEach((key) => { if (params[key]) { search.set(key, String(params[key])); } }); return api.get(`/api/credit-grants?${search.toString()}`).then((res: any) => res.data); }; type Props = { customer_id?: string; subscription_id?: string; status?: string; pageSize?: number; onTableDataChange?: Function; mode?: 'dashboard' | 'portal'; }; export function StatusChip({ status, label }: { status: string; label?: string }) { const getStatusColor = (statusValue: string) => { switch (statusValue) { case 'granted': return 'success'; case 'pending': return 'warning'; case 'expired': return 'default'; case 'depleted': return 'default'; case 'voided': return 'default'; default: return 'default'; } }; return ; } const getLink = (grant: TCreditGrantExpanded, inDashboard: boolean) => { let path = `/customer/credit-grant/${grant.id}`; if (inDashboard) { path = `/admin/customers/${grant.id}`; } return { link: createLink(path), connect: false, }; }; const GrantsTable = React.memo((props: Props) => { const { pageSize, status = '', customer_id, subscription_id, onTableDataChange } = props; const listKey = 'credit-grants-table'; const { t, locale } = useLocaleContext(); const { session } = usePaymentContext(); const navigate = useNavigate(); const isAdmin = ['owner', 'admin'].includes(session?.user?.role || ''); const inDashboard = props.mode === 'dashboard' && isAdmin; // 如果没有传入 customer_id,使用当前登录用户的 DID const effectiveCustomerId = customer_id || session?.user?.did; const [search, setSearch] = useState<{ pageSize: number; page: number }>({ pageSize: pageSize || 10, page: 1, }); const { loading, data = { list: [], count: 0 } } = useRequest( () => fetchData({ ...search, status, customer_id: effectiveCustomerId, subscription_id, }), { refreshDeps: [search, status, effectiveCustomerId, subscription_id], } ); const prevData = useRef(data); const handleLinkClick = (e: React.MouseEvent, grant: TCreditGrantExpanded) => { const { link } = getLink(grant, inDashboard); handleNavigation(e, link, navigate, { target: link.external ? '_blank' : '_self' }); }; useEffect(() => { if (onTableDataChange) { onTableDataChange(data, prevData.current); prevData.current = data; } // eslint-disable-next-line react-hooks/exhaustive-deps }, [data]); const columns = [ { label: t('common.name'), name: 'name', options: { customBodyRenderLite: (_: string, index: number) => { const grant = data?.list[index] as TCreditGrantExpanded; return handleLinkClick(e, grant)}>{grant.name || grant.id}; }, }, }, { label: t('common.status'), name: 'status', options: { customBodyRenderLite: (_: string, index: number) => { const grant = data?.list[index] as TCreditGrantExpanded; return ( handleLinkClick(e, grant)}> ); }, }, }, { label: t('common.remainingCredit'), name: 'remaining_amount', align: 'right', options: { customBodyRenderLite: (_: string, index: number) => { const grant = data?.list[index] as TCreditGrantExpanded; return ( handleLinkClick(e, grant)}> {formatCreditAmount( formatBNStr(grant.remaining_amount, grant.paymentCurrency.decimal), grant.paymentCurrency.symbol )} ); }, }, }, { label: t('common.scope'), name: 'scope', options: { customBodyRenderLite: (_: string, index: number) => { const grant = data?.list[index] as TCreditGrantExpanded; let scope = 'general'; if (grant.applicability_config?.scope?.prices) { scope = 'specific'; } return ( handleLinkClick(e, grant)}> {scope === 'specific' ? t('common.specific') : t('common.general')} ); }, }, }, { label: t('common.effectiveDate'), name: 'effective_at', options: { customBodyRenderLite: (_: string, index: number) => { const grant = data?.list[index] as TCreditGrantExpanded; const effectiveAt = grant.effective_at ? grant.effective_at * 1000 : grant.created_at; return ( handleLinkClick(e, grant)}> {formatToDate(effectiveAt, locale, 'YYYY-MM-DD HH:mm')} ); }, }, }, { label: t('common.expirationDate'), name: 'expires_at', options: { customBodyRenderLite: (_: string, index: number) => { const grant = data?.list[index] as TCreditGrantExpanded; return ( handleLinkClick(e, grant)}> {grant.expires_at ? formatToDate(grant.expires_at * 1000, locale, 'YYYY-MM-DD HH:mm') : '-'} ); }, }, }, ]; const onTableChange = ({ page, rowsPerPage }: any) => { if (search.pageSize !== rowsPerPage) { setSearch((x) => ({ ...x, pageSize: rowsPerPage, page: 1 })); } else if (search.page !== page + 1) { setSearch((x) => ({ ...x, page: page + 1 })); } }; return ( ); }); const TableRoot = styled(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; } } `; export default function CreditGrantsList(rawProps: Props) { const props = Object.assign( { customer_id: '', subscription_id: '', status: 'granted,pending,depleted,expired', pageSize: 10, onTableDataChange: () => {}, }, rawProps ); return ; }