Files
Checkmate/Client/src/Components/BasicTable/index.jsx
Daniel Cojocea d871907d97 Pagination fix
2024-07-22 17:03:09 -04:00

164 lines
4.7 KiB
JavaScript

import {
TableContainer,
Paper,
Table,
TableHead,
TableRow,
TableCell,
TableBody,
Pagination,
PaginationItem,
} from "@mui/material";
import React, { useState } from "react";
import PropTypes from "prop-types";
import "./index.css";
import ArrowBackRoundedIcon from "@mui/icons-material/ArrowBackRounded";
import ArrowForwardRoundedIcon from "@mui/icons-material/ArrowForwardRounded";
/**
* BasicTable Component
* Renders a table with optional pagination.
*
* @component
* @param {Object} props - Component props.
* @param {Object} props.data - Data for the table including columns and rows.
* @param {Array} props.data.cols - Array of objects for column headers.
* @param {number} props.data.cols[].id - Unique identifier for the column.
* @param {string} props.data.cols[].name - Name of the column to display as header.
* @param {Array} props.data.rows - Array of row objects.
* @param {number} props.data.rows[].id - Unique identifier for the row.
* @param {Array} props.data.rows[].data - Array of cell data objects for the row.
* @param {number} props.data.rows[].data[].id - Unique identifier for the cell.
* @param {JSX.Element} props.data.rows[].data[].data - The content to display in the cell.
* @param {function} props.data.rows.data.handleClick - Function to call when the row is clicked.
* @param {boolean} [props.paginated=false] - Flag to enable pagination.
* @param {boolean} [props.reversed=false] - Flag to enable reverse order.
*
* @example
* const data = {
* cols: [
* { id: 1, name: "First Col" },
* { id: 2, name: "Second Col" },
* { id: 3, name: "Third Col" },
* { id: 4, name: "Fourth Col" },
* ],
* rows: [
* {
* id: 1,
* data: [
* { id: 1, data: <div>Data for Row 1 Col 1</div> },
* { id: 2, data: <div>Data for Row 1 Col 2</div> },
* { id: 3, data: <div>Data for Row 1 Col 3</div> },
* { id: 4, data: <div>Data for Row 1 Col 4</div> },
* ],
* },
* {
* id: 2,
* data: [
* { id: 5, data: <div>Data for Row 2 Col 1</div> },
* { id: 6, data: <div>Data for Row 2 Col 2</div> },
* { id: 7, data: <div>Data for Row 2 Col 3</div> },
* { id: 8, data: <div>Data for Row 2 Col 4</div> },
* ],
* },
* ],
* };
*
* <BasicTable data={data} rows={rows} paginated={true} />
*/
const BasicTable = ({ data, paginated, reversed }) => {
// Add headers to props validation
const [page, setPage] = useState(0);
const rowsPerPage = 5;
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
let displayData = [];
if (data && data.rows) {
let rows = reversed ? [...data.rows].reverse() : data.rows;
displayData = paginated
? rows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
: rows;
}
if (!data || !data.cols || !data.rows) {
return <div>No data</div>;
}
let paginationComponent = <></>;
if (paginated === true && data.rows.length > rowsPerPage) {
paginationComponent = (
<Pagination
count={Math.ceil(data.rows.length / rowsPerPage)}
page={page + 1}
onChange={(event, value) => handleChangePage(event, value - 1)}
shape="rounded"
renderItem={(item) => (
<PaginationItem
slots={{
previous: ArrowBackRoundedIcon,
next: ArrowForwardRoundedIcon,
}}
{...item}
sx={{
"&:focus": {
outline: "none",
},
"& .MuiTouchRipple-root": {
pointerEvents: "none",
display: "none",
},
}}
/>
)}
/>
);
}
return (
<>
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
{data.cols.map((col) => (
<TableCell key={col.id}>{col.name}</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{displayData.map((row) => {
return (
<TableRow
sx={{ cursor: row.handleClick ? "pointer" : "default" }}
key={row.id}
onClick={row.handleClick ? row.handleClick : null}
>
{row.data.map((cell) => {
return <TableCell key={cell.id}>{cell.data}</TableCell>;
})}
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
{paginationComponent}
</>
);
};
BasicTable.propTypes = {
data: PropTypes.object.isRequired,
paginated: PropTypes.bool,
reversed: PropTypes.bool,
};
export default BasicTable;