diff --git a/backend/src/controllers/team.controller.js b/backend/src/controllers/team.controller.js index 16b2d63f..0613413d 100644 --- a/backend/src/controllers/team.controller.js +++ b/backend/src/controllers/team.controller.js @@ -53,8 +53,7 @@ const getServerUrl = async (req, res) => { const getTeamDetails = async (req, res) => { try { - const { page = 1, limit = 10 } = req.query; - const data = await teamService.getTeam(Number(page), Number(limit)); + const data = await teamService.getTeam(); if (!data?.team || !data.users) { throw new Error('Team data not found'); } @@ -67,13 +66,9 @@ const getTeamDetails = async (req, res) => { role: settings.user.roleName[user.role], createdAt: new Intl.DateTimeFormat('en-US').format(user.createdAt), })), - totalUsers: data.totalUsers, - totalPages: data.totalPages, - currentPage: data.currentPage, }; return res.status(200).json(result); } catch (err) { - console.log(err); const { statusCode, payload } = internalServerError('GET_TEAM_ERROR', err.message); res.status(statusCode).json(payload); } @@ -134,4 +129,4 @@ module.exports = { getServerUrl, setServerUrl, teamService, -}; +}; \ No newline at end of file diff --git a/backend/src/service/team.service.js b/backend/src/service/team.service.js index 45cf465d..918876ca 100644 --- a/backend/src/service/team.service.js +++ b/backend/src/service/team.service.js @@ -34,33 +34,15 @@ class TeamService { } - async getTeam(page = 1, limit = 10) { + async getTeam() { try { - page = Math.max(1, page); - limit = Math.max(1, limit); - const offset = (page - 1) * limit; const team = await Team.findOne({ limit: 1, }); - if (!team) { - return null; - } - const { count, rows: users } = await User.findAndCountAll({ - limit, - offset, - order: [['createdAt', 'DESC']], - }); - - return { - team, - users, - totalUsers: count, - totalPages: Math.ceil(count / limit), - currentPage: page, - }; + const users = await User.findAll(); + return { team, users }; } catch (err) { - console.log(err); throw new Error("Failed to retrieve team"); } } @@ -185,4 +167,4 @@ class TeamService { } } -module.exports = TeamService; +module.exports = TeamService; \ No newline at end of file diff --git a/backend/src/test/unit/controllers/team.test.js b/backend/src/test/unit/controllers/team.test.js index 30a30d89..05f7faa2 100644 --- a/backend/src/test/unit/controllers/team.test.js +++ b/backend/src/test/unit/controllers/team.test.js @@ -15,10 +15,7 @@ describe('Unit test team controller', () => { res.status = sinon.stub().returns(res); res.json = sinon.stub().returns(res); }); - afterEach(async () => { - sinon.restore(); - await db.Team.destroy({ where: {}, truncate: true, restartIdentity: true }); - }); + afterEach(sinon.restore); it('setOrganisation - should return status 400 if a team is already created', async () => { sinon.stub(Team, 'count').returns(1); @@ -90,7 +87,6 @@ describe('Unit test team controller', () => { }); }); it('getTeamDetails - should return status 500 if no team was created', async () => { - const req = { query: { page: '1', limit: '10' } }; sinon.stub(service, 'getTeam').returns(null); await controller.getTeamDetails(req, res); expect(res.status.args[0][0]).to.equal(500); @@ -102,7 +98,6 @@ describe('Unit test team controller', () => { }); }); it('getTeamDetails - should return status 200 and the team and list of users if everything goes right', async () => { - const req = { query: { page: '1', limit: '10' } }; sinon.stub(service, 'getTeam').resolves({ team: { name: 'Test', @@ -117,7 +112,6 @@ describe('Unit test team controller', () => { expect(body.users).not.to.be.deep.equal(userMocks.validList); }); it('getTeamDetails - should return status 500 if something goes wrong', async () => { - const req = { query: { page: '1', limit: '10' } }; sinon.stub(service, 'getTeam').rejects(); await controller.getTeamDetails(req, res); expect(res.status.args[0][0]).to.equal(500); diff --git a/backend/src/test/unit/services/team.test.js b/backend/src/test/unit/services/team.test.js index 3a09aad0..8065a800 100644 --- a/backend/src/test/unit/services/team.test.js +++ b/backend/src/test/unit/services/team.test.js @@ -27,10 +27,7 @@ describe("Test team service", () => { rollback, })); }); - afterEach(async () => { - sinon.restore(); - await db.Team.destroy({ where: {}, truncate: true, restartIdentity: true }); - }); + afterEach(sinon.restore); it("createTeam - should create the team", async () => { TeamMock.create = sinon .stub(Team, "create") @@ -50,18 +47,14 @@ describe("Test team service", () => { } }); it("getTeam - should return the team and the users on the team if every thing goes right", async () => { - const mockUsers = { count: validList.length, rows: validList }; TeamMock.findOne = sinon .stub(Team, "findOne") .resolves({ id: 1, name: "team" }); - UserMock.findAndCountAll = sinon.stub(User, 'findAndCountAll').resolves(mockUsers); - const team = await service.getTeam(1,10); + UserMock.findAll = sinon.stub(User, "findAll").resolves(validList); + const team = await service.getTeam(); expect(team).to.deep.equal({ - team: { id: 1, name: 'team' }, + team: { id: 1, name: "team" }, users: validList, - totalUsers: validList.length, - totalPages: Math.ceil(validList.length / 10), - currentPage: 1, }); }); it("getTeam - should throw an error if something goes wrong", async () => { diff --git a/frontend/src/components/PageBtnContainer/PageBtnContainer.css b/frontend/src/components/PageBtnContainer/PageBtnContainer.css deleted file mode 100644 index ce838403..00000000 --- a/frontend/src/components/PageBtnContainer/PageBtnContainer.css +++ /dev/null @@ -1,14 +0,0 @@ -.pagination-container { - height: 4rem; - margin-top: 0.5rem; - display: flex; - align-items: center; - justify-content: center; - flex-wrap: wrap; - gap: 1rem; -} - -.ellipsis { - color: #7f56d9; - cursor: default; -} diff --git a/frontend/src/components/PageBtnContainer/PageBtnContainer.jsx b/frontend/src/components/PageBtnContainer/PageBtnContainer.jsx deleted file mode 100644 index f54b398d..00000000 --- a/frontend/src/components/PageBtnContainer/PageBtnContainer.jsx +++ /dev/null @@ -1,121 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import './PageBtnContainer.css'; -import Button from '../Button/Button'; -import ArrowBackIcon from '@mui/icons-material/ArrowBack'; -import ArrowForwardIcon from '@mui/icons-material/ArrowForward'; - -const PageBtnContainer = ({ currentPage, setCurrentPage, totalPages }) => { - const changePage = (pageNumber) => setCurrentPage(pageNumber); - - const generatePagination = () => { - const pages = []; - - if (totalPages <= 0) return pages; - - if (totalPages <= 7) { - for (let i = 1; i <= totalPages; i++) { - pages.push({ type: 'page', value: i }); - } - return pages; - } - - pages.push({ type: 'page', value: 1 }); - - if (currentPage > 3) { - pages.push({ type: 'ellipsis', id: 'start-ellipsis' }); - } else { - pages.push({ type: 'page', value: 2 }); - } - - const rangeStart = Math.max(2, currentPage - 1); - const rangeEnd = Math.min(totalPages - 1, currentPage + 1); - - if (currentPage <= 3) { - for (let i = 3; i <= Math.min(5, totalPages - 2); i++) { - pages.push({ type: 'page', value: i }); - } - } else if (currentPage >= totalPages - 2) { - for (let i = totalPages - 4; i <= totalPages - 2; i++) { - if (i > 2) pages.push({ type: 'page', value: i }); - } - } else { - for (let i = rangeStart; i <= rangeEnd; i++) { - pages.push({ type: 'page', value: i }); - } - } - - if (currentPage < totalPages - 2) { - pages.push({ type: 'ellipsis', id: 'end-ellipsis' }); - } else if ( - totalPages > 3 && - !pages.some((p) => p.type === 'page' && p.value === totalPages - 1) - ) { - pages.push({ type: 'page', value: totalPages - 1 }); - } - - pages.push({ type: 'page', value: totalPages }); - - return pages; - }; - - const nextPage = () => { - const nextPage = currentPage + 1; - setCurrentPage(nextPage); - }; - - const prevPage = () => { - const prevPage = currentPage - 1; - setCurrentPage(prevPage); - }; - - return ( -
- - ) - )} - -
- ); -}; - -PageBtnContainer.propTypes = { - currentPage: PropTypes.number.isRequired, - setCurrentPage: PropTypes.func.isRequired, - totalPages: PropTypes.number.isRequired, -}; - -export default PageBtnContainer; diff --git a/frontend/src/components/Pagination/TablePagination/PaginationTable.jsx b/frontend/src/components/Pagination/TablePagination/PaginationTable.jsx new file mode 100644 index 00000000..a142f0dd --- /dev/null +++ b/frontend/src/components/Pagination/TablePagination/PaginationTable.jsx @@ -0,0 +1,58 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import TablePagination from '@mui/material/TablePagination'; +import TablePaginationActions from './TablePaginationActions'; +import DropdownMenu from '../../DropdownMenu/DropdownMenu'; + +const PaginationTable = ({ + page, + setPage, + rowsPerPage, + setRowsPerPage, + rowsPerPageOptions = [5, 10, 25, { label: 'All', value: -1 }], + count, + colSpan, + labelRowsPerPage, + component = 'td', +}) => { + const handleChangePage = (event, newPage) => { + setPage(newPage); + }; + + const handleChangeRowsPerPage = (event) => { + setRowsPerPage(parseInt(event.target.value, 10)); + setPage(0); + }; + + return ( + , + }} + count={count} + rowsPerPage={rowsPerPage} + page={page} + onPageChange={handleChangePage} + onRowsPerPageChange={handleChangeRowsPerPage} + ActionsComponent={TablePaginationActions} + /> + ); +}; + +PaginationTable.propTypes = { + component: PropTypes.elementType, + page: PropTypes.number.isRequired, + rowsPerPage: PropTypes.number.isRequired, + rowsPerPageOptions: PropTypes.array, + labelRowsPerPage: PropTypes.string, + colSpan: PropTypes.number, + count: PropTypes.number.isRequired, + setRowsPerPage: PropTypes.func.isRequired, + setPage: PropTypes.func.isRequired, +}; + +export default PaginationTable; diff --git a/frontend/src/components/Pagination/TablePagination/TablePaginationActions.jsx b/frontend/src/components/Pagination/TablePagination/TablePaginationActions.jsx new file mode 100644 index 00000000..2006db94 --- /dev/null +++ b/frontend/src/components/Pagination/TablePagination/TablePaginationActions.jsx @@ -0,0 +1,80 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import { useTheme } from '@mui/material/styles'; +import Box from '@mui/material/Box'; +import IconButton from '@mui/material/IconButton'; +import FirstPageIcon from '@mui/icons-material/FirstPage'; +import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft'; +import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight'; +import LastPageIcon from '@mui/icons-material/LastPage'; + +function TablePaginationActions(props) { + const theme = useTheme(); + 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 ( + + + {theme.direction === 'rtl' ? : } + + + {theme.direction === 'rtl' ? ( + + ) : ( + + )} + + = Math.ceil(count / rowsPerPage) - 1} + aria-label="next page" + > + {theme.direction === 'rtl' ? ( + + ) : ( + + )} + + = Math.ceil(count / rowsPerPage) - 1} + aria-label="last page" + > + {theme.direction === 'rtl' ? : } + + + ); +} + +TablePaginationActions.propTypes = { + count: PropTypes.number.isRequired, + onPageChange: PropTypes.func.isRequired, + page: PropTypes.number.isRequired, + rowsPerPage: PropTypes.number.isRequired, +}; + +export default TablePaginationActions; diff --git a/frontend/src/scenes/settings/TeamTab/TeamTab.jsx b/frontend/src/scenes/settings/TeamTab/TeamTab.jsx index 7b19a96f..2287e3ba 100644 --- a/frontend/src/scenes/settings/TeamTab/TeamTab.jsx +++ b/frontend/src/scenes/settings/TeamTab/TeamTab.jsx @@ -11,7 +11,6 @@ import { VscEdit } from 'react-icons/vsc'; import styles from './TeamTab.module.css'; import TeamTable from './TeamTable/TeamTable'; import Button from '@components/Button/Button'; -import PageBtnContainer from '../../../components/PageBtnContainer/PageBtnContainer'; import CustomTextField from '@components/TextFieldComponents/CustomTextField/CustomTextField'; import LoadingArea from '@components/LoadingPage/LoadingArea'; @@ -42,8 +41,6 @@ const TeamTab = ({ handleTabChange }) => { const [refetch, setRefetch] = useState(true); const [loading, setLoading] = useState(true); const [team, setTeam] = useState([]); - const [currentPage, setCurrentPage] = useState(1); - const [totalPages, setTotalPages] = useState(1); const { userInfo, updateProfile } = useAuth(); const currentUserId = userInfo?.id ?? null; const [openInviteTeamMemberModal, setOpenInviteTeamMemberModal] = @@ -55,36 +52,31 @@ const TeamTab = ({ handleTabChange }) => { const [selectedMember, setSelectedMember] = useState(null); - const perPage = 10; - useEffect(() => { - loadTeamDetails(currentPage, perPage); - }, [currentPage, perPage, refetch]); - - const loadTeamDetails = async (page, limit) => { - try { - setLoading(() => true); - const response = await getOrgDetails(page, limit); - if (response.data.users) { - const matchedUser = response.data.users.find( - (user) => user.id === currentUserId && user.role !== userInfo.role - ); + (async () => { + try { + setLoading(() => true); + const response = await getOrgDetails(); + if (response.data.users) { + const matchedUser = response.data.users.find( + (user) => user.id === currentUserId && user.role !== userInfo.role + ); - if (matchedUser) { - updateProfile({ ...userInfo, role: matchedUser.role }); - handleTabChange(null, '1'); + if (matchedUser) { + updateProfile({ ...userInfo, role: matchedUser.role }); + handleTabChange(null, '1'); + } + setTeam(() => response.data.users); } - setTeam(() => response.data.users); + setOrgName(() => response.data.name); + } catch (error) { + console.error('Error fetching team details', error.message); + handleGenericError('Error fetching team details'); + } finally { + setLoading(false); } - setOrgName(() => response.data.name); - setTotalPages(() => response.data.totalPages); - } catch (error) { - console.error('Error fetching team details', error.message); - handleGenericError('Error fetching team details'); - } finally { - setLoading(false); - } - }; + })(); + }, [refetch]); const handleInviteTeamMemberModalClose = () => { setOpenInviteTeamMemberModal(false); @@ -152,145 +144,132 @@ const TeamTab = ({ handleTabChange }) => { } }; - return ( -
- <> -
-
Organisation Name
-
- {!editOrgName && ( -

{!loading && orgName}

- )} - {editOrgName && ( - setOrgName(e.target.value)} - onFocus={(e) => - e.currentTarget.setSelectionRange( - e.currentTarget.value.length, - e.currentTarget.value.length - ) - } + return loading ? ( + + ) : ( + <> +
+
Organisation Name
+
+ {!editOrgName &&

{orgName}

} + {editOrgName && ( + setOrgName(e.target.value)} + onFocus={(e) => + e.currentTarget.setSelectionRange( + e.currentTarget.value.length, + e.currentTarget.value.length + ) + } + /> + )} + {!editOrgName ? ( + + ) : ( + <> + - )} - {!editOrgName ? ( - setEditOrgName(false)} className={styles.pencil} - onClick={toggleEdit} + color="black" /> - ) : ( - <> - - setEditOrgName(false)} - className={styles.pencil} - color="black" - /> - - )} -
+ + )}
+
+
Team Members
- - {loading ? ( - - ) : ( -
-
- - - - - - - - -
- - - + +
- )} -
+ + + +
+ ); }; diff --git a/frontend/src/scenes/settings/TeamTab/TeamTable/TeamTable.jsx b/frontend/src/scenes/settings/TeamTab/TeamTable/TeamTable.jsx index ff4a07ad..155a1d3d 100644 --- a/frontend/src/scenes/settings/TeamTab/TeamTable/TeamTable.jsx +++ b/frontend/src/scenes/settings/TeamTab/TeamTable/TeamTable.jsx @@ -5,12 +5,14 @@ import TableCell from '@mui/material/TableCell'; import TableContainer from '@mui/material/TableContainer'; import TableHead from '@mui/material/TableHead'; import TableRow from '@mui/material/TableRow'; +import TableFooter from '@mui/material/TableFooter'; import Paper from '@mui/material/Paper'; import styles from './TeamTable.module.css'; import { RiDeleteBinLine } from 'react-icons/ri'; import { useAuth } from '../../../../services/authProvider'; import DropdownMenu from '@components/DropdownMenu/DropdownMenu'; import { roles } from '../../../../utils/constants'; +import PaginationTable from '@components/Pagination/TablePagination/PaginationTable'; import PropTypes from 'prop-types'; const TeamTable = ({ @@ -19,6 +21,8 @@ const TeamTable = ({ setChangeRoleModalOpen, setSelectedMember, }) => { + const [page, setPage] = React.useState(0); + const [rowsPerPage, setRowsPerPage] = React.useState(5); const { userInfo } = useAuth(); const handleRemoveMember = async (member) => { @@ -43,7 +47,10 @@ const TeamTable = ({ - {team.map((member, index) => ( + {(rowsPerPage > 0 + ? team.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) + : team + ).map((member, index) => ( {userInfo.id == member.id ? YOU : member.name} @@ -81,6 +88,19 @@ const TeamTable = ({ ))} + + + + + ); diff --git a/frontend/src/services/settingServices.js b/frontend/src/services/settingServices.js index 206c202f..9da673e6 100644 --- a/frontend/src/services/settingServices.js +++ b/frontend/src/services/settingServices.js @@ -20,11 +20,9 @@ export const getUser = async () => { } }; -export const getOrgDetails = async (page = 1, limit = 5) => { +export const getOrgDetails = async () => { try { - const response = await apiClient.get('/team/details', { - params: { page, limit }, - }); + const response = await apiClient.get('/team/details'); return response; } catch (error) { console.error('Error getting details: ', error.message); diff --git a/frontend/src/templates/DefaultPageTemplate/DefaultPageTemplate.jsx b/frontend/src/templates/DefaultPageTemplate/DefaultPageTemplate.jsx index 542e4431..8863c979 100644 --- a/frontend/src/templates/DefaultPageTemplate/DefaultPageTemplate.jsx +++ b/frontend/src/templates/DefaultPageTemplate/DefaultPageTemplate.jsx @@ -4,6 +4,7 @@ import ParagraphCSS from '@components/ParagraphCSS/ParagraphCSS'; import GuideMainPageTemplate from '../GuideMainPageTemplate/GuideMainPageTemplate'; import CreateActivityButton from '@components/Button/CreateActivityButton/CreateActivityButton'; import toastEmitter, { TOAST_EMITTER_KEY } from '../../utils/toastEmitter'; +import LoadingArea from '../../components/LoadingPage/LoadingArea'; import './DefaultPageTemplate.css'; import { useAuth } from '../../services/authProvider'; import { renderIfAuthorized } from '../../utils/generalHelper'; @@ -27,7 +28,9 @@ const DefaultPageTemplate = ({ const [itemDeleted, setItemDeleted] = useState(false); const [itemsDuplicated, setItemsDuplicated] = useState(false); const [loading, setLoading] = useState(true); + const [hasFetched, setHasFetched] = useState(false); const [load, setLoad] = useState(true); + const [count, setCount] = useState(0); const { userInfo } = useAuth(); const { openDialog } = useDialog(); @@ -123,13 +126,16 @@ const DefaultPageTemplate = ({ if (load) { setLoading(true); } + setLoading(true); const data = await getItems(); setItems(data); + setCount(data.length); } catch (error) { console.error(`Failed to fetch ${itemType.toLowerCase()}s:`, error); } finally { setLoading(false); setLoad(true); + setHasFetched(true); } }; fetchData(); @@ -155,34 +161,34 @@ const DefaultPageTemplate = ({ return ( <> - {loading ? ( -
- ) : ( -
- {items.length === 0 ? ( -
- {renderIfAuthorized(role, 'admin', )} - {renderIfAuthorized( - role, - 'admin', - - )} -
- ) : ( - - )} -
- )} +
+ {!hasFetched ? ( + + ) : items.length === 0 ? ( +
+ {renderIfAuthorized(role, 'admin', )} + {renderIfAuthorized( + role, + 'admin', + + )} +
+ ) : ( + + )} +
); }; diff --git a/frontend/src/templates/GuideMainPageTemplate/GuideMainPageComponents/List/ListItem/ListItem.css b/frontend/src/templates/GuideMainPageTemplate/GuideMainPageComponents/List/ListItem/ListItem.css index 2afbf41b..26749630 100644 --- a/frontend/src/templates/GuideMainPageTemplate/GuideMainPageComponents/List/ListItem/ListItem.css +++ b/frontend/src/templates/GuideMainPageTemplate/GuideMainPageComponents/List/ListItem/ListItem.css @@ -58,7 +58,7 @@ } .list-item-info p { - margin: 2px 0 0 33px; + margin: 2px 0 0 0; color: var(--main-text-color); } diff --git a/frontend/src/templates/GuideMainPageTemplate/GuideMainPageComponents/List/ListItem/ListItem.jsx b/frontend/src/templates/GuideMainPageTemplate/GuideMainPageComponents/List/ListItem/ListItem.jsx index 80f84635..43979d6e 100644 --- a/frontend/src/templates/GuideMainPageTemplate/GuideMainPageComponents/List/ListItem/ListItem.jsx +++ b/frontend/src/templates/GuideMainPageTemplate/GuideMainPageComponents/List/ListItem/ListItem.jsx @@ -1,12 +1,11 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { IconButton, useTheme } from '@mui/material'; +import { IconButton } from '@mui/material'; import { DuplicateIcon, EditIcon, TrashIcon, } from '../../../../../assets/icons/utilityIcons'; -import CircleIcon from '@mui/icons-material/Circle'; import './ListItem.css'; import { useAuth } from '../../../../../services/authProvider'; import { renderIfAuthorized } from '../../../../../utils/generalHelper'; @@ -20,7 +19,6 @@ const ListItem = ({ onEdit, onDuplicate, }) => { - const theme = useTheme(); const { userInfo } = useAuth(); const role = userInfo.role; @@ -28,16 +26,6 @@ const ListItem = ({
-
- -
-

{title}

{text &&

{text}

} diff --git a/frontend/src/templates/GuideMainPageTemplate/GuideMainPageTemplate.jsx b/frontend/src/templates/GuideMainPageTemplate/GuideMainPageTemplate.jsx index 4a789ef7..bc8c8bab 100644 --- a/frontend/src/templates/GuideMainPageTemplate/GuideMainPageTemplate.jsx +++ b/frontend/src/templates/GuideMainPageTemplate/GuideMainPageTemplate.jsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import List from './GuideMainPageComponents/List/List'; import ContentArea from './GuideMainPageComponents/ContentArea/ContentArea'; import ContentHeader from './GuideMainPageComponents/ContentHeader/ContentHeader'; @@ -8,16 +8,22 @@ import './GuideMainPageTemplate.css'; import { activityInfoData } from '../../data/guideMainPageData'; import { useAuth } from '../../services/authProvider'; import { renderIfAuthorized } from '../../utils/generalHelper'; +import PaginationTable from '../../components/Pagination/TablePagination/PaginationTable'; +import LoadingArea from '../../components/LoadingPage/LoadingArea'; import PropTypes from 'prop-types'; const GuideMainPageTemplate = ({ items, + count, handleDelete, isPopupOpen, handleClosePopup, type, onClick, + loading, }) => { + const [page, setPage] = useState(0); + const [rowsPerPage, setRowsPerPage] = useState(5); const { userInfo } = useAuth(); const role = userInfo.role; const { heading, paragraph, buttonText, title } = activityInfoData[type]; @@ -33,17 +39,47 @@ const GuideMainPageTemplate = ({ )}
- - - -
-

{heading}

-

'), - }} - >

-
+ {loading ? ( + + ) : ( + <> + + {(rowsPerPage > 0 + ? items.slice( + page * rowsPerPage, + page * rowsPerPage + rowsPerPage + ) + : items + ).map((row, index) => ( + + ))} + {count > 5 && ( + + )} + +
+

{heading}

+

'), + }} + >

+
+ + )}