import React, { useEffect, useMemo, useState } from 'react';
import {
MaterialReactTable,
useMaterialReactTable,
type MRT_ColumnDef,
MRT_EditActionButtons,
MRT_Row,
} from 'material-react-table';
import { Box, Button, DialogActions, DialogContent, DialogTitle, IconButton, InputAdornment, MenuItem, Pagination, Select, TextField, Tooltip, Typography } from '@mui/material';
import { Search, Clear, Edit, Delete } from '@mui/icons-material';
type ArgInstance = {
data?: any[];
api?: any;
columns: MRT_ColumnDef<any>[];
loading?: boolean;
enablePager?: boolean;
searchParam?: any;
};
type Setting = {
enablePager?: boolean;
searchParam?: any;
};
type State = {
loading?: boolean;
};
type TableInstance = {
data: ArgInstance,
settings?: Setting;
state?: State;
leftForm?: any;
rightForm?: any;
topForm?: any;
};
const loadingErrorMessage = 'Loading Error';
const MaterialStaticTable = (props: TableInstance) => {
//should be memoized or stable
const { data, columns, } = props.data;
const showRowsPage: any = [10, 20, 30, 50];
const [enableColumnOrdering, setEnableColumnOrdering] = useState(true);
const [enableRowVirtual, setEnableRowVirtual] = useState(true);
const [isError, setIsError] = useState(false);
const [isLoading, setIsLoading] = useState(props.state?.loading || false);
const [isFetching, setIsFetching] = useState(false);
const [globalFilter, setGlobalFilter] = useState('');
const [frontPager, setFrontPager] = useState(true);
const [tableData, setTableData] = useState<any[]>(data || []);
const [pagination, setPagination] = useState({
pageIndex: frontPager ? 0 : 1, // 对于支持后端分页的接口0页代表查所有
pageSize: 10,
});
const [columnsData, setColumnsData] = useState<any>(columns || []);
const [isEnablePager, setIsEnablePager] = useState(props.data.enablePager || true);
const [rowCount, setRowCount] = useState(tableData?.length || 0);
const [totalPage, setTotalPage] = useState(Math.ceil((tableData?.length ?? 0) / pagination.pageSize || 10));
const [searchCondition, setSearchCondition] = useState('');
const [tablesReqInfo, setTablesReqInfo] = useState<any>(null);
const [tablesData, setTablesData] = useState(data || []);
const [filterString, setFilterString] = useState<any>('');
const [loadTime, setLoadTime] = useState<any>(0);
//DELETE action
const openDeleteConfirmModal = (row: MRT_Row<any>) => {
if (window.confirm('Are you sure you want to delete this user?')) {
// deleteUser(row.original.id);
console.log('delete user', row.original, row.original.id);
setTableData(tableData.filter((item) => item.id !== row.original?.id))
}
};
const refreshTable = () => {
// Refresh table logic here
};
useEffect(() => {
// console.log('tableData', tableData);
setRowCount(tableData?.length || 0);
setTotalPage(Math.ceil((tableData?.length ?? 0) / pagination.pageSize || 10));
}, [tableData]);
const table = useMaterialReactTable({
columns: columns,
data: tableData,
enablePagination: isEnablePager,
enableRowVirtualization: !enableRowVirtual,
muiCircularProgressProps: {
color: 'warning',
thickness: 5,
size: 80,
},
muiSkeletonProps: {
animation: 'pulse',
height: 28,
},
// enableColumnVirtualization: enableColumnVirtualization,
initialState: {
// pagination,
// density: 'compact', // 表格紧密 compact comfortable
// showGlobalFilter: !isPrint,
// ...customState,
},
// 当包含2时禁止选择
muiSelectCheckboxProps: ({ row }) => ({
disabled: row.original.state.indexOf("2") > 0,
}),
manualPagination: !frontPager, // 是否前端分页(接口请求走后端分页)
rowCount: rowCount, // 数据总数
pageCount: pagination.pageSize,
state: {
pagination,
// pagination: pagination,
isLoading: isLoading,
showAlertBanner: isError,
showProgressBars: isFetching,
},
muiSearchTextFieldProps: {
placeholder: 'Search Column Options',
sx: { minWidth: '18rem' },
variant: 'outlined',
},
muiTablePaperProps: {
sx: { mb: '1.5rem' },
id: 'relevant-column-options-table'//'column-options-table',
},
// rowNumberDisplayMode: "static",
// renderDetailPanel: ({ row }) => (
// <Typography
// color={row.original.description ? 'secondary.main' : 'text.secondary'}
// >
// {row.original.description || 'No Description Provided... Yet...'}
// </Typography>
// ),
// muiPaginationProps: {
// color: 'primary',
// showRowsPerPage: false,
// rowsPerPageOptions: showRowsPage, //showRowsPage,
// shape: 'rounded',
// variant: 'outlined',
// size: 'small',
// defaultPage: frontPager ? 0 : 1,
// count: totalPage,
// page: (frontPager ? 1 : 0) + pagination.pageIndex,
// onChange: (event, page) => {
// // fix default page init to 0 cause two request
// // console.log('onchange', (frontPager ? -1 : 0) + page, page);
// setPagination({ ...pagination, ...{ pageIndex: (frontPager ? -1 : 0) + page } });
// },
// },
// defaultColumn: {
// minSize: 1,
// maxSize: 100,
// // size: document.body.clientWidth / columns.length - 3,
// },
paginationDisplayMode: 'pages',
// enableStickyHeader: true,
enableStickyFooter: true,
enableColumnOrdering: enableColumnOrdering,
enableColumnResizing: true, //false为自动分布行
layoutMode: 'grid',
enableFullScreenToggle: false, // 全屏
enableColumnDragging: true, // 列拖拽
enableDensityToggle: false, // 密度
enableColumnActions: false, // 列操作
enableFilters: true, // 控制全局过滤以及每一列过滤(开启会导致表格右上角出现过滤框)
manualFiltering: true,
// enableColumnVirtualization: true,//虚拟滚动
enableGlobalFilter: false, // /searchFromEnd,
positionGlobalFilter: 'right', // "left",
///
onGlobalFilterChange: setGlobalFilter,
onColumnFiltersChange: (filterData: any) => { },
onShowColumnFiltersChange: (filterData: any) => { },
enableColumnFilterModes: true,// 开启列过滤模式
///
// columnFilterDisplayMode: "custom",
enableRowNumbers: true,
// enableRowDragging: true,
enableTableHead: true,
enableMultiSort: true,
manualSorting: false, // 手动排序
enableEditing: true,
editDisplayMode: 'modal', //default
onEditingRowSave: ({ table, values }) => {
//validate data
//save data to api
console.log('onEditingRowSave', table, values);
table.setEditingRow(null); //exit editing mode
},
// muiEditTextFieldProps: ({ cell, row, table }) => ({
// onBlur: (event) => {
// //validate data
// //save data to api and/or rerender table
// // table.setEditingCell(null) is called automatically onBlur internally
// },
// }),
onEditingRowCancel: () => {
//clear any validation errors
},
// custom edit components
// 自定义编辑组件
renderEditRowDialogContent: ({ table, row, internalEditComponents }) => (
<>
<DialogTitle variant="h3">Edit User(Info)</DialogTitle>
<DialogContent
sx={{ display: 'flex', flexDirection: 'column', gap: '1.5rem' }}
>
{internalEditComponents}
<Box>or render custom edit components here</Box>
</DialogContent>
<DialogActions>
<MRT_EditActionButtons variant="text" table={table} row={row} />
</DialogActions>
</>
),
// 行操作
renderRowActions: ({ row, table }) => (
<Box sx={{ display: 'flex', gap: '1rem' }}>
<Tooltip title="Edit">
<IconButton onClick={() => table.setEditingRow(row)}>
<Edit />
</IconButton>
</Tooltip>
<Tooltip title="Delete">
<IconButton color="error" onClick={() => openDeleteConfirmModal(row)}>
<Delete />
</IconButton>
</Tooltip>
</Box>
),
enableRowActions: true,
enableRowSelection: true,// 允许行选择
enableGrouping: false,
enableHiding: true,
enableSorting: true,
// defaultColumn: {
// minSize: 40,
// maxSize: 1000,
// size: 180,
// },
// muiTableContainerProps: {
// sx: {
// },
// },
muiTableBodyProps: {
sx: {
maxHeight: isEnablePager ? '700px' || '600px' : 'unset',
overflowY: 'auto',
minHeight: '600px',
},
},
muiTableBodyRowProps: ({ row }: any) => {
let { original } = row;
let custStyle: any = {};
// if (original.moreLabRecordFound === true) {
// custStyle.background = '#F7EAC1';
// }
// if (original.moreLabRecordFound === false) {
// custStyle.background = '#FFC4C4';
// }
return {
sx: { ...custStyle },
className: '',
};
},
// muiTableBodyRowProps: muiTableBodyRowProps,
muiTableBodyCellProps: ({ cell, column, table }) => ({
onClick: () => {
table.setEditingCell(cell); //set editing cell
//optionally, focus the text field
queueMicrotask(() => {
const textField = table.refs.editInputRefs.current[column.id];
if (textField) {
textField.focus();
textField.select?.();
}
});
},
}),
renderTopToolbarCustomActions: () => (
<Box className="m-r-10 table_top_left">
<Box className="flex flex-1">
<Button
onClick={() => {
table.setCreatingRow(true); //simplest way to open the create row modal with no default values
//or you can pass in a row object to set default values with the `createRow` helper function
// table.setCreatingRow(
// createRow(table, {
// //optionally pass in default values for the new row, useful for nested data or other complex scenarios
// }),
// );
}}
>
Create New User
</Button>
{props.leftForm ?? " "}
</Box>
</Box>
),
renderToolbarInternalActions: ({ table }) => {
return (
<>
<Box className="visibleNotPrinter">
<TextField
name="searchCondition"
onChange={(e: any) => {
setGlobalFilter(e.target.value || '');
}}
value={globalFilter}
autoComplete="off"
InputProps={{
startAdornment: (
<InputAdornment position="start">
<Search
onClick={() => {
setLoadTime(new Date());
}}
sx={{ cursor: 'pointer' }}
/>
</InputAdornment>
),
endAdornment: (
<InputAdornment position="start">
<Clear
onClick={() => {
setGlobalFilter('');
}}
sx={{ cursor: 'pointer' }}
/>
</InputAdornment>
),
}}
/>
</Box>
</>
);
},
// muiBottomToolbarProps: {
// sx: {
// // display: "inline-block",
// display: "flex",
// width: "100%",
// },
// },
muiTableFooterCellProps: {
sx: {
display: 'flex',
width: '45%',
float: 'right',
},
},
// renderBottomToolbarCustomActions: () => (
// <Box className="f-r f-s-14">
// <span className="total_counts">Total {rowCount} Records</span>
// </Box>
// ),
renderBottomToolbar: () => (
<Box sx={{
display: 'flex',
width: '100%',
padding: '10px',
justifyContent: 'space-between',
alignItems: 'center',
}}>
<Box>
<span >Total {rowCount} Records</span>{' '}
</Box>
<Box sx={{ display: 'flex', justifyContent: 'center', alignContent: 'center' }}>
<Box>
<span >Rows Per Page:</span>
<Select
disabled={isLoading}
value={pagination.pageSize}
onChange={(event: any) => {
setPagination({
...pagination,
pageSize: event?.target?.value || 10,
pageIndex: frontPager ? 0 : 1
});
const pageCount = tablesData.length > 0
? Math.ceil(tablesData.length / event?.target?.value || 10)
: 0;
setTotalPage(pageCount);
}}
>
{showRowsPage.map((pageItem: any, indexItem: number) => (
<MenuItem key={indexItem} value={pageItem}>
{pageItem}
</MenuItem>
))}
</Select>
</Box>
<Pagination
disabled={isLoading}
showFirstButton
showLastButton
shape="rounded"
page={pagination.pageIndex + (frontPager ? 1 : 0)}
count={totalPage} sx={{ display: 'flex', justifyContent: 'center', alignContent: 'center', marginRight: '20px' }}
onChange={(event: any, page: number) => {
setPagination({
...pagination,
pageIndex: (frontPager ? -1 : 0) + page
});
}}
/>
</Box>
</Box>
),
muiToolbarAlertBannerProps: isError
? {
color: 'error',
children: loadingErrorMessage,
}
: undefined,
});
return <MaterialReactTable table={table} />;
};
07-12
7435
