improved datatable

This commit is contained in:
Boki 2025-06-18 07:54:42 -04:00
parent 344478c577
commit 7f4a70309c
2 changed files with 137 additions and 175 deletions

View file

@ -13,20 +13,17 @@ export function ExchangesTable() {
error,
updateExchange,
fetchExchangeDetails,
fetchProviderMappings,
updateProviderMapping,
createProviderMapping,
refetch
} = useExchanges();
console.log('ExchangesTable render:', { exchanges, loading, error });
const [editingCell, setEditingCell] = useState<{ id: string; field: string } | null>(null);
const [editValue, setEditValue] = useState('');
const [addProviderDialog, setAddProviderDialog] = useState<{
exchangeId: string;
exchangeName: string;
} | null>(null);
const [expandedRows, setExpandedRows] = useState<Set<string>>(new Set());
const [expandedRowData, setExpandedRowData] = useState<Record<string, ProviderMapping[]>>({});
const handleCellEdit = useCallback(
@ -61,59 +58,50 @@ export function ExchangesTable() {
[updateProviderMapping, refetch]
);
const handleToggleExpandRow = useCallback(async (rowId: string) => {
setExpandedRows(prev => {
const next = new Set(prev);
if (next.has(rowId)) {
next.delete(rowId);
} else {
next.add(rowId);
// Load provider mappings for this exchange
if (!expandedRowData[rowId]) {
fetchExchangeDetails(rowId).then(details => {
if (details) {
setExpandedRowData(prev => ({
...prev,
[rowId]: details.provider_mappings
}));
}
});
const handleRowExpand = useCallback(
async (row: any) => {
const exchangeId = row.original.id;
if (!expandedRowData[exchangeId]) {
const details = await fetchExchangeDetails(exchangeId);
if (details) {
setExpandedRowData(prev => ({
...prev,
[exchangeId]: details.provider_mappings
}));
}
}
return next;
});
}, [fetchExchangeDetails, expandedRowData]);
},
[fetchExchangeDetails]
);
const columns = useMemo<ColumnDef<Exchange>[]>(() => {
return [
{
id: 'expand',
id: 'expander',
header: '',
size: 30,
enableResizing: false,
cell: ({ row }) => {
const isExpanded = expandedRows.has(row.original.id);
return (
return row.getCanExpand() ? (
<button
onClick={() => handleToggleExpandRow(row.original.id)}
className="text-text-secondary hover:text-text-primary transition-colors"
onClick={() => {
row.getToggleExpandedHandler()();
handleRowExpand(row);
}}
className="text-text-secondary hover:text-text-primary transition-colors w-6 h-6 flex items-center justify-center"
>
{isExpanded ? '▼' : '▶'}
{row.getIsExpanded() ? '▼' : '▶'}
</button>
);
) : null;
},
size: 40,
enableResizing: false,
},
{
id: 'id',
header: 'ID',
accessorKey: 'id',
size: 50,
enableResizing: false,
cell: ({ getValue, cell }) => (
<span
className="font-mono text-primary-400 text-xs"
style={{ width: cell.column.getSize() }}
>
size: 80,
cell: ({ getValue }) => (
<span className="font-mono text-primary-400 text-xs">
{getValue() as string}
</span>
),
@ -122,13 +110,9 @@ export function ExchangesTable() {
id: 'code',
header: 'Code',
accessorKey: 'code',
size: 80,
enableResizing: false,
cell: ({ getValue, cell }) => (
<span
className="font-mono text-text-primary text-sm font-medium"
style={{ width: cell.column.getSize() }}
>
size: 100,
cell: ({ getValue }) => (
<span className="font-mono text-text-primary text-sm font-medium">
{getValue() as string}
</span>
),
@ -137,9 +121,7 @@ export function ExchangesTable() {
id: 'name',
header: 'Name',
accessorKey: 'name',
size: 200,
maxSize: 300,
enableResizing: true,
size: 250,
cell: ({ getValue, row, cell }) => {
const isEditing =
editingCell?.id === row.original.id && editingCell?.field === 'name';
@ -184,7 +166,6 @@ export function ExchangesTable() {
header: 'Country',
accessorKey: 'country',
size: 80,
maxSize: 80,
cell: ({ getValue }) => (
<span className="text-text-secondary text-sm">{getValue() as string}</span>
),
@ -193,7 +174,7 @@ export function ExchangesTable() {
id: 'currency',
header: 'Currency',
accessorKey: 'currency',
size: 70,
size: 80,
cell: ({ getValue, cell }) => (
<span
className="font-mono text-text-secondary text-sm"
@ -208,7 +189,6 @@ export function ExchangesTable() {
header: 'Active',
accessorKey: 'active',
size: 80,
maxSize: 80,
cell: ({ getValue, row, cell }) => {
const isActive = getValue() as boolean;
return (
@ -231,7 +211,7 @@ export function ExchangesTable() {
id: 'provider_mappings',
header: 'Provider Mappings',
accessorKey: 'provider_mapping_count',
size: 150,
size: 180,
cell: ({ getValue, row }) => {
const totalMappings = parseInt(getValue() as string) || 0;
const activeMappings = parseInt(row.original.active_mapping_count) || 0;
@ -265,7 +245,7 @@ export function ExchangesTable() {
{
id: 'actions',
header: 'Actions',
size: 100,
size: 120,
cell: ({ row }) => (
<button
onClick={() => handleAddProviderMapping(row.original.id, row.original.name)}
@ -282,7 +262,6 @@ export function ExchangesTable() {
header: 'Last Updated',
accessorKey: 'updated_at',
size: 120,
maxSize: 120,
cell: ({ getValue }) => (
<span className="text-xs text-text-muted">
{new Date(getValue() as string).toLocaleDateString()}
@ -293,11 +272,10 @@ export function ExchangesTable() {
}, [
editingCell,
editValue,
expandedRows,
handleCellEdit,
handleToggleActive,
handleAddProviderMapping,
handleToggleExpandRow,
handleRowExpand,
]);
if (error) {
@ -312,7 +290,8 @@ export function ExchangesTable() {
);
}
const renderExpandedRow = (exchange: Exchange) => {
const renderSubComponent = ({ row }: { row: any }) => {
const exchange = row.original as Exchange;
const mappings = expandedRowData[exchange.id] || [];
if (mappings.length === 0) {
@ -383,36 +362,16 @@ export function ExchangesTable() {
);
};
console.log('About to render DataTable with:', {
dataLength: (exchanges || []).length,
columnsLength: columns.length,
loading,
error
});
return (
<>
<div className="space-y-0">
<DataTable
data={exchanges || []}
columns={columns}
loading={loading}
height={600}
className="rounded-lg border border-border"
/>
{/* Expanded rows */}
{Array.from(expandedRows).map(exchangeId => {
const exchange = exchanges?.find(e => e.id === exchangeId);
if (!exchange) return null;
return (
<div key={`expanded-${exchangeId}`} className="border-l border-r border-b border-border rounded-b-lg -mt-1">
{renderExpandedRow(exchange)}
</div>
);
})}
</div>
<DataTable
data={exchanges || []}
columns={columns}
loading={loading}
className="max-h-[calc(100vh-300px)]"
getRowCanExpand={() => true}
renderSubComponent={renderSubComponent}
/>
{addProviderDialog && (
<AddProviderMappingDialog