diff --git a/src/components/Projects/Members/Members.jsx b/src/components/Projects/Members/Members.jsx index 202f5aa5cd..657c9056bc 100644 --- a/src/components/Projects/Members/Members.jsx +++ b/src/components/Projects/Members/Members.jsx @@ -21,11 +21,15 @@ import { boxStyle, boxStyleDark } from 'styles'; import ToggleSwitch from 'components/UserProfile/UserProfileEdit/ToggleSwitch'; import Loading from 'components/common/Loading'; - const Members = props => { const darkMode = props.state.theme.darkMode; - const projectId = props.match.params.projectId; + + // Get the project name from props or sessionStorage + const projectName = props.location.state && props.location.state.projectName + ? props.location.state.projectName + : sessionStorage.getItem('projectName') || 'Unknown Project'; + const [showFindUserList, setShowFindUserList] = useState(false); const [membersList, setMembersList] = useState(props.state.projectMembers.members); const [lastTimeoutId, setLastTimeoutId] = useState(null); @@ -45,9 +49,8 @@ const Members = props => { }, [projectId]); const assignAll = async () => { - const allUsers = props.state.projectMembers.foundUsers.filter(user => user.assigned === false); + const allUsers = props.state.projectMembers.foundUsers.filter(user => !user.assigned); - // Wait for all members to be assigned await Promise.all( allUsers.map(user => props.assignProject(projectId, user._id, 'Assign', user.firstName, user.lastName), @@ -63,7 +66,6 @@ const Members = props => { } }, [props.state.projectMembers.members, isLoading]); - // ADDED: State for toggling display of active members only const [showActiveMembersOnly, setShowActiveMembersOnly] = useState(false); const displayedMembers = showActiveMembersOnly @@ -76,7 +78,6 @@ const Members = props => { setMembersList(props.state.projectMembers.members); }; - // Waits for user to finsh typing before calling API const handleInputChange = event => { const currentValue = event.target.value; @@ -92,7 +93,7 @@ const Members = props => { return ( -
+
+ {canAssignProjectToUsers ? (
@@ -124,7 +127,7 @@ const Members = props => { @@ -147,9 +150,7 @@ const Members = props => { - + {canAssignProjectToUsers ? ( @@ -191,15 +192,15 @@ const Members = props => { handleUserProfile={handleToggle} /> - {isLoading ? ( ) : ( + {isLoading ? ( + + ) : (
- # - # Name Email
- - - {canUnassignUserInProject ? : null} + + + {canUnassignUserInProject ? : null} @@ -209,12 +210,12 @@ const Members = props => { key={member._id ?? i} projectId={projectId} uid={member._id} - fullName={member.firstName + ' ' + member.lastName} + fullName={`${member.firstName} ${member.lastName}`} darkMode={darkMode} /> ))} -
- # - #NameAction
+ )}
@@ -225,6 +226,7 @@ const Members = props => { const mapStateToProps = state => { return { state }; }; + export default connect(mapStateToProps, { fetchAllMembers, findUserProfiles, diff --git a/src/components/Projects/Project/Project.jsx b/src/components/Projects/Project/Project.jsx index 10dad8ccf3..5b013f8e86 100644 --- a/src/components/Projects/Project/Project.jsx +++ b/src/components/Projects/Project/Project.jsx @@ -7,137 +7,89 @@ import { connect } from 'react-redux'; import hasPermission from 'utils/permissions'; import { boxStyle } from 'styles'; import { toast } from 'react-toastify'; -import { modifyProject, clearError } from '../../../actions/projects'; -import ModalTemplate from './../../common/Modal'; -import { CONFIRM_ARCHIVE } from './../../../languages/en/messages'; -const Project = props => { +const Project = (props) => { const { darkMode, index } = props; const [firstLoad, setFirstLoad] = useState(true); const [projectData, setProjectData] = useState(props.projectData); - const { projectName, isActive,isArchived, _id: projectId } = projectData; + const { projectName, isActive, _id: projectId } = projectData; const [displayName, setDisplayName] = useState(projectName); - const initialModalData = { - showModal: false, - modalMessage: "", - modalTitle: "", - hasConfirmBtn: false, - hasInactiveBtn: false, - }; - - const [modalData, setModalData] = useState(initialModalData); - - const onCloseModal = () => { - setModalData(initialModalData); - props.clearError(); - }; const [category, setCategory] = useState(props.category || 'Unspecified'); // Initialize with props or default + const [category, setCategory] = useState(props.category || 'Unspecified'); const canPutProject = props.hasPermission('putProject'); const canDeleteProject = props.hasPermission('deleteProject'); - const canSeeProjectManagementFullFunctionality = props.hasPermission('seeProjectManagement'); const canEditCategoryAndStatus = props.hasPermission('editProject'); - const updateProject = ({ updatedProject, status }) => async dispatch => { - try { - dispatch(updateProject({ updatedProject, status })); - } catch (err) { - const status = err?.response?.status || 500; - const error = err?.response?.data || { message: 'An error occurred' }; - dispatch(updateProject({ status, error })); - } + const updateProject = (key, value) => { + setProjectData({ + ...projectData, + [key]: value, + }); }; const onDisplayNameChange = (e) => { setDisplayName(e.target.value); - } + }; const onUpdateProjectName = () => { if (displayName.length < 3) { toast.error('Project name must be at least 3 characters long'); - setDisplayName(displayName); } else if (displayName !== projectName) { updateProject('projectName', displayName); - } + } }; const onUpdateProjectActive = () => { updateProject('isActive', !isActive); - } + }; const onUpdateProjectCategory = (e) => { setCategory(e.target.value); - updateProject('category', e.target.value); // Update the projectData state + updateProject('category', e.target.value); }; const onArchiveProject = () => { - setModalData({ - showModal: true, - modalMessage: `

Do you want to archive ${projectData.projectName}?

`, - modalTitle: CONFIRM_ARCHIVE, - hasConfirmBtn: true, - hasInactiveBtn: isActive, - }); - } - - const setProjectInactive = () => { - updateProject('isActive', !isActive); - onCloseModal(); - } - const confirmArchive = () => { - updateProject('isArchived', !isArchived); - props.onProjectArchived(); - onCloseModal(); + props.onClickArchiveBtn(projectData); }; useEffect(() => { - const onUpdateProject = async () => { - if (firstLoad) { - setFirstLoad(false); - } else { - await props.modifyProject(projectData); - } - }; - - onUpdateProject(); + if (firstLoad) { + setFirstLoad(false); + } else { + props.onUpdateProject(projectData); + } + if (props.projectData.category) { + setCategory(props.projectData.category); + } }, [projectData]); return ( - <> -
{index + 1}
- - {(canPutProject || canSeeProjectManagementFullFunctionality) ? ( - - + {canPutProject || canSeeProjectManagementFullFunctionality ? ( onUpdateProjectName(displayName)} + onBlur={onUpdateProjectName} /> ) : ( projectName )} - + {canEditCategoryAndStatus || canPutProject ? ( - + ) : ( + projectName + )} + + + + {canEditCategoryAndStatus || canPutProject ? ( + + ) : ( + category + )} + + + + {isActive ? ( +
+ +
+ ) : ( +
+ +
+ )} + + + + + + + + + + + + + + + + + + + + + {canDeleteProject && ( + + + + )} + + + {showModal && ( +
+

Confirm Archive

+

Do you want to archive {projectName}?

+ + +
+ )} + + ); +}; - await waitFor(() => { - // check if the active status is active after clicking - const activeStatus = getByTestId('project-active').querySelector('i'); - expect(activeStatus).toHaveClass('fa-circle'); - }); - }); - - it('triggers delete action on button click', () => { - const { getByTestId } = renderProject(sampleProps); - - // Find the delete button and click it - const deleteButton = getByTestId('delete-button'); - fireEvent.click(deleteButton); - - // Check if the modal is triggered - const modal = document.querySelector('.modal'); - expect(modal).toBeInTheDocument(); - - const archiveButton=screen.getAllByText('Archive')[0]; - fireEvent.click(archiveButton); - - expect(screen.getByText('Confirm Archive')).toBeInTheDocument(); - expect(screen.getByText(`Do you want to archive ${sampleProjectData.projectName}?`)).toBeInTheDocument(); - - const closeButton=screen.getByText('Close') - fireEvent.click(closeButton) - expect(screen.queryByText('Confirm Archive')).not.toBeInTheDocument(); - }); -}); +const mapStateToProps = (state) => state; +export default connect(mapStateToProps, { hasPermission })(Project);