diff --git a/Client/src/Components/TabPanels/ProfileSettings/PasswordPanel.jsx b/Client/src/Components/TabPanels/ProfileSettings/PasswordPanel.jsx index 8a7763fa2..8343a9819 100644 --- a/Client/src/Components/TabPanels/ProfileSettings/PasswordPanel.jsx +++ b/Client/src/Components/TabPanels/ProfileSettings/PasswordPanel.jsx @@ -22,11 +22,12 @@ import ButtonSpinner from "../../ButtonSpinner"; * PasswordPanel component manages the form for editing password. * * @returns {JSX.Element} - * */ const PasswordPanel = () => { const theme = useTheme(); + //TODO - use redux loading state + //!! - currently all loading buttons are tied to the same state const [isLoading, setIsLoading] = useState(false); const [showPassword, setShowPassword] = useState(false); diff --git a/Client/src/Components/TabPanels/ProfileSettings/ProfilePanel.jsx b/Client/src/Components/TabPanels/ProfileSettings/ProfilePanel.jsx index 5b51a0f2b..024b1d499 100644 --- a/Client/src/Components/TabPanels/ProfileSettings/ProfilePanel.jsx +++ b/Client/src/Components/TabPanels/ProfileSettings/ProfilePanel.jsx @@ -19,7 +19,6 @@ import Button from "../../Button"; * and deleting account. * * @returns {JSX.Element} - * */ const ProfilePanel = () => { diff --git a/Client/src/Components/TabPanels/ProfileSettings/TeamPanel.jsx b/Client/src/Components/TabPanels/ProfileSettings/TeamPanel.jsx new file mode 100644 index 000000000..326dfa2ef --- /dev/null +++ b/Client/src/Components/TabPanels/ProfileSettings/TeamPanel.jsx @@ -0,0 +1,569 @@ +import { useTheme } from "@emotion/react"; +import TabPanel from "@mui/lab/TabPanel"; +import { + Box, + Checkbox, + Container, + Divider, + MenuItem, + 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"; + +/** + * TeamPanel component manages the organization and team members, + * providing functionalities like renaming the organization, managing team members, + * and inviting new members. + * + * @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); + const [orgStates, setOrgStates] = useState({ + name: "Bluewave Labs", + isLoading: false, + isOpen: false, + newName: "", + }); + const toggleOrgModal = (state) => { + setOrgStates((prev) => ({ + ...prev, + isOpen: state, + })); + }; + const toggleOrgLoading = (state) => { + setOrgStates((prev) => ({ + ...prev, + isLoading: state, + })); + }; + const handleRenameOrg = () => { + toggleOrgLoading(true); + + setTimeout(() => { + setOrgStates((prev) => ({ + ...prev, + name: prev.newName !== "" ? prev.newName : prev.name, + isLoading: false, + isOpen: false, + newName: "", + })); + }, 2000); + }; + + 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); + }; + const [toggleInviteModal, setToggleInviteModal] = useState(false); + const handleInviteMember = () => {}; + const handleMembersQuery = (type) => { + let count = 0; + teamStates.members.forEach((member) => { + type === "" ? count++ : member.type === type ? count++ : ""; + }); + return count; + }; + return ( + + + + + + Organization name + + + + toggleOrgModal(true)} + isLoading={orgStates.isLoading} + sx={{ fontSize: "13px" }} + /> + toggleOrgModal(true)} + /> + + + + + Team members + + + + + handleFilter("")} sx={{ cursor: "pointer" }}> + All + + {handleMembersQuery("")} + + + handleFilter("admin")} + sx={{ cursor: "pointer" }} + > + Administrator + + {handleMembersQuery("admin")} + + + handleFilter("member")} + sx={{ cursor: "pointer" }} + > + Member + + {handleMembersQuery("member")} + + + + setToggleInviteModal(true)} + /> + + + + + + + {actionsConfig.map((action) => ( + + {action.label} + + ))} + + + + + + {roleConfig.map((role) => ( + + {role.label} + + ))} + + + + + + + + {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} + + ) : ( + "" + ) + )} + + + + + + + + + + + + toggleOrgModal(false)} + disablePortal + > + + + Rename this organization? + + + setOrgStates((prev) => ({ + ...prev, + newName: event.target.value, + })) + } + > + + toggleOrgModal(false)} + sx={{ fontSize: "13px" }} + /> + + + + + setToggleInviteModal(false)} + 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, + // })) + // } + > + + setToggleInviteModal(false)} + sx={{ fontSize: "13px" }} + /> + + + + + + ); +}; + +TeamPanel.propTypes = { + // No props are being passed to this component, hence no specific PropTypes are defined. +}; + +export default TeamPanel; diff --git a/Client/src/Pages/Settings/index.jsx b/Client/src/Pages/Settings/index.jsx index 465284e72..c49b08a38 100644 --- a/Client/src/Pages/Settings/index.jsx +++ b/Client/src/Pages/Settings/index.jsx @@ -2,131 +2,26 @@ import PropTypes from "prop-types"; import { useState } from "react"; import { Box, - Typography, Tab, useTheme, - TextField, - Stack, - Divider, - Modal, - FormControl, - OutlinedInput, - InputAdornment, - IconButton, - Container, - Table, - TableHead, - TableRow, - TableCell, - TableBody, - Checkbox, - Select, - MenuItem, } from "@mui/material"; -import TabPanel from "@mui/lab/TabPanel"; import TabContext from "@mui/lab/TabContext"; import TabList from "@mui/lab/TabList"; -import Visibility from "@mui/icons-material/Visibility"; -import VisibilityOff from "@mui/icons-material/VisibilityOff"; -import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined"; -import WarningAmberOutlinedIcon from "@mui/icons-material/WarningAmberOutlined"; -import ButtonSpinner from "../../Components/ButtonSpinner"; -import Button from "../../Components/Button"; import "./index.css"; -import AnnouncementsDualButtonWithIcon from "../../Components/Announcements/AnnouncementsDualButtonWithIcon/AnnouncementsDualButtonWithIcon"; import ProfilePanel from "../../Components/TabPanels/ProfileSettings/ProfilePanel"; import PasswordPanel from "../../Components/TabPanels/ProfileSettings/PasswordPanel"; +import TeamPanel from "../../Components/TabPanels/ProfileSettings/TeamPanel"; + +/** + * Settings component renders a settings page with tabs for Profile, Password, and Team settings. + * + * @returns {JSX.Element} + */ const tabList = ["Profile", "Password", "Team"]; -const passwordConfig = { - current_password: { - id: "edit-current-password", - label: "Current password", - type: "input", - }, - password: { - id: "edit-password", - label: "Password", - type: "input", - }, - confirm_password: { - id: "notice-confirm-password", - label: "Confirm new password", - type: "notice", - }, -}; -const orgConfig = { - name: "Bluewave Labs", - isLoading: false, - isOpen: false, - newName: "", -}; -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" } }, -]; -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 Settings = () => { + const theme = useTheme(); //(tab) 0 - Profile //(tab) 1 - Password //(tab) 2 - Team @@ -135,95 +30,6 @@ const Settings = () => { setTab(newTab); }; - const theme = useTheme(); - - const [isLoading, setIsLoading] = useState(false); - const [isOpen, setIsOpen] = useState(false); - - const handleDeleteAccount = () => { - setIsLoading(true); - setTimeout(() => { - setIsLoading(false); - setIsOpen(false); - }, 2000); - }; - const [showPassword, setShowPassword] = useState(false); - - const [orgStates, setOrgStates] = useState(orgConfig); - const toggleOrgModal = (state) => { - setOrgStates((prev) => ({ - ...prev, - isOpen: state, - })); - }; - const toggleOrgLoading = (state) => { - setOrgStates((prev) => ({ - ...prev, - isLoading: state, - })); - }; - const handleRenameOrg = () => { - toggleOrgLoading(true); - - setTimeout(() => { - setOrgStates((prev) => ({ - ...prev, - name: prev.newName !== "" ? prev.newName : prev.name, - isLoading: false, - isOpen: false, - newName: "", - })); - }, 2000); - }; - - const [teamStates, setTeamStates] = useState({ - members: teamConfig, - filter: "", - }); - const handleCellChecked = (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, - })); - }; - const handleApplyActionSelect = () => { - setIsLoading(true); - setTimeout(() => { - setIsLoading(false); - }, 2000); - }; - const handleApplyRoleSelect = () => { - setIsLoading(true); - setTimeout(() => { - setIsLoading(false); - }, 2000); - }; - const handleSaveTeam = () => { - setIsLoading(true); - setTimeout(() => { - setIsLoading(false); - }, 2000); - }; - const [toggleInviteModal, setToggleInviteModal] = useState(false); - const handleInviteMember = () => {}; - const handleMembersQuery = (type) => { - let count = 0; - teamStates.members.forEach((member) => { - type === "" ? count++ : member.type === type ? count++ : ""; - }); - return count; - }; return ( { - - - - - - Organization name - - - - toggleOrgModal(true)} - isLoading={orgStates.isLoading} - sx={{ fontSize: "13px" }} - /> - toggleOrgModal(true)} - /> - - - - - Team members - - - - - handleFilter("")} - sx={{ cursor: "pointer" }} - > - All - - {handleMembersQuery("")} - - - handleFilter("admin")} - sx={{ cursor: "pointer" }} - > - Administrator - - {handleMembersQuery("admin")} - - - handleFilter("member")} - sx={{ cursor: "pointer" }} - > - Member - - {handleMembersQuery("member")} - - - - setToggleInviteModal(true)} - /> - - - - - - - {actionsConfig.map((action) => ( - - {action.label} - - ))} - - - - - - {roleConfig.map((role) => ( - - {role.label} - - ))} - - - - - - - - {teamColumns.map((cell) => ( - - {cell.label} - - ))} - - - - {teamStates.members.map((cell) => - teamStates.filter === "" || - teamStates.filter === cell.type ? ( - - - handleCellChecked(cell.id)} - inputProps={{ "aria-label": "controlled" }} - /> - - - - - {cell.name} - - Created at {cell.createdAt} - - - {cell.email} - {cell.role} - - ) : ( - "" - ) - )} - - - - - - {/* !!! - All save buttons are tied to the same state */} - {/* TODO - Implement Save Team function */} - - - - - - - + - toggleOrgModal(false)} - disablePortal - > - - - Rename this organization? - - - setOrgStates((prev) => ({ - ...prev, - newName: event.target.value, - })) - } - > - - toggleOrgModal(false)} - sx={{ fontSize: "13px" }} - /> - - - - - setToggleInviteModal(false)} - 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, - // })) - // } - > - - setToggleInviteModal(false)} - sx={{ fontSize: "13px" }} - /> - - - - ); }; +Settings.propTypes = { + // No props are being passed to this component, hence no specific PropTypes are defined. +}; + export default Settings;