From 8d51fd8bf3c9737a80ed97e9dd7f1315b1764602 Mon Sep 17 00:00:00 2001 From: M M Date: Thu, 18 Jul 2024 23:02:05 -0700 Subject: [PATCH 001/131] Updated joi validation schema. --- Server/validation/joi.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Server/validation/joi.js b/Server/validation/joi.js index b559479e9..2947406bd 100644 --- a/Server/validation/joi.js +++ b/Server/validation/joi.js @@ -154,6 +154,10 @@ const getPageSpeedCheckParamValidation = joi.object({ const createPageSpeedCheckParamValidation = joi.object({ monitorId: joi.string().required(), + accessibility: joi.number().required().min(0).max(100), + bestPractices: joi.number().required().min(0).max(100), + seo: joi.number().required().min(0).max(100), + performance: joi.number().required().min(0).max(100), }); const deletePageSpeedCheckParamValidation = joi.object({ From 73ec86e6e310883a9729f6232506d25b66d1f0a9 Mon Sep 17 00:00:00 2001 From: M M Date: Thu, 18 Jul 2024 23:05:33 -0700 Subject: [PATCH 002/131] Updated route handler function for the speed check controller. --- .../controllers/pageSpeedCheckController.js | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/Server/controllers/pageSpeedCheckController.js b/Server/controllers/pageSpeedCheckController.js index 8da1b39d2..937b63ebf 100644 --- a/Server/controllers/pageSpeedCheckController.js +++ b/Server/controllers/pageSpeedCheckController.js @@ -39,10 +39,26 @@ const getPageSpeedChecks = async (req, res, next) => { */ const createPageSpeedCheck = async (req, res, next) => { try { - // Validate monitorId parameter - await createPageSpeedCheckParamValidation.validateAsync(req.params); + // Validate monitorId parameter and request body + const { monitorId } = req.params; + const { accessibility, bestPractices, seo, performance } = req.body; + + await createPageSpeedCheckParamValidation.validateAsync({ monitorId, accessibility, bestPractices, seo, performance }); - return res.status(200).json({ msg: "Hit createPageSpeedCheck" }); + const newPageSpeedCheck = new PageSpeedCheck({ + monitorId, + accessibility, + bestPractices, + seo, + performance, + }); + + await newPageSpeedCheck.save(); + + return res.status(201).json({ + msg: successMessages.CREATED, + data: newPageSpeedCheck, + }); } catch (error) { if (error.isJoi) { return res.status(400).json({ error: error.details[0].message }); From 83a837d236ab2e340033a8d68e54eb39ef7967a9 Mon Sep 17 00:00:00 2001 From: M M Date: Thu, 18 Jul 2024 23:21:28 -0700 Subject: [PATCH 003/131] Updated router module. --- Server/routes/pageSpeedCheckRoute.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Server/routes/pageSpeedCheckRoute.js b/Server/routes/pageSpeedCheckRoute.js index 803012d95..bb140e575 100644 --- a/Server/routes/pageSpeedCheckRoute.js +++ b/Server/routes/pageSpeedCheckRoute.js @@ -1,8 +1,7 @@ const router = require("express").Router(); const { verifyOwnership } = require("../middleware/verifyOwnership"); const Monitor = require("../models/Monitor"); -const { createPageSpeedCheck, getPageSpeedChecks, deletePageSpeedCheck } = require("../controllers/pageSpeedCheckController"); - +const checkController = require("../controllers/pageSpeedCheckController"); /** * @route POST /pagespeed/:monitorId @@ -14,7 +13,7 @@ const { createPageSpeedCheck, getPageSpeedChecks, deletePageSpeedCheck } = requi router.post( "/pagespeed/:monitorId", verifyOwnership(Monitor, "monitorId"), - createPageSpeedCheck + checkController.createPageSpeedCheck ); /** @@ -27,7 +26,7 @@ router.post( router.get( "/pagespeed/:monitorId", verifyOwnership(Monitor, "monitorId"), - getPageSpeedChecks + checkController.getPageSpeedChecks ); /** @@ -40,7 +39,7 @@ router.get( router.delete( "/pagespeed/:monitorId", verifyOwnership(Monitor, "monitorId"), - deletePageSpeedCheck + checkController.deletePageSpeedCheck ); module.exports = router; From a2cc51475493289d4cc06cff04805645ae44f67d Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Fri, 19 Jul 2024 10:05:18 -0700 Subject: [PATCH 004/131] Move register to register folder --- Client/src/App.jsx | 2 +- .../Pages/Auth/{ => Register}/Register.jsx | 24 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) rename Client/src/Pages/Auth/{ => Register}/Register.jsx (92%) diff --git a/Client/src/App.jsx b/Client/src/App.jsx index 0482aec5d..622c8c79b 100644 --- a/Client/src/App.jsx +++ b/Client/src/App.jsx @@ -2,7 +2,7 @@ import { Routes, Route } from "react-router-dom"; // import "./App.css"; import NotFound from "./Pages/NotFound"; import Login from "./Pages/Auth/Login"; -import Register from "./Pages/Auth/Register"; +import Register from "./Pages/Auth/Register/Register"; import HomeLayout from "./Layouts/HomeLayout"; import Account from "./Pages/Account"; import Monitors from "./Pages/Monitors"; diff --git a/Client/src/Pages/Auth/Register.jsx b/Client/src/Pages/Auth/Register/Register.jsx similarity index 92% rename from Client/src/Pages/Auth/Register.jsx rename to Client/src/Pages/Auth/Register/Register.jsx index f6d0b3b0f..3003a3a75 100644 --- a/Client/src/Pages/Auth/Register.jsx +++ b/Client/src/Pages/Auth/Register/Register.jsx @@ -1,19 +1,19 @@ import { useState, useEffect } from "react"; import { useNavigate } from "react-router-dom"; - -import "./index.css"; -import background from "../../assets/Images/background_pattern_decorative.png"; -import Logomark from "../../assets/Images/bwl-logo-2.svg?react"; -import Check from "../../Components/Check/Check"; -import Button from "../../Components/Button"; -import { credentials } from "../../Validation/validation"; -import axiosInstance from "../../Utils/axiosConfig"; -import { useDispatch } from "react-redux"; -import { register } from "../../Features/Auth/authSlice"; -import { createToast } from "../../Utils/toastUtils"; -import Field from "../../Components/Inputs/Field"; import { useTheme } from "@emotion/react"; import { Stack, Typography } from "@mui/material"; +import { useDispatch } from "react-redux"; + +import "../index.css"; +import background from "../../../assets/Images/background_pattern_decorative.png"; +import Logomark from "../../../assets/Images/bwl-logo-2.svg?react"; +import Check from "../../../Components/Check/Check"; +import Button from "../../../Components/Button"; +import { credentials } from "../../../Validation/validation"; +import axiosInstance from "../../../Utils/axiosConfig"; +import { register } from "../../../Features/Auth/authSlice"; +import { createToast } from "../../../Utils/toastUtils"; +import Field from "../../../Components/Inputs/Field"; const Register = () => { const dispatch = useDispatch(); From 61b16147cb3399e8b379c9b835f672961bb8a76e Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Fri, 19 Jul 2024 10:24:01 -0700 Subject: [PATCH 005/131] Move admin check for register page to HOC --- Client/src/HOC/withAdminCheck.jsx | 31 +++++++++++++++++++++ Client/src/Pages/Auth/Register/Register.jsx | 22 ++++----------- 2 files changed, 36 insertions(+), 17 deletions(-) create mode 100644 Client/src/HOC/withAdminCheck.jsx diff --git a/Client/src/HOC/withAdminCheck.jsx b/Client/src/HOC/withAdminCheck.jsx new file mode 100644 index 000000000..2d8812728 --- /dev/null +++ b/Client/src/HOC/withAdminCheck.jsx @@ -0,0 +1,31 @@ +import React, { useEffect } from "react"; +import { useNavigate } from "react-router-dom"; +import axiosInstance from "../Utils/axiosConfig"; + +const withAdminCheck = (WrappedComponent) => { + const WithAdminCheck = (props) => { + const navigate = useNavigate(); + + useEffect(() => { + console.log("admin check"); + axiosInstance + .get("/auth/users/admin") + .then((response) => { + if (response.data.data === true) { + navigate("/login"); + } + }) + .catch((error) => { + console.log(error); + }); + }, [navigate]); + return ; + }; + const wrappedComponentName = + WrappedComponent.displayName || WrappedComponent.name || "Component"; + WithAdminCheck.displayName = `WithAdminCheck(${wrappedComponentName})`; + + return WithAdminCheck; +}; + +export default withAdminCheck; diff --git a/Client/src/Pages/Auth/Register/Register.jsx b/Client/src/Pages/Auth/Register/Register.jsx index 3003a3a75..dae616d3a 100644 --- a/Client/src/Pages/Auth/Register/Register.jsx +++ b/Client/src/Pages/Auth/Register/Register.jsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from "react"; +import { useState } from "react"; import { useNavigate } from "react-router-dom"; import { useTheme } from "@emotion/react"; import { Stack, Typography } from "@mui/material"; @@ -10,10 +10,10 @@ import Logomark from "../../../assets/Images/bwl-logo-2.svg?react"; import Check from "../../../Components/Check/Check"; import Button from "../../../Components/Button"; import { credentials } from "../../../Validation/validation"; -import axiosInstance from "../../../Utils/axiosConfig"; -import { register } from "../../../Features/Auth/authSlice"; import { createToast } from "../../../Utils/toastUtils"; import Field from "../../../Components/Inputs/Field"; +import withAdminCheck from "../../../HOC/withAdminCheck"; +import { register } from "../../../Features/Auth/authSlice"; const Register = () => { const dispatch = useDispatch(); @@ -39,19 +39,6 @@ const Register = () => { }); const [errors, setErrors] = useState({}); - useEffect(() => { - axiosInstance - .get("/auth/users/admin") - .then((response) => { - if (response.data.data === true) { - navigate("/login"); - } - }) - .catch((error) => { - console.log(error); - }); - }, [form, navigate]); - const handleSubmit = async (e) => { e.preventDefault(); @@ -242,4 +229,5 @@ const Register = () => { ); }; -export default Register; +const WrappedRegister = withAdminCheck(Register); +export default WrappedRegister; From f3b85e4e9af88e5a55931fa6d2bb66007bf85bf8 Mon Sep 17 00:00:00 2001 From: Daniel Cojocea Date: Fri, 19 Jul 2024 13:27:00 -0400 Subject: [PATCH 006/131] Added select field and styling --- Client/src/Components/Button/index.jsx | 5 +- Client/src/Components/ButtonSpinner/index.jsx | 1 + .../TabPanels/Account/TeamPanel.jsx | 133 +++++++++++++++--- Client/src/Pages/Account/index.css | 27 +++- 4 files changed, 135 insertions(+), 31 deletions(-) diff --git a/Client/src/Components/Button/index.jsx b/Client/src/Components/Button/index.jsx index fcf157f5e..c53ece09e 100644 --- a/Client/src/Components/Button/index.jsx +++ b/Client/src/Components/Button/index.jsx @@ -58,15 +58,12 @@ const Button = ({ id, type, level, label, disabled, img, onClick, sx }) => { color={color} disabled={disabled} onClick={onClick} + disableRipple sx={{ textTransform: "none", "&:focus": { outline: "none", }, - "& .MuiTouchRipple-root": { - pointerEvents: "none", - display: "none", - }, ...sx, }} > diff --git a/Client/src/Components/ButtonSpinner/index.jsx b/Client/src/Components/ButtonSpinner/index.jsx index 7f89f1ab9..2d940c539 100644 --- a/Client/src/Components/ButtonSpinner/index.jsx +++ b/Client/src/Components/ButtonSpinner/index.jsx @@ -70,6 +70,7 @@ const ButtonSpinner = ({ endIcon={position === "end" && img} onClick={onClick} loading={isLoading} + disableRipple sx={{ textTransform: "none", "&:focus": { diff --git a/Client/src/Components/TabPanels/Account/TeamPanel.jsx b/Client/src/Components/TabPanels/Account/TeamPanel.jsx index 471752dfa..5ef356f9c 100644 --- a/Client/src/Components/TabPanels/Account/TeamPanel.jsx +++ b/Client/src/Components/TabPanels/Account/TeamPanel.jsx @@ -21,6 +21,8 @@ import ButtonSpinner from "../../ButtonSpinner"; import Button from "../../Button"; import { useState } from "react"; import EditSvg from "../../../assets/icons/edit.svg?react"; +import Field from "../../Inputs/Field"; +import { credentials } from "../../../Validation/validation"; /** * TeamPanel component manages the organization and team members, @@ -106,19 +108,11 @@ const TeamPanel = () => { name: "Bluewave Labs", isLoading: false, isEdit: false, - newName: "", }); const toggleEdit = () => { setOrgStates((prev) => ({ ...prev, isEdit: !prev.isEdit })); }; - const handleChange = (event) => { - const { value } = event.target; - setOrgStates((prev) => ({ - ...prev, - name: value, - })); - }; const handleRename = () => {}; const [teamStates, setTeamStates] = useState({ @@ -163,8 +157,44 @@ const TeamPanel = () => { setIsLoading(false); }, 2000); }; + + const [toInvite, setToInvite] = useState({ + email: "", + role: "", + }); + const [errors, setErrors] = useState({}); + + const handleChange = (event) => { + const { value } = event.target; + setToInvite((prev) => ({ + ...prev, + email: value, + })); + + const validation = credentials.validate( + { email: value }, + { abortEarly: false } + ); + + setErrors((prev) => { + const updatedErrors = { ...prev }; + + if (validation.error) { + updatedErrors.email = validation.error.details[0].message; + } else { + delete updatedErrors.email; + } + return updatedErrors; + }); + }; const [isOpen, setIsOpen] = useState(false); const handleInviteMember = () => {}; + const closeInviteModal = () => { + setIsOpen(false); + setToInvite({ email: "", role: "" }); + setErrors({}); + }; + const handleMembersQuery = (type) => { let count = 0; teamStates.members.forEach((member) => { @@ -188,7 +218,12 @@ const TeamPanel = () => { > + setOrgStates((prev) => ({ + ...prev, + name: event.target.value, + })) + } disabled={!orgStates.isEdit} sx={{ color: theme.palette.otherColors.bluishGray, @@ -409,7 +444,7 @@ const TeamPanel = () => { aria-labelledby="modal-invite-member" aria-describedby="invite-member-to-team" open={isOpen} - onClose={() => setIsOpen(false)} + onClose={closeInviteModal} disablePortal > { Invite new team member - + When you add a new team member, they will get access to all monitors. - - // setOrgStates((prev) => ({ - // ...prev, - // newName: event.target.value, - // })) - // } - > - + placeholder="Email" + value={toInvite.email} + onChange={handleChange} + error={errors.email} + /> + + +
+
); }; From d871907d976edc829845739826121443794da41f Mon Sep 17 00:00:00 2001 From: Daniel Cojocea Date: Mon, 22 Jul 2024 17:03:09 -0400 Subject: [PATCH 062/131] Pagination fix --- Client/src/Components/BasicTable/index.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Client/src/Components/BasicTable/index.jsx b/Client/src/Components/BasicTable/index.jsx index fbd8759e5..93eba2024 100644 --- a/Client/src/Components/BasicTable/index.jsx +++ b/Client/src/Components/BasicTable/index.jsx @@ -91,7 +91,7 @@ const BasicTable = ({ data, paginated, reversed }) => { } let paginationComponent = <>; - if (paginated === true && displayData.length > rowsPerPage) { + if (paginated === true && data.rows.length > rowsPerPage) { paginationComponent = ( Date: Mon, 22 Jul 2024 14:28:03 -0700 Subject: [PATCH 063/131] Added endponts and routes for fetching monitors with incidents --- Server/controllers/monitorController.js | 41 +++++++++++++++++++++++++ Server/db/MongoDB.js | 41 ++++++++++++++++++++++--- Server/routes/monitorRoute.js | 9 ++++++ 3 files changed, 87 insertions(+), 4 deletions(-) diff --git a/Server/controllers/monitorController.js b/Server/controllers/monitorController.js index 4e51aca97..45a55a973 100644 --- a/Server/controllers/monitorController.js +++ b/Server/controllers/monitorController.js @@ -98,15 +98,54 @@ const getMonitorsByUserId = async (req, res, next) => { } }; +/** + * Returns monitor with matching ID and incidents + * @async + * @param {Express.Request} req + * @param {Express.Response} res + * @returns {Promise} + * @throws {Error} + */ const getMonitorByIdForIncidents = async (req, res, next) => { try { + await getMonitorByIdValidation.validateAsync(req.params); + + let monitorWithIncidents = await req.db.getMonitorByIdForIncidents( + req, + res + ); + + return res.json({ + success: true, + msg: successMessages.MONTIOR_GET_BY_ID, + data: monitorWithIncidents, + }); } catch (error) { error.service = SERVICE_NAME; next(error); } }; + +/** + * Returns all monitors with incidents that belong to User with UserID + * @async + * @param {Express.Request} req + * @param {Express.Response} res + * @returns {Promise} + * @throws {Error} + */ const getMonitorsByUserIdForIncidents = async (req, res, next) => { try { + await getMonitorsByUserIdValidation.validateAsync(req.params); + let monitorsWithIncidents = await req.db.getMonitorsByUserIdForIncidents( + req, + res + ); + return res.json({ + success: true, + msg: successMessages.MONITOR_GET_BY_USER_ID(req.params.userId), + data: monitorsWithIncidents, + }); } catch (error) { error.service = SERVICE_NAME; next(error); @@ -242,6 +281,8 @@ module.exports = { getAllMonitors, getMonitorById, getMonitorsByUserId, + getMonitorByIdForIncidents, + getMonitorsByUserIdForIncidents, createMonitor, deleteMonitor, deleteAllMonitors, diff --git a/Server/db/MongoDB.js b/Server/db/MongoDB.js index 86160b91c..644d446ac 100644 --- a/Server/db/MongoDB.js +++ b/Server/db/MongoDB.js @@ -131,7 +131,6 @@ const updateUser = async (req, res) => { ) .select("-password") .select("-profileImage"); - console.log(updatedUser); return updatedUser; } catch (error) { throw error; @@ -346,7 +345,21 @@ const getMonitorsByUserId = async (req, res) => { * @returns {Promise} * @throws {Error} */ -const getMonitorByIdForIncidents = async (req, res, next) => {}; +const getMonitorByIdForIncidents = async (req, res, next) => { + try { + const monitor = await Monitor.findById(req.params.monitorId); + const checks = await Check.find({ + monitorId: monitor._id, + status: false, + }).sort({ + createdAt: 1, + }); + const monitorWithChecks = { ...monitor.toObject(), checks }; + return monitorWithChecks; + } catch (error) { + throw error; + } +}; /** * Get monitors by UserID @@ -356,7 +369,26 @@ const getMonitorByIdForIncidents = async (req, res, next) => {}; * @returns {Promise>} * @throws {Error} */ -const getMonitorsByUserIdForIncidents = async (req, res, next) => {}; +const getMonitorsByUserIdForIncidents = async (req, res) => { + try { + const monitors = await Monitor.find({ userId: req.params.userId }); + // Map each monitor to include its associated checks + const monitorsWithChecks = await Promise.all( + monitors.map(async (monitor) => { + const checks = await Check.find({ + monitorId: monitor._id, + status: false, + }).sort({ + createdAt: 1, + }); + return { ...monitor.toObject(), checks }; + }) + ); + return monitorsWithChecks; + } catch (error) { + throw error; + } +}; /** * Create a monitor @@ -468,7 +500,6 @@ const editMonitor = async (req, res) => { const createCheck = async (checkData) => { try { - console.log(checkData); const check = await new Check({ ...checkData }).save(); return check; } catch (error) { @@ -657,6 +688,8 @@ module.exports = { getAllMonitors, getMonitorById, getMonitorsByUserId, + getMonitorByIdForIncidents, + getMonitorsByUserIdForIncidents, createMonitor, deleteMonitor, deleteAllMonitors, diff --git a/Server/routes/monitorRoute.js b/Server/routes/monitorRoute.js index ae7a5852e..9ba703244 100644 --- a/Server/routes/monitorRoute.js +++ b/Server/routes/monitorRoute.js @@ -7,6 +7,15 @@ router.get("/", monitorController.getAllMonitors); router.get("/:monitorId", monitorController.getMonitorById); router.get("/user/:userId", monitorController.getMonitorsByUserId); +router.get( + "/incidents/:monitorId", + monitorController.getMonitorByIdForIncidents +); +router.get( + "/incidents/user/:userId", + monitorController.getMonitorsByUserIdForIncidents +); + router.post("/", monitorController.createMonitor); router.post( "/delete/:monitorId", From 04d1d9ee558452d39556fc401de4911596af519b Mon Sep 17 00:00:00 2001 From: Daniel Cojocea Date: Mon, 22 Jul 2024 18:18:30 -0400 Subject: [PATCH 064/131] Fetch users from db --- .../TabPanels/Account/TeamPanel.jsx | 351 +++++------------- 1 file changed, 86 insertions(+), 265 deletions(-) diff --git a/Client/src/Components/TabPanels/Account/TeamPanel.jsx b/Client/src/Components/TabPanels/Account/TeamPanel.jsx index cc717485a..59ed4fb88 100644 --- a/Client/src/Components/TabPanels/Account/TeamPanel.jsx +++ b/Client/src/Components/TabPanels/Account/TeamPanel.jsx @@ -9,17 +9,12 @@ import { Modal, Select, Stack, - Table, - TableBody, - TableCell, - TableHead, - TableRow, TextField, Typography, } from "@mui/material"; import ButtonSpinner from "../../ButtonSpinner"; import Button from "../../Button"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import EditSvg from "../../../assets/icons/edit.svg?react"; import Field from "../../Inputs/Field"; import { credentials } from "../../../Validation/validation"; @@ -27,6 +22,7 @@ import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; import axiosInstance from "../../../Utils/axiosConfig"; import { createToast } from "../../../Utils/toastUtils"; import { useSelector } from "react-redux"; +import BasicTable from "../../BasicTable"; /** * TeamPanel component manages the organization and team members, @@ -36,138 +32,97 @@ import { useSelector } from "react-redux"; * @returns {JSX.Element} */ -const teamColumns = [ - { - id: "checkbox", - label: "", - sx: { minWidth: "20px", width: "40px" }, - }, - { - id: "name", - label: "NAME", - sx: { fontSize: "12px" }, - }, - { id: "email", label: "EMAIL", sx: { fontSize: "12px" } }, - { id: "role", label: "ROLE", sx: { fontSize: "12px" } }, -]; -//for testing, will be removed later -const teamConfig = [ - { - id: 0, - isChecked: false, - name: "John Connor", - email: "john@domain.com", - type: "admin", - role: "Administrator", - createdAt: "10/4/2022", - }, - { - id: 1, - isChecked: false, - name: "Adam McFadden", - email: "adam@domain.com", - type: "member", - role: "Member", - createdAt: "10/4/2022", - }, - { - id: 2, - isChecked: false, - name: "Cris Cross", - email: "cris@domain.com", - type: "member", - role: "Member", - createdAt: "10/4/2022", - }, - { - id: 3, - isChecked: false, - name: "Prince", - email: "prince@domain.com", - type: "member", - role: "Member", - createdAt: "10/4/2022", - }, -]; -const actionsConfig = [ - { - value: "bulk", - label: "Bulk actions", - }, -]; -const roleConfig = [ - { - value: "role", - label: "Change role to", - }, -]; - const TeamPanel = () => { const theme = useTheme(); - //TODO - use redux loading state - //!! - currently all loading buttons are tied to the same state - const [isLoading, setIsLoading] = useState(false); - //TODO - connect to redux + + const { authToken } = useSelector((state) => state.auth); + //TODO const [orgStates, setOrgStates] = useState({ name: "Bluewave Labs", - isLoading: false, isEdit: false, }); + const [toInvite, setToInvite] = useState({ + email: "", + role: "", + }); + const [teamStates, setTeamStates] = useState({}); + const [tableData, setTableData] = useState({}); + const [errors, setErrors] = useState({}); + useEffect(() => { + const fetchTeam = async () => { + try { + const response = await axiosInstance.get("/auth/users", { + headers: { Authorization: `Bearer ${authToken}` }, + }); + setTeamStates({ members: response.data.data, filters: "" }); + + const data = { + cols: [ + { id: 1, name: "NAME" }, + { id: 2, name: "EMAIL" }, + { id: 3, name: "ROLE" }, + ], + rows: response.data.data.map((member, idx) => { + return { + id: member._id, + data: [ + { id: idx, data: member.firstName + " " + member.lastName }, + { id: idx + 1, data: member.email }, + { + id: idx + 2, + data: member.role[0] === "admin" ? "Administrator" : "Member", + }, + ], + }; + }), + }; + + setTableData(data); + } catch (error) { + createToast({ + body: error.message || "Error fetching team members.", + }); + } + }; + + fetchTeam(); + }, []); + + // RENAME ORGANIZATION const toggleEdit = () => { setOrgStates((prev) => ({ ...prev, isEdit: !prev.isEdit })); }; const handleRename = () => {}; - const [teamStates, setTeamStates] = useState({ - members: teamConfig, - filter: "", - }); - const handleCheckCell = (id) => { - const updatedTeamStates = [...teamStates.members]; - updatedTeamStates[id] = { - ...updatedTeamStates[id], - isChecked: !updatedTeamStates[id].isChecked, - }; - setTeamStates((prev) => ({ - ...prev, - members: updatedTeamStates, - })); - }; - const handleFilter = (filter) => { - setTeamStates((prev) => ({ - ...prev, - filter: filter, - })); - }; - //TODO - implement select action function - const handleSelectActionType = () => { - setIsLoading(true); - setTimeout(() => { - setIsLoading(false); - }, 2000); - }; - //TODO - implement select role function - const handleSelectRoleType = () => { - setIsLoading(true); - setTimeout(() => { - setIsLoading(false); - }, 2000); - }; - //TODO - implement save team function - const handleSaveTeam = () => { - setIsLoading(true); - setTimeout(() => { - setIsLoading(false); - }, 2000); + // TABLE ACTIONS + const handleMembersQuery = (type) => { + let count = 0; + tableData.rows?.forEach((member) => { + type === "" ? count++ : member.data[2].data === type ? count++ : ""; + }); + return count; }; - const { authToken } = useSelector((state) => state.auth); - const [toInvite, setToInvite] = useState({ - email: "", - role: "", - }); - const [errors, setErrors] = useState({}); + // const handleCheckCell = (id) => { + // const updatedTeamStates = [...teamStates.members]; + // updatedTeamStates[id] = { + // ...updatedTeamStates[id], + // isChecked: !updatedTeamStates[id].isChecked, + // }; + // setTeamStates((prev) => ({ + // ...prev, + // members: updatedTeamStates, + // })); + // }; + // const handleFilter = (filter) => { + // setTeamStates((prev) => ({ + // ...prev, + // filter: filter, + // })); + // }; + //TODO - implement save team function + const handleSaveTeam = () => {}; const handleChange = (event) => { const { value } = event.target; @@ -192,6 +147,8 @@ const TeamPanel = () => { return updatedErrors; }); }; + + // INVITE MEMBER const [isOpen, setIsOpen] = useState(false); const handleInviteMember = async () => { if (toInvite.role !== "user" || toInvite !== "admin") @@ -233,13 +190,6 @@ const TeamPanel = () => { setErrors({}); }; - const handleMembersQuery = (type) => { - let count = 0; - teamStates.members.forEach((member) => { - type === "" ? count++ : member.type === type ? count++ : ""; - }); - return count; - }; return (
@@ -315,13 +265,13 @@ const TeamPanel = () => { handleFilter("admin")}> Administrator - {handleMembersQuery("admin")} + {handleMembersQuery("Administrator")} handleFilter("member")}> Member - {handleMembersQuery("member")} + {handleMembersQuery("Member")} @@ -332,136 +282,7 @@ const TeamPanel = () => { onClick={() => setIsOpen(true)} /> -
- - - - - - - - - - - - - - - {teamColumns.map((cell) => ( - - {cell.label} - - ))} - - - - {teamStates.members.map((cell) => - teamStates.filter === "" || - teamStates.filter === cell.type ? ( - - - handleCheckCell(cell.id)} - inputProps={{ "aria-label": "controlled" }} - /> - - - - - {cell.name} - - Created at {cell.createdAt} - - - {cell.email} - {cell.role} - - ) : ( - "" - ) - )} - -
-
-
+