import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Button, } from '@mui/material'; import { useSetAtom } from 'jotai'; import { forwardRef } from 'react'; import { TableVirtuoso, TableComponents } from 'react-virtuoso'; import { forSaleAtom, Names, namesAtom, NamesForSale, pendingTxsAtom, PendingTxsState, } from '../../state/global/names'; import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward'; import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward'; import { dismissToast, showError, showLoading, showSuccess } from 'qapp-core'; import { SetStateAction } from 'jotai'; import { SortBy, SortDirection } from '../../interfaces'; const VirtuosoTableComponents: TableComponents = { Scroller: forwardRef((props, ref) => ( )), Table: (props) => ( ), TableHead: forwardRef((props, ref) => ( )), TableRow, TableBody: forwardRef((props, ref) => ( )), }; function fixedHeaderContent( sortBy: string, sortDirection: string, setSort: (field: SortBy) => void ) { const renderSortIcon = (field: string) => { if (sortBy !== field) return null; return sortDirection === 'asc' ? ( ) : ( ); }; const sortableCellSx = { cursor: 'pointer', '&:hover': { backgroundColor: 'action.selected', }, }; return ( setSort('name')} sx={sortableCellSx}> Name {renderSortIcon('name')} setSort('salePrice')} sx={sortableCellSx}> Sale Price {renderSortIcon('salePrice')} Actions ); } type SetPendingTxs = (update: SetStateAction) => void; type SetNames = (update: SetStateAction) => void; type SetNamesForSale = (update: SetStateAction) => void; function rowContent( _index: number, row: NamesForSale, setPendingTxs: SetPendingTxs, setNames: SetNames, setNamesForSale: SetNamesForSale, isPrimaryNameForSale: boolean ) { const handleBuy = async (name: string) => { const loadId = showLoading('Attempting to purchase name...please wait'); try { const res = await qortalRequest({ action: 'BUY_NAME', nameForSale: name, }); showSuccess('Purchased name'); setPendingTxs((prev) => { return { ...prev, // preserve existing categories ['BUY_NAME']: { ...(prev['BUY_NAME'] || {}), // preserve existing transactions in this category [res.signature]: { ...res, status: 'PENDING', callback: () => { setNamesForSale((prev) => prev.filter((item) => item?.name !== res.name) ); setNames((prev) => [ ...prev, { name: res.name, owner: res.creatorAddress, }, ]); }, }, // add or overwrite this transaction }, }; }); } catch (error) { if (error instanceof Error) { showError(error?.message); return; } showError('Unable to purchase name'); } finally { dismissToast(loadId); } }; return ( <> {row.name} {row.salePrice} ); } interface ForSaleTable { namesForSale: NamesForSale[]; sortDirection: SortDirection; sortBy: SortBy; handleSort: (sortBy: SortBy) => void; isPrimaryNameForSale: boolean; } export const ForSaleTable = ({ namesForSale, sortDirection, sortBy, handleSort, isPrimaryNameForSale, }: ForSaleTable) => { const setNames = useSetAtom(namesAtom); const setNamesForSale = useSetAtom(forSaleAtom); const setPendingTxs = useSetAtom(pendingTxsAtom); return ( fixedHeaderContent(sortBy, sortDirection, handleSort) } itemContent={(index, row: NamesForSale) => rowContent( index, row, setPendingTxs, setNames, setNamesForSale, isPrimaryNameForSale ) } /> ); };