Merge remote-tracking branch 'origin/gruppDM' into BumBranch
This commit is contained in:
commit
8d7d815745
20 changed files with 1194 additions and 228 deletions
|
@ -213,7 +213,7 @@ export const api: API = {
|
||||||
): Promise<APIResponse<boolean>> {
|
): Promise<APIResponse<boolean>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`/api/checkIfProjectManager?projectName=${projectName}`,
|
`/api/checkIfProjectManager/${projectName}`,
|
||||||
{
|
{
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
|
|
103
frontend/src/Components/AllTimeReportsInProjectOtherUser.tsx
Normal file
103
frontend/src/Components/AllTimeReportsInProjectOtherUser.tsx
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
//Info: This component is used to display all the time reports for a project. It will display the week number,
|
||||||
|
//total time spent, and if the report has been signed or not. The user can click on a report to edit it.
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { NewWeeklyReport } from "../Types/goTypes";
|
||||||
|
import { Link, useParams } from "react-router-dom";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a component that displays all the time reports for a specific project.
|
||||||
|
* @returns {JSX.Element} representing the component.
|
||||||
|
*/
|
||||||
|
function AllTimeReportsInProject(): JSX.Element {
|
||||||
|
const { username } = useParams();
|
||||||
|
const { projectName } = useParams();
|
||||||
|
const [weeklyReports, setWeeklyReports] = useState<NewWeeklyReport[]>([]);
|
||||||
|
|
||||||
|
/* // Call getProjects when the component mounts
|
||||||
|
useEffect(() => {
|
||||||
|
const getWeeklyReports = async (): Promise<void> => {
|
||||||
|
const token = localStorage.getItem("accessToken") ?? "";
|
||||||
|
const response = await api.getWeeklyReportsForUser(
|
||||||
|
projectName ?? "",
|
||||||
|
token,
|
||||||
|
);
|
||||||
|
console.log(response);
|
||||||
|
if (response.success) {
|
||||||
|
setWeeklyReports(response.data ?? []);
|
||||||
|
} else {
|
||||||
|
console.error(response.message);
|
||||||
|
}
|
||||||
|
}; */
|
||||||
|
// Mock data
|
||||||
|
const getWeeklyReports = async (): Promise<void> => {
|
||||||
|
// Simulate a delay
|
||||||
|
await Promise.resolve();
|
||||||
|
const mockWeeklyReports: NewWeeklyReport[] = [
|
||||||
|
{
|
||||||
|
projectName: "Project 1",
|
||||||
|
week: 1,
|
||||||
|
developmentTime: 10,
|
||||||
|
meetingTime: 2,
|
||||||
|
adminTime: 1,
|
||||||
|
ownWorkTime: 3,
|
||||||
|
studyTime: 4,
|
||||||
|
testingTime: 5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
projectName: "Project 1",
|
||||||
|
week: 2,
|
||||||
|
developmentTime: 8,
|
||||||
|
meetingTime: 2,
|
||||||
|
adminTime: 1,
|
||||||
|
ownWorkTime: 3,
|
||||||
|
studyTime: 4,
|
||||||
|
testingTime: 5,
|
||||||
|
},
|
||||||
|
// Add more reports as needed
|
||||||
|
];
|
||||||
|
|
||||||
|
// Use the mock data instead of the real data
|
||||||
|
setWeeklyReports(mockWeeklyReports);
|
||||||
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
void getWeeklyReports();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h1 className="text-[30px] font-bold">{username}'s Time Reports</h1>
|
||||||
|
<div className="border-4 border-black bg-white flex flex-col items-center justify-center min-h-[65vh] h-fit w-[50vw] rounded-3xl content-center overflow-scroll space-y-[10vh] p-[30px] text-[30px]">
|
||||||
|
{weeklyReports.map((newWeeklyReport, index) => (
|
||||||
|
<Link
|
||||||
|
to={`/editOthersTR/${projectName}/${username}/${newWeeklyReport.week}`}
|
||||||
|
key={index}
|
||||||
|
className="border-b-2 border-black w-full"
|
||||||
|
>
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<h1>
|
||||||
|
<span className="font-bold">{"Week: "}</span>
|
||||||
|
{newWeeklyReport.week}
|
||||||
|
</h1>
|
||||||
|
<h1>
|
||||||
|
<span className="font-bold">{"Total Time: "}</span>
|
||||||
|
{newWeeklyReport.developmentTime +
|
||||||
|
newWeeklyReport.meetingTime +
|
||||||
|
newWeeklyReport.adminTime +
|
||||||
|
newWeeklyReport.ownWorkTime +
|
||||||
|
newWeeklyReport.studyTime +
|
||||||
|
newWeeklyReport.testingTime}{" "}
|
||||||
|
min
|
||||||
|
</h1>
|
||||||
|
<h1>
|
||||||
|
<span className="font-bold">{"Signed: "}</span>
|
||||||
|
NO
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AllTimeReportsInProject;
|
129
frontend/src/Components/DisplayUnsignedReports.tsx
Normal file
129
frontend/src/Components/DisplayUnsignedReports.tsx
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import { Link, useParams } from "react-router-dom";
|
||||||
|
|
||||||
|
interface UnsignedReports {
|
||||||
|
projectName: string;
|
||||||
|
username: string;
|
||||||
|
week: number;
|
||||||
|
signed: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a component that displays the projects a user is a part of and links to the projects start-page.
|
||||||
|
* @returns The JSX element representing the component.
|
||||||
|
*/
|
||||||
|
function DisplayUserProject(): JSX.Element {
|
||||||
|
const { projectName } = useParams();
|
||||||
|
const [unsignedReports, setUnsignedReports] = useState<UnsignedReports[]>([]);
|
||||||
|
//const navigate = useNavigate();
|
||||||
|
|
||||||
|
// const getUnsignedReports = async (): Promise<void> => {
|
||||||
|
// const token = localStorage.getItem("accessToken") ?? "";
|
||||||
|
// const response = await api.getUserProjects(token);
|
||||||
|
// console.log(response);
|
||||||
|
// if (response.success) {
|
||||||
|
// setUnsignedReports(response.data ?? []);
|
||||||
|
// } else {
|
||||||
|
// console.error(response.message);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// const handleReportClick = async (projectName: string): Promise<void> => {
|
||||||
|
// const username = localStorage.getItem("username") ?? "";
|
||||||
|
// const token = localStorage.getItem("accessToken") ?? "";
|
||||||
|
// const response = await api.checkIfProjectManager(
|
||||||
|
// username,
|
||||||
|
// projectName,
|
||||||
|
// token,
|
||||||
|
// );
|
||||||
|
// if (response.success) {
|
||||||
|
// if (response.data) {
|
||||||
|
// navigate(`/PMProjectPage/${projectName}`);
|
||||||
|
// } else {
|
||||||
|
// navigate(`/project/${projectName}`);
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// // handle error
|
||||||
|
// console.error(response.message);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
const getUnsignedReports = async (): Promise<void> => {
|
||||||
|
// Simulate a delay
|
||||||
|
await Promise.resolve();
|
||||||
|
|
||||||
|
// Use mock data
|
||||||
|
const reports: UnsignedReports[] = [
|
||||||
|
{
|
||||||
|
projectName: "projecttest",
|
||||||
|
username: "user1",
|
||||||
|
week: 2,
|
||||||
|
signed: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
projectName: "projecttest",
|
||||||
|
username: "user2",
|
||||||
|
week: 2,
|
||||||
|
signed: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
projectName: "projecttest",
|
||||||
|
username: "user3",
|
||||||
|
week: 2,
|
||||||
|
signed: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
projectName: "projecttest",
|
||||||
|
username: "user4",
|
||||||
|
week: 2,
|
||||||
|
signed: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// Set the state with the mock data
|
||||||
|
setUnsignedReports(reports);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Call getProjects when the component mounts
|
||||||
|
useEffect(() => {
|
||||||
|
void getUnsignedReports();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h1 className="font-bold text-[30px] mb-[20px]">
|
||||||
|
All Unsigned Reports In: {projectName}{" "}
|
||||||
|
</h1>
|
||||||
|
<div className="border-4 border-black bg-white flex flex-col items-center justify-center min-h-[65vh] h-fit w-[70vw] rounded-3xl content-center overflow-scroll space-y-[10vh] p-[30px] text-[20px]">
|
||||||
|
{unsignedReports.map(
|
||||||
|
(unsignedReport: UnsignedReports, index: number) => (
|
||||||
|
<h1 key={index} className="border-b-2 border-black w-full">
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<div className="flex">
|
||||||
|
<h1>{unsignedReport.username}</h1>
|
||||||
|
<span className="ml-6 mr-2 font-bold">Week:</span>
|
||||||
|
<h1>{unsignedReport.week}</h1>
|
||||||
|
<span className="ml-6 mr-2 font-bold">Signed:</span>
|
||||||
|
<h1>NO</h1>
|
||||||
|
</div>
|
||||||
|
<div className="flex">
|
||||||
|
<div className="ml-auto flex space-x-4">
|
||||||
|
<Link
|
||||||
|
to={`/PMViewUnsignedReport/${projectName}/${unsignedReport.username}/${unsignedReport.week}`}
|
||||||
|
>
|
||||||
|
<h1 className="underline cursor-pointer font-bold">
|
||||||
|
View Report
|
||||||
|
</h1>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</h1>
|
||||||
|
),
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DisplayUserProject;
|
|
@ -1,6 +1,6 @@
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { Project } from "../Types/goTypes";
|
import { Project } from "../Types/goTypes";
|
||||||
import { Link } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { api } from "../API/API";
|
import { api } from "../API/API";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9,6 +9,7 @@ import { api } from "../API/API";
|
||||||
*/
|
*/
|
||||||
function DisplayUserProject(): JSX.Element {
|
function DisplayUserProject(): JSX.Element {
|
||||||
const [projects, setProjects] = useState<Project[]>([]);
|
const [projects, setProjects] = useState<Project[]>([]);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const getProjects = async (): Promise<void> => {
|
const getProjects = async (): Promise<void> => {
|
||||||
const token = localStorage.getItem("accessToken") ?? "";
|
const token = localStorage.getItem("accessToken") ?? "";
|
||||||
|
@ -21,6 +22,21 @@ function DisplayUserProject(): JSX.Element {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleProjectClick = async (projectName: string): Promise<void> => {
|
||||||
|
const token = localStorage.getItem("accessToken") ?? "";
|
||||||
|
const response = await api.checkIfProjectManager(projectName, token);
|
||||||
|
if (response.success) {
|
||||||
|
if (response.data) {
|
||||||
|
navigate(`/PMProjectPage/${projectName}`);
|
||||||
|
} else {
|
||||||
|
navigate(`/project/${projectName}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// handle error
|
||||||
|
console.error(response.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Call getProjects when the component mounts
|
// Call getProjects when the component mounts
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
void getProjects();
|
void getProjects();
|
||||||
|
@ -30,12 +46,15 @@ function DisplayUserProject(): JSX.Element {
|
||||||
<>
|
<>
|
||||||
<h1 className="font-bold text-[30px] mb-[20px]">Your Projects</h1>
|
<h1 className="font-bold text-[30px] mb-[20px]">Your Projects</h1>
|
||||||
<div className="border-4 border-black bg-white flex flex-col items-center justify-center min-h-[65vh] h-fit w-[50vw] rounded-3xl content-center overflow-scroll space-y-[10vh] p-[30px]">
|
<div className="border-4 border-black bg-white flex flex-col items-center justify-center min-h-[65vh] h-fit w-[50vw] rounded-3xl content-center overflow-scroll space-y-[10vh] p-[30px]">
|
||||||
{projects.map((project, index) => (
|
{projects.map((project) => (
|
||||||
<Link to={`/project/${project.name}`} key={index}>
|
<div
|
||||||
|
onClick={() => void handleProjectClick(project.name)}
|
||||||
|
key={project.id}
|
||||||
|
>
|
||||||
<h1 className="font-bold underline text-[30px] cursor-pointer">
|
<h1 className="font-bold underline text-[30px] cursor-pointer">
|
||||||
{project.name}
|
{project.name}
|
||||||
</h1>
|
</h1>
|
||||||
</Link>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -18,13 +18,17 @@ export default function GetWeeklyReport(): JSX.Element {
|
||||||
const [testingTime, setTestingTime] = useState(0);
|
const [testingTime, setTestingTime] = useState(0);
|
||||||
|
|
||||||
const token = localStorage.getItem("accessToken") ?? "";
|
const token = localStorage.getItem("accessToken") ?? "";
|
||||||
const { projectName } = useParams();
|
const { projectName, fetchedWeek } = useParams<{
|
||||||
const { fetchedWeek } = useParams();
|
projectName: string;
|
||||||
|
fetchedWeek: string;
|
||||||
|
}>();
|
||||||
|
console.log(projectName, fetchedWeek);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
const fetchWeeklyReport = async (): Promise<void> => {
|
const fetchWeeklyReport = async (): Promise<void> => {
|
||||||
const response = await api.getWeeklyReport(
|
const response = await api.getWeeklyReport(
|
||||||
projectName ?? "",
|
projectName ?? "",
|
||||||
fetchedWeek?.toString() ?? "0",
|
fetchedWeek ?? "",
|
||||||
token,
|
token,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -53,9 +57,8 @@ export default function GetWeeklyReport(): JSX.Element {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
void fetchWeeklyReport();
|
void fetchWeeklyReport();
|
||||||
});
|
}, [projectName, fetchedWeek, token]);
|
||||||
|
|
||||||
const handleNewWeeklyReport = async (): Promise<void> => {
|
const handleNewWeeklyReport = async (): Promise<void> => {
|
||||||
const newWeeklyReport: NewWeeklyReport = {
|
const newWeeklyReport: NewWeeklyReport = {
|
||||||
|
@ -76,6 +79,7 @@ export default function GetWeeklyReport(): JSX.Element {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<h1 className="font-bold text-[30px] mb-[20px]">Edit Time Report</h1>
|
||||||
<div className="border-4 border-black bg-white flex flex-col justify-start min-h-[65vh] h-fit w-[50vw] rounded-3xl overflow-scroll space-y-[2vh] p-[30px] items-center">
|
<div className="border-4 border-black bg-white flex flex-col justify-start min-h-[65vh] h-fit w-[50vw] rounded-3xl overflow-scroll space-y-[2vh] p-[30px] items-center">
|
||||||
<form
|
<form
|
||||||
onSubmit={(e) => {
|
onSubmit={(e) => {
|
||||||
|
@ -90,24 +94,10 @@ export default function GetWeeklyReport(): JSX.Element {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex flex-col items-center">
|
<div className="flex flex-col items-center">
|
||||||
<input
|
<div className="flex flex-col w-1/2 border-b-2 border-black items-center justify-center">
|
||||||
className="w-fill h-[5vh] font-sans text-[3vh] pl-[1vw] rounded-full text-center pt-[1vh] pb-[1vh] border-2 border-black"
|
<h1 className="font-bold text-[30px]"> Week: {week}</h1>
|
||||||
type="week"
|
</div>
|
||||||
placeholder="Week"
|
|
||||||
value={
|
|
||||||
week === 0 ? "" : `2024-W${week.toString().padStart(2, "0")}`
|
|
||||||
}
|
|
||||||
onChange={(e) => {
|
|
||||||
const weekNumber = parseInt(e.target.value.split("-W")[1]);
|
|
||||||
setWeek(weekNumber);
|
|
||||||
}}
|
|
||||||
onKeyDown={(event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
}}
|
|
||||||
onPaste={(event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<table className="w-full text-center divide-y divide-x divide-white text-[30px]">
|
<table className="w-full text-center divide-y divide-x divide-white text-[30px]">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -127,9 +117,14 @@ export default function GetWeeklyReport(): JSX.Element {
|
||||||
type="number"
|
type="number"
|
||||||
min="0"
|
min="0"
|
||||||
className="border-2 border-black rounded-md text-center w-1/2"
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
value={developmentTime}
|
value={developmentTime === 0 ? "" : developmentTime}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
if (e.target.value === "") {
|
||||||
|
setDevelopmentTime(0);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
setDevelopmentTime(parseInt(e.target.value));
|
setDevelopmentTime(parseInt(e.target.value));
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
const keyValue = event.key;
|
const keyValue = event.key;
|
||||||
|
@ -146,9 +141,14 @@ export default function GetWeeklyReport(): JSX.Element {
|
||||||
type="number"
|
type="number"
|
||||||
min="0"
|
min="0"
|
||||||
className="border-2 border-black rounded-md text-center w-1/2"
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
value={meetingTime}
|
value={meetingTime === 0 ? "" : meetingTime}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
if (e.target.value === "") {
|
||||||
|
setMeetingTime(0);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
setMeetingTime(parseInt(e.target.value));
|
setMeetingTime(parseInt(e.target.value));
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
const keyValue = event.key;
|
const keyValue = event.key;
|
||||||
|
@ -165,9 +165,14 @@ export default function GetWeeklyReport(): JSX.Element {
|
||||||
type="number"
|
type="number"
|
||||||
min="0"
|
min="0"
|
||||||
className="border-2 border-black rounded-md text-center w-1/2"
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
value={adminTime}
|
value={adminTime === 0 ? "" : adminTime}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
if (e.target.value === "") {
|
||||||
|
setAdminTime(0);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
setAdminTime(parseInt(e.target.value));
|
setAdminTime(parseInt(e.target.value));
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
const keyValue = event.key;
|
const keyValue = event.key;
|
||||||
|
@ -184,9 +189,14 @@ export default function GetWeeklyReport(): JSX.Element {
|
||||||
type="number"
|
type="number"
|
||||||
min="0"
|
min="0"
|
||||||
className="border-2 border-black rounded-md text-center w-1/2"
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
value={ownWorkTime}
|
value={ownWorkTime === 0 ? "" : ownWorkTime}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
if (e.target.value === "") {
|
||||||
|
setOwnWorkTime(0);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
setOwnWorkTime(parseInt(e.target.value));
|
setOwnWorkTime(parseInt(e.target.value));
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
const keyValue = event.key;
|
const keyValue = event.key;
|
||||||
|
@ -203,9 +213,14 @@ export default function GetWeeklyReport(): JSX.Element {
|
||||||
type="number"
|
type="number"
|
||||||
min="0"
|
min="0"
|
||||||
className="border-2 border-black rounded-md text-center w-1/2"
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
value={studyTime}
|
value={studyTime === 0 ? "" : studyTime}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
if (e.target.value === "") {
|
||||||
|
setStudyTime(0);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
setStudyTime(parseInt(e.target.value));
|
setStudyTime(parseInt(e.target.value));
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
const keyValue = event.key;
|
const keyValue = event.key;
|
||||||
|
@ -222,9 +237,14 @@ export default function GetWeeklyReport(): JSX.Element {
|
||||||
type="number"
|
type="number"
|
||||||
min="0"
|
min="0"
|
||||||
className="border-2 border-black rounded-md text-center w-1/2"
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
value={testingTime}
|
value={testingTime === 0 ? "" : testingTime}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
if (e.target.value === "") {
|
||||||
|
setTestingTime(0);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
setTestingTime(parseInt(e.target.value));
|
setTestingTime(parseInt(e.target.value));
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
const keyValue = event.key;
|
const keyValue = event.key;
|
||||||
|
|
|
@ -12,55 +12,74 @@ import Button from "./Button";
|
||||||
*/
|
*/
|
||||||
export default function NewWeeklyReport(): JSX.Element {
|
export default function NewWeeklyReport(): JSX.Element {
|
||||||
const [week, setWeek] = useState<number>(0);
|
const [week, setWeek] = useState<number>(0);
|
||||||
const [developmentTime, setDevelopmentTime] = useState<number>();
|
const [developmentTime, setDevelopmentTime] = useState<number>(0);
|
||||||
const [meetingTime, setMeetingTime] = useState<number>();
|
const [meetingTime, setMeetingTime] = useState<number>(0);
|
||||||
const [adminTime, setAdminTime] = useState<number>();
|
const [adminTime, setAdminTime] = useState<number>(0);
|
||||||
const [ownWorkTime, setOwnWorkTime] = useState<number>();
|
const [ownWorkTime, setOwnWorkTime] = useState<number>(0);
|
||||||
const [studyTime, setStudyTime] = useState<number>();
|
const [studyTime, setStudyTime] = useState<number>(0);
|
||||||
const [testingTime, setTestingTime] = useState<number>();
|
const [testingTime, setTestingTime] = useState<number>(0);
|
||||||
|
|
||||||
const { projectName } = useParams();
|
const { projectName } = useParams();
|
||||||
const token = localStorage.getItem("accessToken") ?? "";
|
const token = localStorage.getItem("accessToken") ?? "";
|
||||||
|
|
||||||
const handleNewWeeklyReport = async (): Promise<void> => {
|
const handleNewWeeklyReport = async (): Promise<boolean> => {
|
||||||
const newWeeklyReport: NewWeeklyReport = {
|
const newWeeklyReport: NewWeeklyReport = {
|
||||||
projectName: projectName ?? "",
|
projectName: projectName ?? "",
|
||||||
week: week,
|
week: week,
|
||||||
developmentTime: developmentTime ?? 0,
|
developmentTime: developmentTime,
|
||||||
meetingTime: meetingTime ?? 0,
|
meetingTime: meetingTime,
|
||||||
adminTime: adminTime ?? 0,
|
adminTime: adminTime,
|
||||||
ownWorkTime: ownWorkTime ?? 0,
|
ownWorkTime: ownWorkTime,
|
||||||
studyTime: studyTime ?? 0,
|
studyTime: studyTime,
|
||||||
testingTime: testingTime ?? 0,
|
testingTime: testingTime,
|
||||||
};
|
};
|
||||||
|
|
||||||
await api.submitWeeklyReport(newWeeklyReport, token);
|
const response = await api.submitWeeklyReport(newWeeklyReport, token);
|
||||||
|
console.log(response);
|
||||||
|
if (response.success) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
// Check if the browser is Chrome or Edge
|
||||||
|
const isChromeOrEdge = /Chrome|Edg/.test(navigator.userAgent);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="border-4 border-black bg-white flex flex-col justify-start min-h-[65vh] h-fit w-[50vw] rounded-3xl overflow-scroll space-y-[2vh] p-[30px] items-center">
|
<div className="border-4 border-black bg-white flex flex-col justify-start min-h-[65vh] h-fit w-[50vw] rounded-3xl overflow-scroll space-y-[2vh] p-[30px] items-center">
|
||||||
<form
|
<form
|
||||||
onSubmit={(e) => {
|
onSubmit={(e) => {
|
||||||
if (week === 0) {
|
|
||||||
alert("Please enter a week number");
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
void (async (): Promise<void> => {
|
||||||
|
if (week === 0 || week > 53 || week < 1) {
|
||||||
|
alert("Please enter a valid week number");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
e.preventDefault();
|
|
||||||
void handleNewWeeklyReport();
|
const success = await handleNewWeeklyReport();
|
||||||
|
if (!success) {
|
||||||
|
alert(
|
||||||
|
"A Time Report for this week already exists, please go to the edit page to edit it or change week number.",
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
alert("Weekly report submitted successfully");
|
||||||
navigate(-1);
|
navigate(-1);
|
||||||
|
})();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex flex-col items-center">
|
<div className="flex flex-col items-center">
|
||||||
|
{isChromeOrEdge ? (
|
||||||
<input
|
<input
|
||||||
className="w-fill h-[5vh] font-sans text-[3vh] pl-[1vw] rounded-full text-center pt-[1vh] pb-[1vh] border-2 border-black"
|
className="w-fill h-[5vh] font-sans text-[3vh] pl-[1vw] rounded-full text-center pt-[1vh] pb-[1vh] border-2 border-black"
|
||||||
type="week"
|
type="week"
|
||||||
placeholder="Week"
|
placeholder="Week"
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setWeek(parseInt(e.target.value));
|
const weekNumber = parseInt(e.target.value.split("-W")[1]);
|
||||||
|
setWeek(weekNumber);
|
||||||
}}
|
}}
|
||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
const keyValue = event.key;
|
const keyValue = event.key;
|
||||||
|
@ -71,6 +90,25 @@ export default function NewWeeklyReport(): JSX.Element {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
) : (
|
||||||
|
<input
|
||||||
|
className="w-fill h-[5vh] font-sans text-[3vh] pl-[1vw] rounded-full text-center pt-[1vh] pb-[1vh] border-2 border-black"
|
||||||
|
type="text"
|
||||||
|
placeholder="Week (Numbers Only)"
|
||||||
|
onChange={(e) => {
|
||||||
|
const weekNumber = parseInt(e.target.value);
|
||||||
|
setWeek(weekNumber);
|
||||||
|
}}
|
||||||
|
onKeyDown={(event) => {
|
||||||
|
const keyValue = event.key;
|
||||||
|
if (!/\d/.test(keyValue) && keyValue !== "Backspace")
|
||||||
|
event.preventDefault();
|
||||||
|
}}
|
||||||
|
onPaste={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<table className="w-full text-center divide-y divide-x divide-white text-[30px]">
|
<table className="w-full text-center divide-y divide-x divide-white text-[30px]">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -90,9 +128,14 @@ export default function NewWeeklyReport(): JSX.Element {
|
||||||
type="number"
|
type="number"
|
||||||
min="0"
|
min="0"
|
||||||
className="border-2 border-black rounded-md text-center w-1/2"
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
value={developmentTime}
|
value={developmentTime === 0 ? "" : developmentTime}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
if (e.target.value === "") {
|
||||||
|
setDevelopmentTime(0);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
setDevelopmentTime(parseInt(e.target.value));
|
setDevelopmentTime(parseInt(e.target.value));
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
const keyValue = event.key;
|
const keyValue = event.key;
|
||||||
|
@ -109,9 +152,14 @@ export default function NewWeeklyReport(): JSX.Element {
|
||||||
type="number"
|
type="number"
|
||||||
min="0"
|
min="0"
|
||||||
className="border-2 border-black rounded-md text-center w-1/2"
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
value={meetingTime}
|
value={meetingTime === 0 ? "" : meetingTime}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
if (e.target.value === "") {
|
||||||
|
setMeetingTime(0);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
setMeetingTime(parseInt(e.target.value));
|
setMeetingTime(parseInt(e.target.value));
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
const keyValue = event.key;
|
const keyValue = event.key;
|
||||||
|
@ -128,9 +176,14 @@ export default function NewWeeklyReport(): JSX.Element {
|
||||||
type="number"
|
type="number"
|
||||||
min="0"
|
min="0"
|
||||||
className="border-2 border-black rounded-md text-center w-1/2"
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
value={adminTime}
|
value={adminTime === 0 ? "" : adminTime}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
if (e.target.value === "") {
|
||||||
|
setAdminTime(0);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
setAdminTime(parseInt(e.target.value));
|
setAdminTime(parseInt(e.target.value));
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
const keyValue = event.key;
|
const keyValue = event.key;
|
||||||
|
@ -147,9 +200,14 @@ export default function NewWeeklyReport(): JSX.Element {
|
||||||
type="number"
|
type="number"
|
||||||
min="0"
|
min="0"
|
||||||
className="border-2 border-black rounded-md text-center w-1/2"
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
value={ownWorkTime}
|
value={ownWorkTime === 0 ? "" : ownWorkTime}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
if (e.target.value === "") {
|
||||||
|
setOwnWorkTime(0);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
setOwnWorkTime(parseInt(e.target.value));
|
setOwnWorkTime(parseInt(e.target.value));
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
const keyValue = event.key;
|
const keyValue = event.key;
|
||||||
|
@ -166,9 +224,14 @@ export default function NewWeeklyReport(): JSX.Element {
|
||||||
type="number"
|
type="number"
|
||||||
min="0"
|
min="0"
|
||||||
className="border-2 border-black rounded-md text-center w-1/2"
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
value={studyTime}
|
value={studyTime === 0 ? "" : studyTime}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
if (e.target.value === "") {
|
||||||
|
setStudyTime(0);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
setStudyTime(parseInt(e.target.value));
|
setStudyTime(parseInt(e.target.value));
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
const keyValue = event.key;
|
const keyValue = event.key;
|
||||||
|
@ -185,9 +248,14 @@ export default function NewWeeklyReport(): JSX.Element {
|
||||||
type="number"
|
type="number"
|
||||||
min="0"
|
min="0"
|
||||||
className="border-2 border-black rounded-md text-center w-1/2"
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
value={testingTime}
|
value={testingTime === 0 ? "" : testingTime}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
if (e.target.value === "") {
|
||||||
|
setTestingTime(0);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
setTestingTime(parseInt(e.target.value));
|
setTestingTime(parseInt(e.target.value));
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
onKeyDown={(event) => {
|
onKeyDown={(event) => {
|
||||||
const keyValue = event.key;
|
const keyValue = event.key;
|
||||||
|
|
153
frontend/src/Components/OtherUsersTR.tsx
Normal file
153
frontend/src/Components/OtherUsersTR.tsx
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import { WeeklyReport } from "../Types/goTypes";
|
||||||
|
import { api } from "../API/API";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the component for editing a weekly report.
|
||||||
|
* @returns JSX.Element
|
||||||
|
*/
|
||||||
|
|
||||||
|
//This component does not yet work as intended. It is supposed to display the weekly report of a user in a project.
|
||||||
|
export default function OtherUsersTR(): JSX.Element {
|
||||||
|
const [week, setWeek] = useState(0);
|
||||||
|
const [developmentTime, setDevelopmentTime] = useState(0);
|
||||||
|
const [meetingTime, setMeetingTime] = useState(0);
|
||||||
|
const [adminTime, setAdminTime] = useState(0);
|
||||||
|
const [ownWorkTime, setOwnWorkTime] = useState(0);
|
||||||
|
const [studyTime, setStudyTime] = useState(0);
|
||||||
|
const [testingTime, setTestingTime] = useState(0);
|
||||||
|
|
||||||
|
const token = localStorage.getItem("accessToken") ?? "";
|
||||||
|
const { projectName } = useParams();
|
||||||
|
const { username } = useParams();
|
||||||
|
const { fetchedWeek } = useParams();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchUsersWeeklyReport = async (): Promise<void> => {
|
||||||
|
const response = await api.getWeeklyReport(
|
||||||
|
projectName ?? "",
|
||||||
|
fetchedWeek?.toString() ?? "0",
|
||||||
|
token,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
const report: WeeklyReport = response.data ?? {
|
||||||
|
reportId: 0,
|
||||||
|
userId: 0,
|
||||||
|
projectId: 0,
|
||||||
|
week: 0,
|
||||||
|
developmentTime: 0,
|
||||||
|
meetingTime: 0,
|
||||||
|
adminTime: 0,
|
||||||
|
ownWorkTime: 0,
|
||||||
|
studyTime: 0,
|
||||||
|
testingTime: 0,
|
||||||
|
};
|
||||||
|
setWeek(report.week);
|
||||||
|
setDevelopmentTime(report.developmentTime);
|
||||||
|
setMeetingTime(report.meetingTime);
|
||||||
|
setAdminTime(report.adminTime);
|
||||||
|
setOwnWorkTime(report.ownWorkTime);
|
||||||
|
setStudyTime(report.studyTime);
|
||||||
|
setTestingTime(report.testingTime);
|
||||||
|
} else {
|
||||||
|
console.error("Failed to fetch weekly report:", response.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void fetchUsersWeeklyReport();
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h1 className="text-[30px] font-bold">{username}'s Report</h1>
|
||||||
|
<div className="border-4 border-black bg-white flex flex-col justify-start min-h-[65vh] h-fit w-[50vw] rounded-3xl overflow-scroll space-y-[2vh] p-[30px] items-center">
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
|
<div className="flex flex-col w-1/2 border-b-2 border-black items-center justify-center">
|
||||||
|
<h1 className="font-bold text-[30px]"> Week: {week}</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table className="w-full text-center divide-y divide-x divide-white text-[30px]">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th className="w-1/2 py-2 border-b-2 border-black">Activity</th>
|
||||||
|
<th className="w-1/2 py-2 border-b-2 border-black">
|
||||||
|
Total Time (min)
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="divide-y divide-black">
|
||||||
|
<tr className="h-[10vh]">
|
||||||
|
<td>Development</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
min="0"
|
||||||
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
|
value={developmentTime === 0 ? "" : developmentTime}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="h-[10vh]">
|
||||||
|
<td>Meeting</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
min="0"
|
||||||
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
|
value={meetingTime === 0 ? "" : meetingTime}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="h-[10vh]">
|
||||||
|
<td>Administration</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
min="0"
|
||||||
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
|
value={adminTime === 0 ? "" : adminTime}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="h-[10vh]">
|
||||||
|
<td>Own Work</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
min="0"
|
||||||
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
|
value={ownWorkTime === 0 ? "" : ownWorkTime}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="h-[10vh]">
|
||||||
|
<td>Studies</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
min="0"
|
||||||
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
|
value={studyTime === 0 ? "" : studyTime}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="h-[10vh]">
|
||||||
|
<td>Testing</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
min="0"
|
||||||
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
|
value={testingTime === 0 ? "" : testingTime}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,91 +1,55 @@
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Link, useParams } from "react-router-dom";
|
import { Link, useParams } from "react-router-dom";
|
||||||
|
import { api } from "../API/API";
|
||||||
|
import { UserProjectMember } from "../Types/goTypes";
|
||||||
|
|
||||||
function ProjectMembers(): JSX.Element {
|
function ProjectMembers(): JSX.Element {
|
||||||
const { projectName } = useParams();
|
const { projectName } = useParams();
|
||||||
const [projectMembers, setProjectMembers] = useState<ProjectMember[]>([]);
|
const [projectMembers, setProjectMembers] = useState<UserProjectMember[]>([]);
|
||||||
|
|
||||||
// const getProjectMembers = async (): Promise<void> => {
|
|
||||||
// const token = localStorage.getItem("accessToken") ?? "";
|
|
||||||
// const response = await api.getProjectMembers(projectName ?? "", token);
|
|
||||||
// console.log(response);
|
|
||||||
// if (response.success) {
|
|
||||||
// setProjectMembers(response.data ?? []);
|
|
||||||
// } else {
|
|
||||||
// console.error(response.message);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
interface ProjectMember {
|
|
||||||
username: string;
|
|
||||||
role: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const mockProjectMembers = [
|
|
||||||
{
|
|
||||||
username: "username1",
|
|
||||||
role: "Project Manager",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
username: "username2",
|
|
||||||
role: "System Manager",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
username: "username3",
|
|
||||||
role: "Developer",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
username: "username4",
|
|
||||||
role: "Tester",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
username: "username5",
|
|
||||||
role: "Tester",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
username: "username6",
|
|
||||||
role: "Tester",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const getProjectMembers = async (): Promise<void> => {
|
|
||||||
// Use the mock data
|
|
||||||
setProjectMembers(mockProjectMembers);
|
|
||||||
|
|
||||||
await Promise.resolve();
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const getProjectMembers = async (): Promise<void> => {
|
||||||
|
const token = localStorage.getItem("accessToken") ?? "";
|
||||||
|
const response = await api.getAllUsersProject(projectName ?? "", token);
|
||||||
|
console.log(response);
|
||||||
|
if (response.success) {
|
||||||
|
setProjectMembers(response.data ?? []);
|
||||||
|
} else {
|
||||||
|
console.error(response.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void getProjectMembers();
|
void getProjectMembers();
|
||||||
});
|
}, [projectName]);
|
||||||
|
|
||||||
|
interface ProjectMember {
|
||||||
|
Username: string;
|
||||||
|
UserRole: string;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<h1 className="font-bold text-[30px] mb-[20px]">
|
||||||
|
All Members In: {projectName}{" "}
|
||||||
|
</h1>
|
||||||
<div className="border-4 border-black bg-white flex flex-col items-center justify-center min-h-[65vh] h-fit w-[70vw] rounded-3xl content-center overflow-scroll space-y-[10vh] p-[30px] text-[20px]">
|
<div className="border-4 border-black bg-white flex flex-col items-center justify-center min-h-[65vh] h-fit w-[70vw] rounded-3xl content-center overflow-scroll space-y-[10vh] p-[30px] text-[20px]">
|
||||||
{projectMembers.map((projectMember, index) => (
|
{projectMembers.map((projectMember: ProjectMember, index: number) => (
|
||||||
<h1 key={index} className="border-b-2 border-black w-full">
|
<h1 key={index} className="border-b-2 border-black w-full">
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<h1>{projectMember.username}</h1>
|
<h1>{projectMember.Username}</h1>
|
||||||
<span className="ml-6 mr-2 font-bold">Role:</span>
|
<span className="ml-6 mr-2 font-bold">Role:</span>
|
||||||
<h1>{projectMember.role}</h1>
|
<h1>{projectMember.UserRole}</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<div className="ml-auto flex space-x-4">
|
<div className="ml-auto flex space-x-4">
|
||||||
<Link
|
<Link
|
||||||
to={`/viewReports/${projectName}/${projectMember.username}`}
|
to={`/otherUsersTimeReports/${projectName}/${projectMember.Username}`}
|
||||||
>
|
>
|
||||||
<h1 className="underline cursor-pointer font-bold">
|
<h1 className="underline cursor-pointer font-bold">
|
||||||
View Reports
|
View Reports
|
||||||
</h1>
|
</h1>
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
|
||||||
to={`/changeRole/${projectName}/${projectMember.username}`}
|
|
||||||
>
|
|
||||||
<h1 className="underline cursor-pointer font-bold">
|
|
||||||
Change Role
|
|
||||||
</h1>
|
|
||||||
</Link>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
175
frontend/src/Components/TimePerActivity.tsx
Normal file
175
frontend/src/Components/TimePerActivity.tsx
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the component for showing total time per role in a project.
|
||||||
|
* @returns JSX.Element
|
||||||
|
*/
|
||||||
|
export default function TimePerRole(): JSX.Element {
|
||||||
|
const [developmentTime, setDevelopmentTime] = useState<number>();
|
||||||
|
const [meetingTime, setMeetingTime] = useState<number>();
|
||||||
|
const [adminTime, setAdminTime] = useState<number>();
|
||||||
|
const [ownWorkTime, setOwnWorkTime] = useState<number>();
|
||||||
|
const [studyTime, setStudyTime] = useState<number>();
|
||||||
|
const [testingTime, setTestingTime] = useState<number>();
|
||||||
|
|
||||||
|
// const token = localStorage.getItem("accessToken") ?? "";
|
||||||
|
// const username = localStorage.getItem("username") ?? "";
|
||||||
|
const { projectName } = useParams();
|
||||||
|
|
||||||
|
// const fetchTimePerRole = async (): Promise<void> => {
|
||||||
|
// const response = await api.getTimePerRole(
|
||||||
|
// username,
|
||||||
|
// projectName ?? "",
|
||||||
|
// token,
|
||||||
|
// );
|
||||||
|
// {
|
||||||
|
// if (response.success) {
|
||||||
|
// const report: TimePerRole = response.data ?? {
|
||||||
|
// PManagerTime: 0,
|
||||||
|
// SManagerTime: 0,
|
||||||
|
// DeveloperTime: 0,
|
||||||
|
// TesterTime: 0,
|
||||||
|
// };
|
||||||
|
// } else {
|
||||||
|
// console.error("Failed to fetch weekly report:", response.message);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
interface TimePerActivity {
|
||||||
|
developmentTime: number;
|
||||||
|
meetingTime: number;
|
||||||
|
adminTime: number;
|
||||||
|
ownWorkTime: number;
|
||||||
|
studyTime: number;
|
||||||
|
testingTime: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchTimePerActivity = async (): Promise<void> => {
|
||||||
|
// Use mock data
|
||||||
|
const report: TimePerActivity = {
|
||||||
|
developmentTime: 100,
|
||||||
|
meetingTime: 200,
|
||||||
|
adminTime: 300,
|
||||||
|
ownWorkTime: 50,
|
||||||
|
studyTime: 75,
|
||||||
|
testingTime: 110,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set the state with the mock data
|
||||||
|
setDevelopmentTime(report.developmentTime);
|
||||||
|
setMeetingTime(report.meetingTime);
|
||||||
|
setAdminTime(report.adminTime);
|
||||||
|
setOwnWorkTime(report.ownWorkTime);
|
||||||
|
setStudyTime(report.studyTime);
|
||||||
|
setTestingTime(report.testingTime);
|
||||||
|
|
||||||
|
await Promise.resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
void fetchTimePerActivity();
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h1 className="font-bold text-[30px] mb-[20px]">
|
||||||
|
Total Time Per Activity In: {projectName}{" "}
|
||||||
|
</h1>
|
||||||
|
<div className="border-4 border-black bg-white flex flex-col justify-start min-h-[65vh] h-fit w-[50vw] rounded-3xl overflow-scroll space-y-[2vh] p-[30px] items-center">
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
|
<table className="w-full text-center divide-y divide-x divide-white text-[30px]">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th className="w-1/2 py-2 border-b-2 border-black">Activity</th>
|
||||||
|
<th className="w-1/2 py-2 border-b-2 border-black">
|
||||||
|
Total Time (min)
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="divide-y divide-black">
|
||||||
|
<tr className="h-[10vh]">
|
||||||
|
<td>Development</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="string"
|
||||||
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
|
value={developmentTime}
|
||||||
|
onKeyDown={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="h-[10vh]">
|
||||||
|
<td>Meeting</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="string"
|
||||||
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
|
value={meetingTime}
|
||||||
|
onKeyDown={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="h-[10vh]">
|
||||||
|
<td>Administration</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="string"
|
||||||
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
|
value={adminTime}
|
||||||
|
onKeyDown={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="h-[10vh]">
|
||||||
|
<td>Own Work</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="string"
|
||||||
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
|
value={ownWorkTime}
|
||||||
|
onKeyDown={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="h-[10vh]">
|
||||||
|
<td>Studies</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="string"
|
||||||
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
|
value={studyTime}
|
||||||
|
onKeyDown={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="h-[10vh]">
|
||||||
|
<td>Testing</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="string"
|
||||||
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
|
value={testingTime}
|
||||||
|
onKeyDown={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
141
frontend/src/Components/TimePerRole.tsx
Normal file
141
frontend/src/Components/TimePerRole.tsx
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the component for showing total time per role in a project.
|
||||||
|
* @returns JSX.Element
|
||||||
|
*/
|
||||||
|
export default function TimePerRole(): JSX.Element {
|
||||||
|
const [PManagerTime, setPManagerTime] = useState(0);
|
||||||
|
const [SManagerTime, setSManagerTime] = useState(0);
|
||||||
|
const [DeveloperTime, setDeveloperTime] = useState(0);
|
||||||
|
const [TesterTime, setTesterTime] = useState(0);
|
||||||
|
|
||||||
|
// const token = localStorage.getItem("accessToken") ?? "";
|
||||||
|
// const username = localStorage.getItem("username") ?? "";
|
||||||
|
const { projectName } = useParams();
|
||||||
|
|
||||||
|
// const fetchTimePerRole = async (): Promise<void> => {
|
||||||
|
// const response = await api.getTimePerRole(
|
||||||
|
// username,
|
||||||
|
// projectName ?? "",
|
||||||
|
// token,
|
||||||
|
// );
|
||||||
|
// {
|
||||||
|
// if (response.success) {
|
||||||
|
// const report: TimePerRole = response.data ?? {
|
||||||
|
// PManagerTime: 0,
|
||||||
|
// SManagerTime: 0,
|
||||||
|
// DeveloperTime: 0,
|
||||||
|
// TesterTime: 0,
|
||||||
|
// };
|
||||||
|
// } else {
|
||||||
|
// console.error("Failed to fetch weekly report:", response.message);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
interface TimePerRole {
|
||||||
|
PManager: number;
|
||||||
|
SManager: number;
|
||||||
|
Developer: number;
|
||||||
|
Tester: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchTimePerRole = async (): Promise<void> => {
|
||||||
|
// Use mock data
|
||||||
|
const report: TimePerRole = {
|
||||||
|
PManager: 120,
|
||||||
|
SManager: 80,
|
||||||
|
Developer: 200,
|
||||||
|
Tester: 150,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set the state with the mock data
|
||||||
|
setPManagerTime(report.PManager);
|
||||||
|
setSManagerTime(report.SManager);
|
||||||
|
setDeveloperTime(report.Developer);
|
||||||
|
setTesterTime(report.Tester);
|
||||||
|
|
||||||
|
await Promise.resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
void fetchTimePerRole();
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h1 className="font-bold text-[30px] mb-[20px]">
|
||||||
|
Total Time Per Role In: {projectName}{" "}
|
||||||
|
</h1>
|
||||||
|
<div className="border-4 border-black bg-white flex flex-col justify-start min-h-[65vh] h-fit w-[50vw] rounded-3xl overflow-scroll space-y-[2vh] p-[30px] items-center">
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
|
<table className="w-full text-center divide-y divide-x divide-white text-[30px]">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th className="w-1/2 py-2 border-b-2 border-black">Role</th>
|
||||||
|
<th className="w-1/2 py-2 border-b-2 border-black">
|
||||||
|
Total Time (min)
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="divide-y divide-black">
|
||||||
|
<tr className="h-[10vh]">
|
||||||
|
<td>Project Manager</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="string"
|
||||||
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
|
value={PManagerTime}
|
||||||
|
onKeyDown={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="h-[10vh]">
|
||||||
|
<td>System Manager</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="string"
|
||||||
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
|
value={SManagerTime}
|
||||||
|
onKeyDown={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="h-[10vh]">
|
||||||
|
<td>Administration</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="string"
|
||||||
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
|
value={DeveloperTime}
|
||||||
|
onKeyDown={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="h-[10vh]">
|
||||||
|
<td>Own Work</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="string"
|
||||||
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
|
value={TesterTime}
|
||||||
|
onKeyDown={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
188
frontend/src/Components/ViewOtherTimeReport.tsx
Normal file
188
frontend/src/Components/ViewOtherTimeReport.tsx
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import { WeeklyReport, NewWeeklyReport } from "../Types/goTypes";
|
||||||
|
import { api } from "../API/API";
|
||||||
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
|
import Button from "./Button";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the component for editing a weekly report.
|
||||||
|
* @returns JSX.Element
|
||||||
|
*/
|
||||||
|
|
||||||
|
//This component does not yet work as intended. It is supposed to display the weekly report of a user in a project.
|
||||||
|
export default function GetOtherUsersReport(): JSX.Element {
|
||||||
|
const [week, setWeek] = useState(0);
|
||||||
|
const [developmentTime, setDevelopmentTime] = useState(0);
|
||||||
|
const [meetingTime, setMeetingTime] = useState(0);
|
||||||
|
const [adminTime, setAdminTime] = useState(0);
|
||||||
|
const [ownWorkTime, setOwnWorkTime] = useState(0);
|
||||||
|
const [studyTime, setStudyTime] = useState(0);
|
||||||
|
const [testingTime, setTestingTime] = useState(0);
|
||||||
|
|
||||||
|
const token = localStorage.getItem("accessToken") ?? "";
|
||||||
|
const { projectName } = useParams();
|
||||||
|
const { username } = useParams();
|
||||||
|
const { fetchedWeek } = useParams();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchUsersWeeklyReport = async (): Promise<void> => {
|
||||||
|
const response = await api.getWeeklyReport(
|
||||||
|
projectName ?? "",
|
||||||
|
fetchedWeek?.toString() ?? "0",
|
||||||
|
token,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
const report: WeeklyReport = response.data ?? {
|
||||||
|
reportId: 0,
|
||||||
|
userId: 0,
|
||||||
|
projectId: 0,
|
||||||
|
week: 0,
|
||||||
|
developmentTime: 0,
|
||||||
|
meetingTime: 0,
|
||||||
|
adminTime: 0,
|
||||||
|
ownWorkTime: 0,
|
||||||
|
studyTime: 0,
|
||||||
|
testingTime: 0,
|
||||||
|
};
|
||||||
|
setWeek(report.week);
|
||||||
|
setDevelopmentTime(report.developmentTime);
|
||||||
|
setMeetingTime(report.meetingTime);
|
||||||
|
setAdminTime(report.adminTime);
|
||||||
|
setOwnWorkTime(report.ownWorkTime);
|
||||||
|
setStudyTime(report.studyTime);
|
||||||
|
setTestingTime(report.testingTime);
|
||||||
|
} else {
|
||||||
|
console.error("Failed to fetch weekly report:", response.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void fetchUsersWeeklyReport();
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleSignWeeklyReport = async (): Promise<void> => {
|
||||||
|
const newWeeklyReport: NewWeeklyReport = {
|
||||||
|
projectName: projectName ?? "",
|
||||||
|
week,
|
||||||
|
developmentTime,
|
||||||
|
meetingTime,
|
||||||
|
adminTime,
|
||||||
|
ownWorkTime,
|
||||||
|
studyTime,
|
||||||
|
testingTime,
|
||||||
|
};
|
||||||
|
|
||||||
|
await api.submitWeeklyReport(newWeeklyReport, token);
|
||||||
|
};
|
||||||
|
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h1 className="text-[30px] font-bold">{username}'s Report</h1>
|
||||||
|
<div className="border-4 border-black bg-white flex flex-col justify-start min-h-[65vh] h-fit w-[50vw] rounded-3xl overflow-scroll space-y-[2vh] p-[30px] items-center">
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
void handleSignWeeklyReport();
|
||||||
|
navigate(-1);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
|
<div className="flex flex-col w-1/2 border-b-2 border-black items-center justify-center">
|
||||||
|
<h1 className="font-bold text-[30px]"> Week: {week}</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table className="w-full text-center divide-y divide-x divide-white text-[30px]">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th className="w-1/2 py-2 border-b-2 border-black">
|
||||||
|
Activity
|
||||||
|
</th>
|
||||||
|
<th className="w-1/2 py-2 border-b-2 border-black">
|
||||||
|
Total Time (min)
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="divide-y divide-black">
|
||||||
|
<tr className="h-[10vh]">
|
||||||
|
<td>Development</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
min="0"
|
||||||
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
|
value={developmentTime === 0 ? "" : developmentTime}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="h-[10vh]">
|
||||||
|
<td>Meeting</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
min="0"
|
||||||
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
|
value={meetingTime === 0 ? "" : meetingTime}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="h-[10vh]">
|
||||||
|
<td>Administration</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
min="0"
|
||||||
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
|
value={adminTime === 0 ? "" : adminTime}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="h-[10vh]">
|
||||||
|
<td>Own Work</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
min="0"
|
||||||
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
|
value={ownWorkTime === 0 ? "" : ownWorkTime}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="h-[10vh]">
|
||||||
|
<td>Studies</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
min="0"
|
||||||
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
|
value={studyTime === 0 ? "" : studyTime}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="h-[10vh]">
|
||||||
|
<td>Testing</td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
min="0"
|
||||||
|
className="border-2 border-black rounded-md text-center w-1/2"
|
||||||
|
value={testingTime === 0 ? "" : testingTime}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<Button
|
||||||
|
text="Sign Report"
|
||||||
|
onClick={(): void => {
|
||||||
|
return;
|
||||||
|
}}
|
||||||
|
type="submit"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,8 +1,13 @@
|
||||||
import BasicWindow from "../../Components/BasicWindow";
|
import BasicWindow from "../../Components/BasicWindow";
|
||||||
import BackButton from "../../Components/BackButton";
|
import BackButton from "../../Components/BackButton";
|
||||||
|
import AllTimeReportsInProjectOtherUser from "../../Components/AllTimeReportsInProjectOtherUser";
|
||||||
|
|
||||||
function PMOtherUsersTR(): JSX.Element {
|
function PMOtherUsersTR(): JSX.Element {
|
||||||
const content = <></>;
|
const content = (
|
||||||
|
<>
|
||||||
|
<AllTimeReportsInProjectOtherUser />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
const buttons = (
|
const buttons = (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -8,16 +8,13 @@ function PMProjectMembers(): JSX.Element {
|
||||||
const { projectName } = useParams();
|
const { projectName } = useParams();
|
||||||
const content = (
|
const content = (
|
||||||
<>
|
<>
|
||||||
<h1 className="font-bold text-[30px] mb-[20px]">
|
|
||||||
All Members In: {projectName}{" "}
|
|
||||||
</h1>
|
|
||||||
<ProjectMembers />
|
<ProjectMembers />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
const buttons = (
|
const buttons = (
|
||||||
<>
|
<>
|
||||||
<Link to="/PM-time-activity">
|
<Link to={`/PMtimeactivity/${projectName}`}>
|
||||||
<Button
|
<Button
|
||||||
text="Time / Activity"
|
text="Time / Activity"
|
||||||
onClick={(): void => {
|
onClick={(): void => {
|
||||||
|
@ -26,15 +23,6 @@ function PMProjectMembers(): JSX.Element {
|
||||||
type={"button"}
|
type={"button"}
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<Link to="/PM-time-role">
|
|
||||||
<Button
|
|
||||||
text="Time / Role"
|
|
||||||
onClick={(): void => {
|
|
||||||
return;
|
|
||||||
}}
|
|
||||||
type={"button"}
|
|
||||||
/>
|
|
||||||
</Link>
|
|
||||||
<BackButton />
|
<BackButton />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
import BackButton from "../../Components/BackButton";
|
import BackButton from "../../Components/BackButton";
|
||||||
import BasicWindow from "../../Components/BasicWindow";
|
import BasicWindow from "../../Components/BasicWindow";
|
||||||
import TimeReport from "../../Components/NewWeeklyReport";
|
import TimePerActivity from "../../Components/TimePerActivity";
|
||||||
|
|
||||||
function PMTotalTimeActivity(): JSX.Element {
|
function PMTotalTimeActivity(): JSX.Element {
|
||||||
const content = (
|
const content = (
|
||||||
<>
|
<>
|
||||||
<h1 className="font-bold text-[30px] mb-[20px]">
|
<TimePerActivity />
|
||||||
Total Time Per Activity
|
|
||||||
</h1>
|
|
||||||
<TimeReport />
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
import BasicWindow from "../../Components/BasicWindow";
|
import BasicWindow from "../../Components/BasicWindow";
|
||||||
import BackButton from "../../Components/BackButton";
|
import BackButton from "../../Components/BackButton";
|
||||||
|
import TimePerRole from "../../Components/TimePerRole";
|
||||||
|
|
||||||
function PMTotalTimeRole(): JSX.Element {
|
function PMTotalTimeRole(): JSX.Element {
|
||||||
const content = <></>;
|
const content = (
|
||||||
|
<>
|
||||||
|
<TimePerRole />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
const buttons = (
|
const buttons = (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
import BasicWindow from "../../Components/BasicWindow";
|
import BasicWindow from "../../Components/BasicWindow";
|
||||||
import BackButton from "../../Components/BackButton";
|
import BackButton from "../../Components/BackButton";
|
||||||
|
import DisplayUnsignedReports from "../../Components/DisplayUnsignedReports";
|
||||||
|
|
||||||
function PMUnsignedReports(): JSX.Element {
|
function PMUnsignedReports(): JSX.Element {
|
||||||
const content = <></>;
|
const content = (
|
||||||
|
<>
|
||||||
|
<DisplayUnsignedReports />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
const buttons = (
|
const buttons = (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
import BasicWindow from "../../Components/BasicWindow";
|
||||||
|
import BackButton from "../../Components/BackButton";
|
||||||
|
import OtherUsersTR from "../../Components/OtherUsersTR";
|
||||||
|
|
||||||
|
function PMViewOtherUsersTR(): JSX.Element {
|
||||||
|
const content = (
|
||||||
|
<>
|
||||||
|
<OtherUsersTR />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
const buttons = (
|
||||||
|
<>
|
||||||
|
<BackButton />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
return <BasicWindow content={content} buttons={buttons} />;
|
||||||
|
}
|
||||||
|
export default PMViewOtherUsersTR;
|
|
@ -1,34 +1,16 @@
|
||||||
import BackButton from "../../Components/BackButton";
|
import BackButton from "../../Components/BackButton";
|
||||||
import BasicWindow from "../../Components/BasicWindow";
|
import BasicWindow from "../../Components/BasicWindow";
|
||||||
import Button from "../../Components/Button";
|
import ViewOtherTimeReport from "../../Components/ViewOtherTimeReport";
|
||||||
import TimeReport from "../../Components/NewWeeklyReport";
|
|
||||||
|
|
||||||
function PMViewUnsignedReport(): JSX.Element {
|
function PMViewUnsignedReport(): JSX.Element {
|
||||||
const content = (
|
const content = (
|
||||||
<>
|
<>
|
||||||
<h1 className="font-bold text-[30px] mb-[20px]">
|
<ViewOtherTimeReport />
|
||||||
Username's Time Report
|
|
||||||
</h1>
|
|
||||||
<TimeReport />
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
const buttons = (
|
const buttons = (
|
||||||
<>
|
<>
|
||||||
<Button
|
|
||||||
text="Sign"
|
|
||||||
onClick={(): void => {
|
|
||||||
return;
|
|
||||||
}}
|
|
||||||
type="button"
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
text="Save"
|
|
||||||
onClick={(): void => {
|
|
||||||
return;
|
|
||||||
}}
|
|
||||||
type="button"
|
|
||||||
/>
|
|
||||||
<BackButton />
|
<BackButton />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,7 +5,6 @@ import EditWeeklyReport from "../../Components/EditWeeklyReport";
|
||||||
function UserEditTimeReportPage(): JSX.Element {
|
function UserEditTimeReportPage(): JSX.Element {
|
||||||
const content = (
|
const content = (
|
||||||
<>
|
<>
|
||||||
<h1 className="font-bold text-[30px] mb-[20px]">Edit Time Report</h1>
|
|
||||||
<EditWeeklyReport />
|
<EditWeeklyReport />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -31,6 +31,7 @@ import AdminProjectViewMemberInfo from "./Pages/AdminPages/AdminProjectViewMembe
|
||||||
import AdminProjectPage from "./Pages/AdminPages/AdminProjectPage.tsx";
|
import AdminProjectPage from "./Pages/AdminPages/AdminProjectPage.tsx";
|
||||||
import NotFoundPage from "./Pages/NotFoundPage.tsx";
|
import NotFoundPage from "./Pages/NotFoundPage.tsx";
|
||||||
import UnauthorizedPage from "./Pages/UnauthorizedPage.tsx";
|
import UnauthorizedPage from "./Pages/UnauthorizedPage.tsx";
|
||||||
|
import PMViewOtherUsersTR from "./Pages/ProjectManagerPages/PMViewOtherUsersTR.tsx";
|
||||||
|
|
||||||
// This is where the routes are mounted
|
// This is where the routes are mounted
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
|
@ -60,7 +61,7 @@ const router = createBrowserRouter([
|
||||||
element: <UserViewTimeReportsPage />,
|
element: <UserViewTimeReportsPage />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/editTimeReport/:projectName/:weekNumber",
|
path: "/editTimeReport/:projectName/:fetchedWeek",
|
||||||
element: <UserEditTimeReportPage />,
|
element: <UserEditTimeReportPage />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -68,9 +69,13 @@ const router = createBrowserRouter([
|
||||||
element: <PMChangeRole />,
|
element: <PMChangeRole />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/otherUsersTimeReports",
|
path: "/otherUsersTimeReports/:projectName/:username",
|
||||||
element: <PMOtherUsersTR />,
|
element: <PMOtherUsersTR />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/editOthersTR/:projectName/:username/:fetchedWeek",
|
||||||
|
element: <PMViewOtherUsersTR />,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/projectMembers/:projectName",
|
path: "/projectMembers/:projectName",
|
||||||
element: <PMProjectMembers />,
|
element: <PMProjectMembers />,
|
||||||
|
@ -80,11 +85,11 @@ const router = createBrowserRouter([
|
||||||
element: <PMProjectPage />,
|
element: <PMProjectPage />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/PMTimeActivity",
|
path: "/PMTimeActivity/:projectName",
|
||||||
element: <PMTotalTimeActivity />,
|
element: <PMTotalTimeActivity />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/PMTimeRole",
|
path: "/PMTimeRole/:projectName",
|
||||||
element: <PMTotalTimeRole />,
|
element: <PMTotalTimeRole />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -92,7 +97,7 @@ const router = createBrowserRouter([
|
||||||
element: <PMUnsignedReports />,
|
element: <PMUnsignedReports />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/PMViewUnsignedReport",
|
path: "/PMViewUnsignedReport/:projectName/:username/:fetchedWeek",
|
||||||
element: <PMViewUnsignedReport />,
|
element: <PMViewUnsignedReport />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue