From 9a0f855d2b3f78bf4d18fff7d8faff62d0739215 Mon Sep 17 00:00:00 2001 From: Peter KW Date: Thu, 4 Apr 2024 11:26:39 +0200 Subject: [PATCH] Fixes to adding members --- frontend/src/API/API.ts | 24 ++-- frontend/src/Components/AddMember.tsx | 55 ++++----- frontend/src/Components/AddUserToProject.tsx | 118 +++++++++++-------- 3 files changed, 104 insertions(+), 93 deletions(-) diff --git a/frontend/src/API/API.ts b/frontend/src/API/API.ts index 16aebff..414d978 100644 --- a/frontend/src/API/API.ts +++ b/frontend/src/API/API.ts @@ -1,4 +1,4 @@ -import { NewProjMember } from "../Components/AddMember"; +import { AddMemberInfo } from "../Components/AddMember"; import { ProjectRoleChange } from "../Components/ChangeRole"; import { projectTimes } from "../Components/GetProjectTimes"; import { ProjectMember } from "../Components/GetUsersInProject"; @@ -100,7 +100,7 @@ interface API { ): Promise>; /** Gets a weekly report for a specific user, project and week. - * Keep in mind that the user within the token needs to be PM + * Keep in mind that the user within the token needs to be PM * of the project to get the report, unless the user is the target user. * @param {string} projectName The name of the project. * @param {string} week The week number. @@ -196,7 +196,7 @@ interface API { ): Promise>; addUserToProject( - user: NewProjMember, + addMemberInfo: AddMemberInfo, token: string, ): Promise>; @@ -335,18 +335,20 @@ export const api: API = { }, async addUserToProject( - user: NewProjMember, + addMemberInfo: AddMemberInfo, token: string, ): Promise> { try { - const response = await fetch("/api/addUserToProject", { - method: "PUT", - headers: { - "Content-Type": "application/json", - Authorization: "Bearer " + token, + const response = await fetch( + `/api/addUserToProject/${addMemberInfo.projectName}/?userName=${addMemberInfo.userName}`, + { + method: "PUT", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer " + token, + }, }, - body: JSON.stringify(user), - }); + ); if (!response.ok) { return { success: false, message: "Failed to add member" }; diff --git a/frontend/src/Components/AddMember.tsx b/frontend/src/Components/AddMember.tsx index 194afe8..d8036b7 100644 --- a/frontend/src/Components/AddMember.tsx +++ b/frontend/src/Components/AddMember.tsx @@ -1,44 +1,35 @@ -import { APIResponse, api } from "../API/API"; +import { api } from "../API/API"; -export interface NewProjMember { - username: string; - role: string; - projectname: string; +export interface AddMemberInfo { + userName: string; + projectName: string; } /** * Tries to add a member to a project - * @param {Object} props - A NewProjMember - * @returns {boolean} True if added, false if not + * @param {AddMemberInfo} props.membertoAdd - Contains user's name and project's name + * @returns {Promise} */ -function AddMember(props: { memberToAdd: NewProjMember }): boolean { - let added = false; - if ( - props.memberToAdd.username === "" || - props.memberToAdd.role === "" || - props.memberToAdd.projectname === "" - ) { - alert("All fields must be filled before adding"); - return added; +async function AddMember(props: { memberToAdd: AddMemberInfo }): Promise { + if (props.memberToAdd.userName === "") { + alert("You must choose at least one user to add"); + return; } - api - .addUserToProject( + try { + const response = await api.addUserToProject( props.memberToAdd, localStorage.getItem("accessToken") ?? "", - ) - .then((response: APIResponse) => { - if (response.success) { - alert("Member added"); - added = true; - } else { - alert("Member not added"); - console.error(response.message); - } - }) - .catch((error) => { - console.error("An error occurred during member add:", error); - }); - return added; + ); + if (response.success) { + alert(`[${props.memberToAdd.userName}] added`); + } else { + alert(`[${props.memberToAdd.userName}] not added`); + console.error(response.message); + } + } catch (error) { + alert(`[${props.memberToAdd.userName}] not added`); + console.error("An error occurred during member add:", error); + } } export default AddMember; diff --git a/frontend/src/Components/AddUserToProject.tsx b/frontend/src/Components/AddUserToProject.tsx index 039d3c0..f567560 100644 --- a/frontend/src/Components/AddUserToProject.tsx +++ b/frontend/src/Components/AddUserToProject.tsx @@ -1,71 +1,86 @@ -import { useState } from "react"; +import { useEffect, useState } from "react"; import Button from "./Button"; -import GetAllUsers from "./GetAllUsers"; -import AddMember, { NewProjMember } from "./AddMember"; +import AddMember, { AddMemberInfo } from "./AddMember"; import BackButton from "./BackButton"; +import GetUsersInProject, { ProjectMember } from "./GetUsersInProject"; +import GetAllUsers from "./GetAllUsers"; /** * Provides UI for adding a member to a project. * @returns {JSX.Element} - Returns the component UI for adding a member */ function AddUserToProject(props: { projectName: string }): JSX.Element { - const [name, setName] = useState(""); + const [names, setNames] = useState([]); const [users, setUsers] = useState([]); - const [role, setRole] = useState(""); - GetAllUsers({ setUsersProp: setUsers }); + const [usersProj, setUsersProj] = useState([]); - const handleClick = (): boolean => { - const newMember: NewProjMember = { - username: name, - projectname: props.projectName, - role: role, - }; - return AddMember({ memberToAdd: newMember }); + // Gets all users and project members for filtering + GetAllUsers({ setUsersProp: setUsers }); + GetUsersInProject({ + setUsersProp: setUsersProj, + projectName: props.projectName, + }); + /* + * Filters the members from users so that users who are already + * members are not shown + */ + useEffect(() => { + setUsers((prevUsers) => { + const filteredUsers = prevUsers.filter( + (user) => + !usersProj.some((projectUser) => projectUser.Username === user), + ); + return filteredUsers; + }); + }, [usersProj]); + + // Attempts to add all of the selected users to the project + const handleAddClick = async (): Promise => { + if (names.length === 0) + alert("You have to choose at least one user to add"); + for (const name of names) { + const newMember: AddMemberInfo = { + userName: name, + projectName: props.projectName, + }; + await AddMember({ memberToAdd: newMember }); + } + setNames([]); + location.reload(); + }; + + // Updates the names that have been selected + const handleUserClick = (user: string): void => { + setNames((prevNames): string[] => { + if (!prevNames.includes(user)) { + return [...prevNames, user]; + } + return prevNames.filter((name) => name !== user); + }); }; return ( -
-

- User chosen: [{name}] +

+

+ {props.projectName} +

+

+ Choose users to add:

-

- Role chosen: [{role}] -

-

- Project chosen: [{props.projectName}] -

-

Choose role:

-
-
    -
  • { - setRole("member"); - }} - > - {"Member"} -
  • -
  • { - setRole("project_manager"); - }} - > - {"Project manager"} -
  • -
-
-

Choose user:

-
+
    {users.map((user) => (
  • { - setName(user); + handleUserClick(user); }} > {user} @@ -73,13 +88,16 @@ function AddUserToProject(props: { projectName: string }): JSX.Element { ))}
-
+

+ Number of users to be added: {names.length} +

+