Fixes to adding members
This commit is contained in:
		
							parent
							
								
									a1d2520d88
								
							
						
					
					
						commit
						9a0f855d2b
					
				
					 3 changed files with 104 additions and 93 deletions
				
			
		|  | @ -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<APIResponse<string>>; | ||||
| 
 | ||||
|   /** 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<APIResponse<void>>; | ||||
| 
 | ||||
|   addUserToProject( | ||||
|     user: NewProjMember, | ||||
|     addMemberInfo: AddMemberInfo, | ||||
|     token: string, | ||||
|   ): Promise<APIResponse<void>>; | ||||
| 
 | ||||
|  | @ -335,18 +335,20 @@ export const api: API = { | |||
|   }, | ||||
| 
 | ||||
|   async addUserToProject( | ||||
|     user: NewProjMember, | ||||
|     addMemberInfo: AddMemberInfo, | ||||
|     token: string, | ||||
|   ): Promise<APIResponse<void>> { | ||||
|     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" }; | ||||
|  |  | |||
|  | @ -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<void>} | ||||
|  */ | ||||
| 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<void> { | ||||
|   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<void>) => { | ||||
|       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; | ||||
|  |  | |||
|  | @ -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<string[]>([]); | ||||
|   const [users, setUsers] = useState<string[]>([]); | ||||
|   const [role, setRole] = useState(""); | ||||
|   GetAllUsers({ setUsersProp: setUsers }); | ||||
|   const [usersProj, setUsersProj] = useState<ProjectMember[]>([]); | ||||
| 
 | ||||
|   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<void> => { | ||||
|     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 ( | ||||
|     <div className="border-4 border-black bg-white flex flex-col items-center justify-center rounded-3xl content-center pl-20 pr-20  h-[75vh] w-[50vh]"> | ||||
|       <p className="pb-4 mb-2 text-center font-bold text-[18px]"> | ||||
|         User chosen: [{name}] | ||||
|     <div className="border-4 border-black bg-white flex flex-col items-center pt-10 rounded-3xl content-center pl-20 pr-20  h-[63vh] w-[50] overflow-auto"> | ||||
|       <h1 className="text-center font-bold text-[36px] pb-10"> | ||||
|         {props.projectName} | ||||
|       </h1> | ||||
|       <p className="p-1 text-center font-bold text-[26px]"> | ||||
|         Choose users to add: | ||||
|       </p> | ||||
|       <p className="pb-4 mb-2 text-center font-bold text-[18px]"> | ||||
|         Role chosen: [{role}] | ||||
|       </p> | ||||
|       <p className="pb-4 mb-2 text-center font-bold text-[18px]"> | ||||
|         Project chosen: [{props.projectName}] | ||||
|       </p> | ||||
|       <p className="p-1">Choose role:</p> | ||||
|       <div className="border-2 border-black p-2 rounded-xl text-center h-[10h] w-[16] overflow-auto"> | ||||
|         <ul className="text-center items-center font-medium space-y-2"> | ||||
|           <li | ||||
|             className="h-[10] w-[14] items-start px-2 py-1 border-2 border-black rounded-full bg-orange-200 hover:bg-orange-600 hover:text-slate-100 hover:cursor-pointer" | ||||
|             onClick={() => { | ||||
|               setRole("member"); | ||||
|             }} | ||||
|           > | ||||
|             {"Member"} | ||||
|           </li> | ||||
|           <li | ||||
|             className="h-[10] w-[14] items-start px-2 py-1 border-2 border-black rounded-full bg-orange-200 hover:bg-orange-600 hover:text-slate-100 hover:cursor-pointer" | ||||
|             onClick={() => { | ||||
|               setRole("project_manager"); | ||||
|             }} | ||||
|           > | ||||
|             {"Project manager"} | ||||
|           </li> | ||||
|         </ul> | ||||
|       </div> | ||||
|       <p className="p-1">Choose user:</p> | ||||
|       <div className="border-2 border-black p-2 rounded-xl text-center overflow-scroll h-[26vh] w-[26vh]"> | ||||
|       <div className="border-2 border-black pl-2 pr-2 pb-2 rounded-xl text-center overflow-auto h-[26vh] w-[26vh]"> | ||||
|         <ul className="text-center font-medium space-y-2"> | ||||
|           <div></div> | ||||
|           {users.map((user) => ( | ||||
|             <li | ||||
|               className="items-start p-1 border-2 border-black rounded-full bg-orange-200 hover:bg-orange-600 hover:text-slate-100 hover:cursor-pointer" | ||||
|               className={ | ||||
|                 names.includes(user) | ||||
|                   ? "items-start p-1 border-2 border-transparent rounded-full bg-orange-500 hover:bg-orange-600 text-white hover:cursor-pointer ring-2 ring-black" | ||||
|                   : "items-start p-1 border-2 border-black rounded-full bg-orange-200 hover:bg-orange-400 hover:text-slate-100 hover:cursor-pointer" | ||||
|               } | ||||
|               key={user} | ||||
|               value={user} | ||||
|               onClick={() => { | ||||
|                 setName(user); | ||||
|                 handleUserClick(user); | ||||
|               }} | ||||
|             > | ||||
|               <span>{user}</span> | ||||
|  | @ -73,13 +88,16 @@ function AddUserToProject(props: { projectName: string }): JSX.Element { | |||
|           ))} | ||||
|         </ul> | ||||
|       </div> | ||||
|       <div className="flex space-x-5 items-center justify-between"> | ||||
|       <p className="pt-10 pb-5 underline text-center font-bold text-[18px]"> | ||||
|         Number of users to be added: {names.length} | ||||
|       </p> | ||||
|       <div className="space-x-10 items-center"> | ||||
|         <Button | ||||
|           text="Add" | ||||
|           onClick={(): void => { | ||||
|             handleClick(); | ||||
|             void handleAddClick(); | ||||
|           }} | ||||
|           type="submit" | ||||
|           type="button" | ||||
|         /> | ||||
|         <BackButton /> | ||||
|       </div> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Peter KW
						Peter KW