import * as React from 'react';
|
import PropTypes from 'prop-types';
|
import { alpha } from '@mui/material/styles';
|
import Box from '@mui/material/Box';
|
import Table from '@mui/material/Table';
|
import TableBody from '@mui/material/TableBody';
|
import TableCell from '@mui/material/TableCell';
|
import TableContainer from '@mui/material/TableContainer';
|
import TableHead from '@mui/material/TableHead';
|
import TablePagination from '@mui/material/TablePagination';
|
import TableRow from '@mui/material/TableRow';
|
import TableSortLabel from '@mui/material/TableSortLabel';
|
import Toolbar from '@mui/material/Toolbar';
|
import Typography from '@mui/material/Typography';
|
import Paper from '@mui/material/Paper';
|
import Checkbox from '@mui/material/Checkbox';
|
import IconButton from '@mui/material/IconButton';
|
import Tooltip from '@mui/material/Tooltip';
|
import FormControlLabel from '@mui/material/FormControlLabel';
|
import Switch from '@mui/material/Switch';
|
import DeleteIcon from '@mui/icons-material/Delete';
|
import FilterListIcon from '@mui/icons-material/FilterList';
|
import { visuallyHidden } from '@mui/utils';
|
|
function createData(id, name, calories, fat, carbs, protein) {
|
return {
|
id,
|
name,
|
calories,
|
fat,
|
carbs,
|
protein,
|
};
|
}
|
|
const rows = [
|
createData(1, 'Cupcake', 305, 3.7, 67, 4.3),
|
createData(2, 'Donut', 452, 25.0, 51, 4.9),
|
createData(3, 'Eclair', 262, 16.0, 24, 6.0),
|
createData(4, 'Frozen yoghurt', 159, 6.0, 24, 4.0),
|
createData(5, 'Gingerbread', 356, 16.0, 49, 3.9),
|
createData(6, 'Honeycomb', 408, 3.2, 87, 6.5),
|
createData(7, 'Ice cream sandwich', 237, 9.0, 37, 4.3),
|
createData(8, 'Jelly Bean', 375, 0.0, 94, 0.0),
|
createData(9, 'KitKat', 518, 26.0, 65, 7.0),
|
createData(10, 'Lollipop', 392, 0.2, 98, 0.0),
|
createData(11, 'Marshmallow', 318, 0, 81, 2.0),
|
createData(12, 'Nougat', 360, 19.0, 9, 37.0),
|
createData(13, 'Oreo', 437, 18.0, 63, 4.0),
|
];
|
|
function descendingComparator(a, b, orderBy) {
|
if (b[orderBy] < a[orderBy]) {
|
return -1;
|
}
|
if (b[orderBy] > a[orderBy]) {
|
return 1;
|
}
|
return 0;
|
}
|
|
function getComparator(order, orderBy) {
|
return order === 'desc'
|
? (a, b) => descendingComparator(a, b, orderBy)
|
: (a, b) => -descendingComparator(a, b, orderBy);
|
}
|
|
const headCells = [
|
{
|
id: 'name',
|
numeric: false,
|
disablePadding: true,
|
label: 'Dessert (100g serving)',
|
},
|
{
|
id: 'calories',
|
numeric: true,
|
disablePadding: false,
|
label: 'Calories',
|
},
|
{
|
id: 'fat',
|
numeric: true,
|
disablePadding: false,
|
label: 'Fat (g)',
|
},
|
{
|
id: 'carbs',
|
numeric: true,
|
disablePadding: false,
|
label: 'Carbs (g)',
|
},
|
{
|
id: 'protein',
|
numeric: true,
|
disablePadding: false,
|
label: 'Protein (g)',
|
},
|
];
|
|
function EnhancedTableHead(props) {
|
const { onSelectAllClick, order, orderBy, numSelected, rowCount, onRequestSort } =
|
props;
|
const createSortHandler = (property) => (event) => {
|
onRequestSort(event, property);
|
};
|
|
return (
|
<TableHead>
|
<TableRow>
|
<TableCell padding="checkbox">
|
<Checkbox
|
color="primary"
|
indeterminate={numSelected > 0 && numSelected < rowCount}
|
checked={rowCount > 0 && numSelected === rowCount}
|
onChange={onSelectAllClick}
|
inputProps={{
|
'aria-label': 'select all desserts',
|
}}
|
/>
|
</TableCell>
|
{headCells.map((headCell) => (
|
<TableCell
|
key={headCell.id}
|
align={headCell.numeric ? 'right' : 'left'}
|
padding={headCell.disablePadding ? 'none' : 'normal'}
|
sortDirection={orderBy === headCell.id ? order : false}
|
>
|
<TableSortLabel
|
active={orderBy === headCell.id}
|
direction={orderBy === headCell.id ? order : 'asc'}
|
onClick={createSortHandler(headCell.id)}
|
>
|
{headCell.label}
|
{orderBy === headCell.id ? (
|
<Box component="span" sx={visuallyHidden}>
|
{order === 'desc' ? 'sorted descending' : 'sorted ascending'}
|
</Box>
|
) : null}
|
</TableSortLabel>
|
</TableCell>
|
))}
|
</TableRow>
|
</TableHead>
|
);
|
}
|
|
EnhancedTableHead.propTypes = {
|
numSelected: PropTypes.number.isRequired,
|
onRequestSort: PropTypes.func.isRequired,
|
onSelectAllClick: PropTypes.func.isRequired,
|
order: PropTypes.oneOf(['asc', 'desc']).isRequired,
|
orderBy: PropTypes.string.isRequired,
|
rowCount: PropTypes.number.isRequired,
|
};
|
|
function EnhancedTableToolbar(props) {
|
const { numSelected } = props;
|
return (
|
<Toolbar
|
sx={[
|
{
|
pl: { sm: 2 },
|
pr: { xs: 1, sm: 1 },
|
},
|
numSelected > 0 && {
|
bgcolor: (theme) =>
|
alpha(theme.palette.primary.main, theme.palette.action.activatedOpacity),
|
},
|
]}
|
>
|
{numSelected > 0 ? (
|
<Typography
|
sx={{ flex: '1 1 100%' }}
|
color="inherit"
|
variant="subtitle1"
|
component="div"
|
>
|
{numSelected} selected
|
</Typography>
|
) : (
|
<Typography
|
sx={{ flex: '1 1 100%' }}
|
variant="h6"
|
id="tableTitle"
|
component="div"
|
>
|
Nutrition
|
</Typography>
|
)}
|
{numSelected > 0 ? (
|
<Tooltip title="Delete">
|
<IconButton>
|
<DeleteIcon />
|
</IconButton>
|
</Tooltip>
|
) : (
|
<Tooltip title="Filter list">
|
<IconButton>
|
<FilterListIcon />
|
</IconButton>
|
</Tooltip>
|
)}
|
</Toolbar>
|
);
|
}
|
|
EnhancedTableToolbar.propTypes = {
|
numSelected: PropTypes.number.isRequired,
|
};
|
|
export default function EnhancedTable() {
|
const [order, setOrder] = React.useState('asc');
|
const [orderBy, setOrderBy] = React.useState('calories');
|
const [selected, setSelected] = React.useState([]);
|
const [page, setPage] = React.useState(0);
|
const [dense, setDense] = React.useState(false);
|
const [rowsPerPage, setRowsPerPage] = React.useState(5);
|
|
const handleRequestSort = (event, property) => {
|
const isAsc = orderBy === property && order === 'asc';
|
setOrder(isAsc ? 'desc' : 'asc');
|
setOrderBy(property);
|
};
|
|
const handleSelectAllClick = (event) => {
|
if (event.target.checked) {
|
const newSelected = rows.map((n) => n.id);
|
setSelected(newSelected);
|
return;
|
}
|
setSelected([]);
|
};
|
|
const handleClick = (event, id) => {
|
const selectedIndex = selected.indexOf(id);
|
let newSelected = [];
|
|
if (selectedIndex === -1) {
|
newSelected = newSelected.concat(selected, id);
|
} else if (selectedIndex === 0) {
|
newSelected = newSelected.concat(selected.slice(1));
|
} else if (selectedIndex === selected.length - 1) {
|
newSelected = newSelected.concat(selected.slice(0, -1));
|
} else if (selectedIndex > 0) {
|
newSelected = newSelected.concat(
|
selected.slice(0, selectedIndex),
|
selected.slice(selectedIndex + 1),
|
);
|
}
|
setSelected(newSelected);
|
};
|
|
const handleChangePage = (event, newPage) => {
|
setPage(newPage);
|
};
|
|
const handleChangeRowsPerPage = (event) => {
|
setRowsPerPage(parseInt(event.target.value, 10));
|
setPage(0);
|
};
|
|
const handleChangeDense = (event) => {
|
setDense(event.target.checked);
|
};
|
|
// Avoid a layout jump when reaching the last page with empty rows.
|
const emptyRows =
|
page > 0 ? Math.max(0, (1 + page) * rowsPerPage - rows.length) : 0;
|
|
const visibleRows = React.useMemo(
|
() =>
|
[...rows]
|
.sort(getComparator(order, orderBy))
|
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage),
|
[order, orderBy, page, rowsPerPage],
|
);
|
|
return (
|
<Box sx={{ width: '100%' }}>
|
<Paper sx={{ width: '100%', mb: 2 }}>
|
<EnhancedTableToolbar numSelected={selected.length} />
|
<TableContainer>
|
<Table
|
sx={{ minWidth: 750 }}
|
aria-labelledby="tableTitle"
|
size={dense ? 'small' : 'medium'}
|
>
|
<EnhancedTableHead
|
numSelected={selected.length}
|
order={order}
|
orderBy={orderBy}
|
onSelectAllClick={handleSelectAllClick}
|
onRequestSort={handleRequestSort}
|
rowCount={rows.length}
|
/>
|
<TableBody>
|
{visibleRows.map((row, index) => {
|
const isItemSelected = selected.includes(row.id);
|
const labelId = `enhanced-table-checkbox-${index}`;
|
|
return (
|
<TableRow
|
hover
|
onClick={(event) => handleClick(event, row.id)}
|
role="checkbox"
|
aria-checked={isItemSelected}
|
tabIndex={-1}
|
key={row.id}
|
selected={isItemSelected}
|
sx={{ cursor: 'pointer' }}
|
>
|
<TableCell padding="checkbox">
|
<Checkbox
|
color="primary"
|
checked={isItemSelected}
|
inputProps={{
|
'aria-labelledby': labelId,
|
}}
|
/>
|
</TableCell>
|
<TableCell
|
component="th"
|
id={labelId}
|
scope="row"
|
padding="none"
|
>
|
{row.name}
|
</TableCell>
|
<TableCell align="right">{row.calories}</TableCell>
|
<TableCell align="right">{row.fat}</TableCell>
|
<TableCell align="right">{row.carbs}</TableCell>
|
<TableCell align="right">{row.protein}</TableCell>
|
</TableRow>
|
);
|
})}
|
{emptyRows > 0 && (
|
<TableRow
|
style={{
|
height: (dense ? 33 : 53) * emptyRows,
|
}}
|
>
|
<TableCell colSpan={6} />
|
</TableRow>
|
)}
|
</TableBody>
|
</Table>
|
</TableContainer>
|
<TablePagination
|
rowsPerPageOptions={[5, 10, 25]}
|
component="div"
|
count={rows.length}
|
rowsPerPage={rowsPerPage}
|
page={page}
|
onPageChange={handleChangePage}
|
onRowsPerPageChange={handleChangeRowsPerPage}
|
/>
|
</Paper>
|
<FormControlLabel
|
control={<Switch checked={dense} onChange={handleChangeDense} />}
|
label="Dense padding"
|
/>
|
</Box>
|
);
|
}
|