diff --git a/frontend/src/API/API.ts b/frontend/src/API/API.ts index d330f6d..67768c2 100644 --- a/frontend/src/API/API.ts +++ b/frontend/src/API/API.ts @@ -1004,8 +1004,8 @@ export const api: API = { } }, async getStatistics( - token: string, projectName: string, + token: string, userName?: string, ): Promise> { try { diff --git a/frontend/src/Components/AllTimeReportsInProject.tsx b/frontend/src/Components/AllTimeReportsInProject.tsx index 0d5916b..aef1df1 100644 --- a/frontend/src/Components/AllTimeReportsInProject.tsx +++ b/frontend/src/Components/AllTimeReportsInProject.tsx @@ -37,9 +37,9 @@ function AllTimeReportsInProject(): JSX.Element {
{weeklyReports.map((newWeeklyReport, index) => (

diff --git a/frontend/src/Components/AllTimeReportsInProjectOtherUser.tsx b/frontend/src/Components/AllTimeReportsInProjectOtherUser.tsx index 4218f0a..a96c55b 100644 --- a/frontend/src/Components/AllTimeReportsInProjectOtherUser.tsx +++ b/frontend/src/Components/AllTimeReportsInProjectOtherUser.tsx @@ -39,9 +39,9 @@ function AllTimeReportsInProject(): JSX.Element {
{weeklyReports.map((newWeeklyReport, index) => (

diff --git a/frontend/src/Components/DisplayUnsignedReports.tsx b/frontend/src/Components/DisplayUnsignedReports.tsx index 25a1da3..3cd32f8 100644 --- a/frontend/src/Components/DisplayUnsignedReports.tsx +++ b/frontend/src/Components/DisplayUnsignedReports.tsx @@ -65,7 +65,7 @@ function DisplayUserProject(): JSX.Element { -

+

View Report

diff --git a/frontend/src/Components/DisplayUserProjects.tsx b/frontend/src/Components/DisplayUserProjects.tsx index 65bd4f5..551e809 100644 --- a/frontend/src/Components/DisplayUserProjects.tsx +++ b/frontend/src/Components/DisplayUserProjects.tsx @@ -45,7 +45,7 @@ function DisplayUserProject(): JSX.Element { onClick={() => void handleProjectClick(project.name)} key={project.id} > -

+

{project.name}

diff --git a/frontend/src/Components/EditWeeklyReport.tsx b/frontend/src/Components/EditWeeklyReport.tsx index d56ee42..5037a76 100644 --- a/frontend/src/Components/EditWeeklyReport.tsx +++ b/frontend/src/Components/EditWeeklyReport.tsx @@ -18,12 +18,13 @@ export default function GetWeeklyReport(): JSX.Element { const [testingTime, setTestingTime] = useState(0); const token = localStorage.getItem("accessToken") ?? ""; - const { projectName, fetchedWeek } = useParams<{ + const { projectName, fetchedWeek, signedOrUnsigned } = useParams<{ projectName: string; fetchedWeek: string; + signedOrUnsigned: string; }>(); const username = localStorage.getItem("userName") ?? ""; - console.log(projectName, fetchedWeek); + console.log(projectName, fetchedWeek, signedOrUnsigned); useEffect(() => { const fetchWeeklyReport = async (): Promise => { @@ -59,7 +60,7 @@ export default function GetWeeklyReport(): JSX.Element { }; void fetchWeeklyReport(); - }, [projectName, fetchedWeek, token]); + }, [projectName, fetchedWeek, signedOrUnsigned, token]); const handleUpdateWeeklyReport = async (): Promise => { const updateWeeklyReport: UpdateWeeklyReport = { @@ -139,6 +140,12 @@ export default function GetWeeklyReport(): JSX.Element { ) event.preventDefault(); }} + onClick={() => { + if (signedOrUnsigned === "signed") { + alert("You cannot edit a signed report."); + } + }} + readOnly={signedOrUnsigned === "signed"} /> @@ -168,6 +175,12 @@ export default function GetWeeklyReport(): JSX.Element { ) event.preventDefault(); }} + onClick={() => { + if (signedOrUnsigned === "signed") { + alert("You cannot edit a signed report."); + } + }} + readOnly={signedOrUnsigned === "signed"} /> @@ -197,6 +210,12 @@ export default function GetWeeklyReport(): JSX.Element { ) event.preventDefault(); }} + onClick={() => { + if (signedOrUnsigned === "signed") { + alert("You cannot edit a signed report."); + } + }} + readOnly={signedOrUnsigned === "signed"} /> @@ -226,6 +245,12 @@ export default function GetWeeklyReport(): JSX.Element { ) event.preventDefault(); }} + onClick={() => { + if (signedOrUnsigned === "signed") { + alert("You cannot edit a signed report."); + } + }} + readOnly={signedOrUnsigned === "signed"} /> @@ -255,6 +280,12 @@ export default function GetWeeklyReport(): JSX.Element { ) event.preventDefault(); }} + onClick={() => { + if (signedOrUnsigned === "signed") { + alert("You cannot edit a signed report."); + } + }} + readOnly={signedOrUnsigned === "signed"} /> @@ -284,18 +315,26 @@ export default function GetWeeklyReport(): JSX.Element { ) event.preventDefault(); }} + onClick={() => { + if (signedOrUnsigned === "signed") { + alert("You cannot edit a signed report."); + } + }} + readOnly={signedOrUnsigned === "signed"} /> -

diff --git a/frontend/src/Components/OtherUsersTR.tsx b/frontend/src/Components/OtherUsersTR.tsx index ce7761c..40e0b94 100644 --- a/frontend/src/Components/OtherUsersTR.tsx +++ b/frontend/src/Components/OtherUsersTR.tsx @@ -1,7 +1,8 @@ import { useState, useEffect } from "react"; import { WeeklyReport } from "../Types/goTypes"; import { api } from "../API/API"; -import { useParams } from "react-router-dom"; +import { useParams, useNavigate } from "react-router-dom"; +import Button from "./Button"; /** * Renders the component for editing a weekly report. @@ -17,11 +18,14 @@ export default function OtherUsersTR(): JSX.Element { const [ownWorkTime, setOwnWorkTime] = useState(0); const [studyTime, setStudyTime] = useState(0); const [testingTime, setTestingTime] = useState(0); + const [reportId, setReportId] = useState(0); const token = localStorage.getItem("accessToken") ?? ""; const { projectName } = useParams(); const { username } = useParams(); const { fetchedWeek } = useParams(); + const { signedOrUnsigned } = useParams(); + console.log(projectName, username, fetchedWeek, signedOrUnsigned); useEffect(() => { const fetchUsersWeeklyReport = async (): Promise => { @@ -45,6 +49,7 @@ export default function OtherUsersTR(): JSX.Element { studyTime: 0, testingTime: 0, }; + setReportId(report.reportId); setWeek(report.week); setDevelopmentTime(report.developmentTime); setMeetingTime(report.meetingTime); @@ -60,6 +65,27 @@ export default function OtherUsersTR(): JSX.Element { void fetchUsersWeeklyReport(); }); + const handleUnsignWeeklyReport = async (): Promise => { + const response = await api.unsignReport(reportId, token); + console.log(response); + console.log(reportId); + if (response.success) { + return true; + } else { + return false; + } + }; + + const handleDeleteWeeklyReport = async (): Promise => { + const response = await api.deleteWeeklyReport(reportId, token); + console.log(response); + if (response.success) { + return true; + } + return false; + }; + const navigate = useNavigate(); + return ( <>

{username}'s Report

@@ -153,6 +179,48 @@ export default function OtherUsersTR(): JSX.Element { +
+ {signedOrUnsigned === "signed" && ( +
diff --git a/frontend/src/Components/PMProjectMenu.tsx b/frontend/src/Components/PMProjectMenu.tsx index ce7c5c5..f0cb492 100644 --- a/frontend/src/Components/PMProjectMenu.tsx +++ b/frontend/src/Components/PMProjectMenu.tsx @@ -8,22 +8,22 @@ function PMProjectMenu(): JSX.Element {

{projectName}

-

+

Your Time Reports

-

+

New Time Report

-

+

Statistics

-

+

Unsigned Time Reports

diff --git a/frontend/src/Components/ProjectMembers.tsx b/frontend/src/Components/ProjectMembers.tsx index 52e8559..e06ed75 100644 --- a/frontend/src/Components/ProjectMembers.tsx +++ b/frontend/src/Components/ProjectMembers.tsx @@ -1,6 +1,7 @@ import { useState } from "react"; import { Link, useParams } from "react-router-dom"; import GetUsersInProject, { ProjectMember } from "./GetUsersInProject"; +import { api } from "../API/API"; function ProjectMembers(): JSX.Element { const { projectName } = useParams(); @@ -11,34 +12,68 @@ function ProjectMembers(): JSX.Element { setUsersProp: setProjectMembers, }); + const handleUserDeleteClick = async (username: string): Promise => { + const token = localStorage.getItem("accessToken") ?? ""; + const response = await api.removeUserFromProject( + username, + projectName ?? "", + token, + ); + console.log(response.data); + + // Remove the deleted user from the state + setProjectMembers((prevMembers) => + prevMembers.filter((member) => member.Username !== username), + ); + }; + return ( <>

All Members In: {projectName}{" "}

- {projectMembers.map((projectMember: ProjectMember, index: number) => ( -

-
-
-

{projectMember.Username}

- Role: -

{projectMember.UserRole}

-
-
-
- -

- View Reports -

- + {projectMembers.map((projectMember: ProjectMember, index: number) => { + if (projectMember.Username === "admin") { + return null; // Skip rendering for admin user + } + return ( +

+
+
+

{projectMember.Username}

+ Role: +

{projectMember.UserRole}

+
+
+
+ {projectMember.Username !== + localStorage.getItem("username") && ( +

{ + confirm( + "Are you sure you want to delete this user? This action cannot be undone.", + ) && + void handleUserDeleteClick(projectMember.Username); + }} + > + Delete User +

+ )} + +

+ View Reports +

+ +
-

-

- ))} + + ); + })}
); diff --git a/frontend/src/Components/TimePerActivity.tsx b/frontend/src/Components/TimePerActivity.tsx index c5e4a9f..0963e88 100644 --- a/frontend/src/Components/TimePerActivity.tsx +++ b/frontend/src/Components/TimePerActivity.tsx @@ -14,6 +14,7 @@ export default function TimePerRole(): JSX.Element { const [own_work, setOwnWork] = useState(0); const [study, setStudy] = useState(0); const [testing, setTesting] = useState(0); + const total = development + meeting + admin + own_work + study + testing; const token = localStorage.getItem("accessToken") ?? ""; const { projectName } = useParams(); @@ -49,7 +50,7 @@ export default function TimePerRole(): JSX.Element { return ( <>

- Total Time Per Activity In: {projectName}{" "} + Total Time Per Activity For All Members In: {projectName}{" "}

@@ -129,6 +130,12 @@ export default function TimePerRole(): JSX.Element { /> + + In Total: + +

{total}

+ +
diff --git a/frontend/src/Components/UserProjectMenu.tsx b/frontend/src/Components/UserProjectMenu.tsx index e307e90..4be4dee 100644 --- a/frontend/src/Components/UserProjectMenu.tsx +++ b/frontend/src/Components/UserProjectMenu.tsx @@ -16,12 +16,12 @@ function UserProjectMenu(): JSX.Element {

{projectName}

-

+

Your Time Reports

-

+

New Time Report

diff --git a/frontend/src/Components/UserStatistics.tsx b/frontend/src/Components/UserStatistics.tsx new file mode 100644 index 0000000..c84f1a0 --- /dev/null +++ b/frontend/src/Components/UserStatistics.tsx @@ -0,0 +1,150 @@ +import { useState, useEffect } from "react"; +import { useParams } from "react-router-dom"; +import { api } from "../API/API"; +import { Statistics } from "../Types/goTypes"; + +/** + * Renders the component for showing total time per role in a project. + * @returns JSX.Element + */ +export default function UserStatistics(): JSX.Element { + const [development, setDevelopment] = useState(0); + const [meeting, setMeeting] = useState(0); + const [admin, setAdmin] = useState(0); + const [own_work, setOwnWork] = useState(0); + const [study, setStudy] = useState(0); + const [testing, setTesting] = useState(0); + const total = development + meeting + admin + own_work + study + testing; + + const token = localStorage.getItem("accessToken") ?? ""; + const { projectName } = useParams(); + const { username } = useParams(); + + const fetchTimePerActivity = async (): Promise => { + const response = await api.getStatistics( + projectName ?? "", + token, + username ?? "", + ); + { + if (response.success) { + const statistics: Statistics = response.data ?? { + totalDevelopmentTime: 0, + totalMeetingTime: 0, + totalAdminTime: 0, + totalOwnWorkTime: 0, + totalStudyTime: 0, + totalTestingTime: 0, + }; + setDevelopment(statistics.totalDevelopmentTime); + setMeeting(statistics.totalMeetingTime); + setAdmin(statistics.totalAdminTime); + setOwnWork(statistics.totalOwnWorkTime); + setStudy(statistics.totalStudyTime); + setTesting(statistics.totalTestingTime); + } else { + console.error("Failed to fetch weekly report:", response.message); + } + } + }; + + useEffect(() => { + void fetchTimePerActivity(); + }); + + return ( + <> +

+ Total Time In: {projectName}{" "} +

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Activity + Total Time (min) +
Development + +
Meeting + +
Administration + +
Own Work + +
Studies + +
Testing + +
In Total: +

{total}

+
+
+
+ + ); +} diff --git a/frontend/src/Pages/ProjectManagerPages/PMOtherUsersTR.tsx b/frontend/src/Pages/ProjectManagerPages/PMOtherUsersTR.tsx index cb558b0..b586b64 100644 --- a/frontend/src/Pages/ProjectManagerPages/PMOtherUsersTR.tsx +++ b/frontend/src/Pages/ProjectManagerPages/PMOtherUsersTR.tsx @@ -1,8 +1,12 @@ import BasicWindow from "../../Components/BasicWindow"; import BackButton from "../../Components/BackButton"; import AllTimeReportsInProjectOtherUser from "../../Components/AllTimeReportsInProjectOtherUser"; +import Button from "../../Components/Button"; +import { useParams, Link } from "react-router-dom"; function PMOtherUsersTR(): JSX.Element { + const { projectName } = useParams(); + const { username } = useParams(); const content = ( <> @@ -11,6 +15,15 @@ function PMOtherUsersTR(): JSX.Element { const buttons = ( <> + +