Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion frontend/react-app/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import AdminPanel from './pages/AdminPanel';
import CreateTask from './pages/CreateTask';
import ChangePassword from './pages/ChangePassword';
import EditUserDetails from './pages/EditUserDetails';
import CreatTeamPage from './pages/CreateTeamPage';


function App() {
Expand All @@ -38,7 +39,7 @@ function App() {
<Route path="/admin-panel" element={<ProtectedRoute allowedRoles={['admin']} protectedContent={<AdminPanel/>} urlReirect={"/home"}></ProtectedRoute>}/>
<Route path="/change-password" element={<ProtectedRoute allowedRoles={['admin','teamMember']} protectedContent={<ChangePassword/>} urlReirect={"/login"}></ProtectedRoute>}/>
<Route path="/edit-user-details" element={<ProtectedRoute allowedRoles={['admin']} protectedContent={<EditUserDetails/>} urlReirect={"/home"}></ProtectedRoute>}/>

<Route path="/create-team" element={<ProtectedRoute allowedRoles={['admin']} protectedContent={<CreatTeamPage/>} urlReirect={"/home"}></ProtectedRoute>}/>
{/*Default path should be login, unless specified */}
<Route path="/" exact element={<Login/>} />

Expand Down
8 changes: 1 addition & 7 deletions frontend/react-app/src/api/adminApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,21 +84,15 @@ export const unlockTask = async (taskId) => {

//Get all admins
export const getAdmins = async () => {
try {
const response = await fetch(`${BASE_URL}`, {
method: 'GET'
});

if (!response.ok) {
console.error(`Failed to retrieve admins: ${response.status} ${response.statusText}`);
throw Error(response);
}

return await response.json();
}
catch (error) {
console.error(`Failed to retrieve all admins: `, error);
throw error;
}
};

//reset password
Expand Down
17 changes: 3 additions & 14 deletions frontend/react-app/src/api/teamApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,22 @@ const BASE_URL = "http://localhost:8080/api/teams";

//Create a team
export const createTeam = async (teamLeadId, teamName) => {
try {
console.log(teamLeadId, teamName)
const response = await fetch(`${BASE_URL}`, {
method: 'POST',
headers: { "Content-Type": "application/json" },
body: JSON.stringify({teamLeadId, teamName})
});

if (!response.ok) {
console.error(`Failed to create team: ${response.status} ${response.statusText}`);
return null;
throw Error(response.statusText)
}

return await response.json();
}
catch (error) {
console.error("Error creating team: ", error);
return null;
}
};

//Delete a team
export const deleteTeam = async (teamId) => {
try {
const response = await fetch(`${BASE_URL}/${teamId}`, {
method: 'DELETE'
});
Expand All @@ -35,11 +28,7 @@ export const deleteTeam = async (teamId) => {
}

return true;
}
catch (error) {
console.error("Error deleting team: ", error);
return null;
}

};

//Change team lead
Expand Down
13 changes: 5 additions & 8 deletions frontend/react-app/src/api/teamMemberAccountApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,27 +87,24 @@ export const modifyTeamMemberEmail = async (teamMemberId, newEmail) => {

//Get a team member with their ID
export const getTeamMemberById = async (teamMemberId) => {
try {

const response = await fetch(`${BASE_URL}/${teamMemberId}`, {
method: 'GET'
});

if (!response.ok) {
console.error(`Failed to retrieve team member: ${response.status} ${response.statusText}`);
throw Error(response)
}

return await response.json();
}
catch (error) {
console.error(`Failed to retrieve team member: `, error);
throw error;
}


};

//Get all team ememebrs
export const getTeamMembers = async () => {
try {
const response = await fetch(`${BASE_URL}/team-members`, {
const response = await fetch(`${BASE_URL}`, {
method: 'GET'
});

Expand Down
2 changes: 1 addition & 1 deletion frontend/react-app/src/components/CreateTaskForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ function CreateTaskForm({userId}){
})
}
})
//window.location.href="/home";
window.location.href="/home";
} catch (error) {
console.log(error)
alert("FAILED IN MAKING TASK");
Expand Down
61 changes: 61 additions & 0 deletions frontend/react-app/src/components/CreateTeamForm.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { useForm, Controller} from "react-hook-form";
import Select from 'react-select'
import { createTeam } from "../api/teamApi";
import { assignTeamMemberToTeam } from "../api/adminApi";
export default function CreateTeamForm({users}){
const {handleSubmit, register, control} = useForm();
async function onSumbit(data){
try {
const teamLead = data.teamMembers.shift();
const responseToCreateTeam = await createTeam(teamLead.value, data.teamName)
if(data.teamMembers.length >0){
data.teamMembers.map( async (teamMember)=>{
const responseToAddToTeam = assignTeamMemberToTeam(teamMember.value, responseToCreateTeam.teamId)
})
}
await alert("Team Created with id"+ responseToCreateTeam.teamId)
window.location.href="/home";
} catch (error) {
console.log(error)
}
}
const customStyles = {
control: (provided) => ({
...provided,
width: '65vw',
minWidth: '100px',
maxWidth: '100%',
minHeight: '30px',
maxHeight: '100%',
border: '2px solid grey',
borderRadius: '10px',
paddingLeft: '8px',
backgroundColor: '#BFCDE0',
margin: '10px 0px',
}),
};
return(
<form id="createAccountForm" onSubmit={handleSubmit(onSumbit)}>
<label>Team Name</label>
<input type="text" {...register("teamName", {required:true})}/>
<label>Team Members (One Required, First Selected Will Be Team Lead)</label>
<Controller
control={control}
defaultValue={[]}
className='Select'
id = 'selectTeamMembers'
name="teamMembers"
rules={{required:true}}
render={({field}) => (
<Select
{...field}
options={users}
isMulti
styles={customStyles}

/>)}
/>
<button type="submit">Create Team</button>
</form>
)
}
16 changes: 16 additions & 0 deletions frontend/react-app/src/components/DeleteTeamButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { deleteTeam } from "../api/teamApi"

export default function DeleteTeamButton({teamId}){
async function deleteThisTeam(){
try {
const response = deleteTeam(teamId)
await alert('Team Deleted')
window.location.href="/home";
} catch (error) {

}
}
return(
<button onClick={deleteThisTeam} className="importButton">Delete Team</button>
)
}
2 changes: 1 addition & 1 deletion frontend/react-app/src/components/SignOut.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ export default function SignOut(){
}
return(

<button onClick={clearCookies}>Sign Out</button>
<button className="importButton" onClick={clearCookies}>Sign Out</button>
)
}
11 changes: 5 additions & 6 deletions frontend/react-app/src/components/Teams.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import "../css/Teams.css"
import {Link} from 'react-router-dom'

//team buttons (don't have onclick functionality yet)
function Teams({team}){
return(
<div className="teams">
<button className="team-btn">
<div className="team-info">
<h1>{team.id}</h1>
<h1>{team.name}</h1>
</div>
</button>
<Link className="teamButton headerText1" to='/team-tasks' state={{ teamId: team.teamId}} key={team.teamId} >
{team.teamName}
</Link>

</div>
);
}
Expand Down
8 changes: 4 additions & 4 deletions frontend/react-app/src/components/UserInfo.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import "../css/Profile.css"
import logo from '../logo.svg';

//user information used in the profile page
function UserInfo(){
function UserInfo({userInfo}){

//mock data
const user = {
Expand All @@ -18,9 +18,9 @@ function UserInfo(){
<img src={user.profilePictureUrl} alt="Profile Picture" />
</div>
<div className="profile-info">
<h1 className="profile-name">{user.name}</h1>
<p className="profile-username">{user.username}</p>
<h3 className="profile-email">{user.email}</h3>
<h1 className="profile-name">{userInfo.accountId}</h1>
<p className="profile-username">{userInfo.userName}</p>
<h3 className="profile-email">{userInfo.userEmail}</h3>
</div>
</div>
);
Expand Down
1 change: 1 addition & 0 deletions frontend/react-app/src/pages/AdminPanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export default function AdminPanel(){
<div className="rowFlexbox buttonRow">
<a href="create-account" ><button className='importButton'>Create New Account</button></a>
<a href="/all-users"><button className="importButton">See/Edit All Users</button></a>
<a href="/create-team"><button className="importButton">Create Team</button></a>
</div>
<form onSubmit={handleSubmit(onSubmit)} className="goToTeamTaskForm">
<select name="" id="" {...register("teamId")}>
Expand Down
47 changes: 47 additions & 0 deletions frontend/react-app/src/pages/CreateTeamPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React, { useEffect, useState } from 'react';
import '../css/CreateAccount.css';
import Header from '../components/Header';
import CreateTeamForm from '../components/CreateTeamForm';
import { getTeamMembers } from '../api/teamMemberAccountApi';
import { getAdmins } from '../api/adminApi';

export default function CreatTeamPage(){
const [loading, setLoading]= useState(true);
const [allUsers, setTeamMemberData] = useState([]);

function FormatUserData(users){
let returnArr =[]
users.map((user)=>{
returnArr = [...returnArr, {value: user.accountId, label: user.userName, name: user.userName}]
})
return returnArr
}

useEffect(()=>{
async function getAllUsers(){
try {
const teamMembers = await getTeamMembers();
const admins = await getAdmins();
setTeamMemberData(()=>teamMembers.concat(admins))
} catch (error) {
console.log(error)
}finally{
setLoading(false)
}
}
getAllUsers();
},[])
if(loading){
return (<div>...Loading</div>)
}
return (
<div className='pageContainer'>
<Header/>
<div className='pageBody'>
<CreateTeamForm
users = {FormatUserData(allUsers)}
/>
</div>
</div>
)
}
39 changes: 31 additions & 8 deletions frontend/react-app/src/pages/Profile.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,51 @@ import UserInfo from "../components/UserInfo"
import Teams from "../components/Teams"
import SignOut from '../components/SignOut'
import Header from "../components/Header";
import { useCookies } from "react-cookie";
import { useEffect, useState } from "react";
import {getTeamMemberById} from '../api/teamMemberAccountApi'
import { getTeamsForMember } from "../api/teamMemberApi";

function Profile(){
const [cookies] = useCookies(['userInfo']);
const [userData, setUserData] = useState();
const [teams, setTeams] = useState();
const [loading, setLoading] = useState(true);
//mock data
const teams = [
{id: 1, name: "The Alphas"},
{id: 2, name: "The Nerds"},
{id: 3, name: "C++ +"},
];

useEffect(()=>{
async function getUserInfo(){
try {
const user = await getTeamMemberById(cookies.userInfo.accountId)
const usersTeams = await getTeamsForMember(cookies.userInfo.accountId)
setUserData(user)
setTeams(usersTeams)
} catch (error) {

}finally{
setLoading(false)
}
}
getUserInfo();
},[])
if(loading){
return (<div>...Loading</div>)
}
console.log(userData)
return (
<div className='pageContainer'>
<Header/>
<div className='pageBody'>
<UserInfo />
<UserInfo
userInfo = {userData}/>
<h1>My teams</h1>
<div className="teams-grid">
{teams.map((team) => (
<Teams team={team} key={team.id}/>
<Teams team={team} key={team.teamId}/>
))}
</div>
<div>
<a href="/change-password"><button>Change Password</button></a>
<a href="/change-password"><button className="importButton">Change Password</button></a>
</div>
<SignOut/>
</div>
Expand Down
8 changes: 8 additions & 0 deletions frontend/react-app/src/pages/TeamTasks.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useState, useEffect } from 'react';
import { getTeamMembers } from "../api/teamApi";
import { useLocation } from 'react-router-dom';
import { getTeamTasks } from "../api/teamApi";
import DeleteTeamButton from "../components/DeleteTeamButton";

function getAssigneesNames(taskItem) {
return taskItem.assignedMembers.map((member) => member.userName).join(", ");
Expand Down Expand Up @@ -200,6 +201,13 @@ if(loadingNames || loadingTasks){
<TeamMember key={member.teamId} member={member} isAdminPage={isAdmin}/>
))}
</div>
{cookies.userInfo.role === 'admin'&&
(
<DeleteTeamButton
teamId={teamId}
/>
)
}



Expand Down
Loading