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 { ProjectRoleChange } from "../Components/ChangeRole";
|
||||||
import { projectTimes } from "../Components/GetProjectTimes";
|
import { projectTimes } from "../Components/GetProjectTimes";
|
||||||
import { ProjectMember } from "../Components/GetUsersInProject";
|
import { ProjectMember } from "../Components/GetUsersInProject";
|
||||||
|
@ -100,7 +100,7 @@ interface API {
|
||||||
): Promise<APIResponse<string>>;
|
): Promise<APIResponse<string>>;
|
||||||
|
|
||||||
/** Gets a weekly report for a specific user, project and week.
|
/** 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.
|
* of the project to get the report, unless the user is the target user.
|
||||||
* @param {string} projectName The name of the project.
|
* @param {string} projectName The name of the project.
|
||||||
* @param {string} week The week number.
|
* @param {string} week The week number.
|
||||||
|
@ -196,7 +196,7 @@ interface API {
|
||||||
): Promise<APIResponse<void>>;
|
): Promise<APIResponse<void>>;
|
||||||
|
|
||||||
addUserToProject(
|
addUserToProject(
|
||||||
user: NewProjMember,
|
addMemberInfo: AddMemberInfo,
|
||||||
token: string,
|
token: string,
|
||||||
): Promise<APIResponse<void>>;
|
): Promise<APIResponse<void>>;
|
||||||
|
|
||||||
|
@ -335,18 +335,20 @@ export const api: API = {
|
||||||
},
|
},
|
||||||
|
|
||||||
async addUserToProject(
|
async addUserToProject(
|
||||||
user: NewProjMember,
|
addMemberInfo: AddMemberInfo,
|
||||||
token: string,
|
token: string,
|
||||||
): Promise<APIResponse<void>> {
|
): Promise<APIResponse<void>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch("/api/addUserToProject", {
|
const response = await fetch(
|
||||||
method: "PUT",
|
`/api/addUserToProject/${addMemberInfo.projectName}/?userName=${addMemberInfo.userName}`,
|
||||||
headers: {
|
{
|
||||||
"Content-Type": "application/json",
|
method: "PUT",
|
||||||
Authorization: "Bearer " + token,
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Authorization: "Bearer " + token,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
body: JSON.stringify(user),
|
);
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
return { success: false, message: "Failed to add member" };
|
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 {
|
export interface AddMemberInfo {
|
||||||
username: string;
|
userName: string;
|
||||||
role: string;
|
projectName: string;
|
||||||
projectname: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries to add a member to a project
|
* Tries to add a member to a project
|
||||||
* @param {Object} props - A NewProjMember
|
* @param {AddMemberInfo} props.membertoAdd - Contains user's name and project's name
|
||||||
* @returns {boolean} True if added, false if not
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
function AddMember(props: { memberToAdd: NewProjMember }): boolean {
|
async function AddMember(props: { memberToAdd: AddMemberInfo }): Promise<void> {
|
||||||
let added = false;
|
if (props.memberToAdd.userName === "") {
|
||||||
if (
|
alert("You must choose at least one user to add");
|
||||||
props.memberToAdd.username === "" ||
|
return;
|
||||||
props.memberToAdd.role === "" ||
|
|
||||||
props.memberToAdd.projectname === ""
|
|
||||||
) {
|
|
||||||
alert("All fields must be filled before adding");
|
|
||||||
return added;
|
|
||||||
}
|
}
|
||||||
api
|
try {
|
||||||
.addUserToProject(
|
const response = await api.addUserToProject(
|
||||||
props.memberToAdd,
|
props.memberToAdd,
|
||||||
localStorage.getItem("accessToken") ?? "",
|
localStorage.getItem("accessToken") ?? "",
|
||||||
)
|
);
|
||||||
.then((response: APIResponse<void>) => {
|
if (response.success) {
|
||||||
if (response.success) {
|
alert(`[${props.memberToAdd.userName}] added`);
|
||||||
alert("Member added");
|
} else {
|
||||||
added = true;
|
alert(`[${props.memberToAdd.userName}] not added`);
|
||||||
} else {
|
console.error(response.message);
|
||||||
alert("Member not added");
|
}
|
||||||
console.error(response.message);
|
} catch (error) {
|
||||||
}
|
alert(`[${props.memberToAdd.userName}] not added`);
|
||||||
})
|
console.error("An error occurred during member add:", error);
|
||||||
.catch((error) => {
|
}
|
||||||
console.error("An error occurred during member add:", error);
|
|
||||||
});
|
|
||||||
return added;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AddMember;
|
export default AddMember;
|
||||||
|
|
|
@ -1,71 +1,86 @@
|
||||||
import { useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import Button from "./Button";
|
import Button from "./Button";
|
||||||
import GetAllUsers from "./GetAllUsers";
|
import AddMember, { AddMemberInfo } from "./AddMember";
|
||||||
import AddMember, { NewProjMember } from "./AddMember";
|
|
||||||
import BackButton from "./BackButton";
|
import BackButton from "./BackButton";
|
||||||
|
import GetUsersInProject, { ProjectMember } from "./GetUsersInProject";
|
||||||
|
import GetAllUsers from "./GetAllUsers";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides UI for adding a member to a project.
|
* Provides UI for adding a member to a project.
|
||||||
* @returns {JSX.Element} - Returns the component UI for adding a member
|
* @returns {JSX.Element} - Returns the component UI for adding a member
|
||||||
*/
|
*/
|
||||||
function AddUserToProject(props: { projectName: string }): JSX.Element {
|
function AddUserToProject(props: { projectName: string }): JSX.Element {
|
||||||
const [name, setName] = useState("");
|
const [names, setNames] = useState<string[]>([]);
|
||||||
const [users, setUsers] = useState<string[]>([]);
|
const [users, setUsers] = useState<string[]>([]);
|
||||||
const [role, setRole] = useState("");
|
const [usersProj, setUsersProj] = useState<ProjectMember[]>([]);
|
||||||
GetAllUsers({ setUsersProp: setUsers });
|
|
||||||
|
|
||||||
const handleClick = (): boolean => {
|
// Gets all users and project members for filtering
|
||||||
const newMember: NewProjMember = {
|
GetAllUsers({ setUsersProp: setUsers });
|
||||||
username: name,
|
GetUsersInProject({
|
||||||
projectname: props.projectName,
|
setUsersProp: setUsersProj,
|
||||||
role: role,
|
projectName: props.projectName,
|
||||||
};
|
});
|
||||||
return AddMember({ memberToAdd: newMember });
|
/*
|
||||||
|
* 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 (
|
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]">
|
<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">
|
||||||
<p className="pb-4 mb-2 text-center font-bold text-[18px]">
|
<h1 className="text-center font-bold text-[36px] pb-10">
|
||||||
User chosen: [{name}]
|
{props.projectName}
|
||||||
|
</h1>
|
||||||
|
<p className="p-1 text-center font-bold text-[26px]">
|
||||||
|
Choose users to add:
|
||||||
</p>
|
</p>
|
||||||
<p className="pb-4 mb-2 text-center font-bold text-[18px]">
|
<div className="border-2 border-black pl-2 pr-2 pb-2 rounded-xl text-center overflow-auto h-[26vh] w-[26vh]">
|
||||||
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]">
|
|
||||||
<ul className="text-center font-medium space-y-2">
|
<ul className="text-center font-medium space-y-2">
|
||||||
<div></div>
|
<div></div>
|
||||||
{users.map((user) => (
|
{users.map((user) => (
|
||||||
<li
|
<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}
|
key={user}
|
||||||
value={user}
|
value={user}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setName(user);
|
handleUserClick(user);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span>{user}</span>
|
<span>{user}</span>
|
||||||
|
@ -73,13 +88,16 @@ function AddUserToProject(props: { projectName: string }): JSX.Element {
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</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
|
<Button
|
||||||
text="Add"
|
text="Add"
|
||||||
onClick={(): void => {
|
onClick={(): void => {
|
||||||
handleClick();
|
void handleAddClick();
|
||||||
}}
|
}}
|
||||||
type="submit"
|
type="button"
|
||||||
/>
|
/>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Reference in a new issue