diff --git a/Client/src/Pages/Monitors/Home/MonitorTable/index.jsx b/Client/src/Pages/Monitors/Home/MonitorTable/index.jsx index d4cc08224..4a0325246 100644 --- a/Client/src/Pages/Monitors/Home/MonitorTable/index.jsx +++ b/Client/src/Pages/Monitors/Home/MonitorTable/index.jsx @@ -6,35 +6,113 @@ import { TableRow, TableCell, TableBody, - Pagination, - PaginationItem, Paper, Box, + TablePagination, + Stack, + Typography, + Button, } from "@mui/material"; -import ArrowBackRoundedIcon from "@mui/icons-material/ArrowBackRounded"; -import ArrowForwardRoundedIcon from "@mui/icons-material/ArrowForwardRounded"; import ArrowDownwardRoundedIcon from "@mui/icons-material/ArrowDownwardRounded"; +import { setRowsPerPage } from "../../../../Features/UI/uiSlice"; import { useState, useEffect } from "react"; import { useNavigate } from "react-router"; import { logger } from "../../../../Utils/Logger"; import Host from "../host"; import { StatusLabel } from "../../../../Components/Label"; import { jwtDecode } from "jwt-decode"; -import { useSelector } from "react-redux"; +import { useDispatch, useSelector } from "react-redux"; import { networkService } from "../../../../main"; import { useTheme } from "@emotion/react"; import BarChart from "../../../../Components/Charts/BarChart"; +import LeftArrowDouble from "../../../../assets/icons/left-arrow-double.svg?react"; +import RightArrowDouble from "../../../../assets/icons/right-arrow-double.svg?react"; +import LeftArrow from "../../../../assets/icons/left-arrow.svg?react"; +import RightArrow from "../../../../assets/icons/right-arrow.svg?react"; +import SelectorVertical from "../../../../assets/icons/selector-vertical.svg?react"; import ActionsMenu from "../actionsMenu"; +/** + * Component for pagination actions (first, previous, next, last). + * + * @component + * @param {Object} props + * @param {number} props.count - Total number of items. + * @param {number} props.page - Current page number. + * @param {number} props.rowsPerPage - Number of rows per page. + * @param {function} props.onPageChange - Callback function to handle page change. + * + * @returns {JSX.Element} Pagination actions component. + */ +const TablePaginationActions = (props) => { + const { count, page, rowsPerPage, onPageChange } = props; + + const handleFirstPageButtonClick = (event) => { + onPageChange(event, 0); + }; + const handleBackButtonClick = (event) => { + onPageChange(event, page - 1); + }; + const handleNextButtonClick = (event) => { + onPageChange(event, page + 1); + }; + const handleLastPageButtonClick = (event) => { + onPageChange(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1)); + }; + + return ( + + + + + + + ); +}; + +TablePaginationActions.propTypes = { + count: PropTypes.number.isRequired, + page: PropTypes.number.isRequired, + rowsPerPage: PropTypes.number.isRequired, + onPageChange: PropTypes.func.isRequired, +}; + const MonitorTable = ({ isAdmin }) => { const theme = useTheme(); const navigate = useNavigate(); + const dispatch = useDispatch(); - const [paginationController, setPaginationController] = useState({ - page: 0, - rowsPerPage: 14, - }); + const { rowsPerPage } = useSelector((state) => state.ui.monitors); + const [page, setPage] = useState(0); const [monitors, setMonitors] = useState([]); const [monitorCount, setMonitorCount] = useState(0); const authState = useSelector((state) => state.auth); @@ -44,11 +122,18 @@ const MonitorTable = ({ isAdmin }) => { setUpdateTrigger((prev) => !prev); }; - const handlePageChange = (_, newPage) => { - setPaginationController({ - ...paginationController, - page: newPage - 1, // 0-indexed - }); + const handleChangePage = (event, newPage) => { + setPage(newPage); + }; + + const handleChangeRowsPerPage = (event) => { + dispatch( + setRowsPerPage({ + value: parseInt(event.target.value, 10), + table: "monitors", + }) + ); + setPage(0); }; useEffect(() => { @@ -64,8 +149,8 @@ const MonitorTable = ({ isAdmin }) => { null, "desc", true, - paginationController.page, - paginationController.rowsPerPage + page, + rowsPerPage ); setMonitors(res?.data?.data?.monitors ?? []); setMonitorCount(res?.data?.data?.monitorCount ?? 0); @@ -74,33 +159,17 @@ const MonitorTable = ({ isAdmin }) => { } }; fetchPage(); - }, [ - updateTrigger, - authState, - paginationController.page, - paginationController.rowsPerPage, - ]); + }, [updateTrigger, authState, page, rowsPerPage]); - let paginationComponent = <>; - if (monitorCount > paginationController.rowsPerPage) { - paginationComponent = ( - ( - - )} - /> - ); - } + /** + * Helper function to calculate the range of displayed rows. + * @returns {string} + */ + const getRange = () => { + let start = page * rowsPerPage + 1; + let end = Math.min(page * rowsPerPage + rowsPerPage, monitorCount); + return `${start} - ${end}`; + }; return ( <> @@ -202,7 +271,76 @@ const MonitorTable = ({ isAdmin }) => { - {paginationComponent} + + + Showing {getRange()} of {monitorCount} monitor(s) + + + `Page ${page + 1} of ${Math.max(0, Math.ceil(count / rowsPerPage))}` + } + slotProps={{ + select: { + MenuProps: { + keepMounted: true, + PaperProps: { + className: "pagination-dropdown", + sx: { + mt: 0, + mb: theme.spacing(2), + }, + }, + transformOrigin: { vertical: "bottom", horizontal: "left" }, + anchorOrigin: { vertical: "top", horizontal: "left" }, + sx: { mt: theme.spacing(-2) }, + }, + inputProps: { id: "pagination-dropdown" }, + IconComponent: SelectorVertical, + sx: { + ml: theme.spacing(4), + mr: theme.spacing(12), + minWidth: theme.spacing(20), + textAlign: "left", + "&.Mui-focused > div": { + backgroundColor: theme.palette.background.main, + }, + }, + }, + }} + sx={{ + mt: theme.spacing(6), + color: theme.palette.text.secondary, + "& svg path": { + stroke: theme.palette.text.tertiary, + strokeWidth: 1.3, + }, + "& .MuiSelect-select": { + border: 1, + borderColor: theme.palette.border.light, + borderRadius: theme.shape.borderRadius, + }, + }} + /> + ); };