Merge branch 'frontend' into gruppPP
This commit is contained in:
commit
2f8e7547da
17 changed files with 397 additions and 49 deletions
|
@ -1004,8 +1004,8 @@ export const api: API = {
|
|||
}
|
||||
},
|
||||
async getStatistics(
|
||||
token: string,
|
||||
projectName: string,
|
||||
token: string,
|
||||
userName?: string,
|
||||
): Promise<APIResponse<Statistics>> {
|
||||
try {
|
||||
|
|
|
@ -37,9 +37,9 @@ function AllTimeReportsInProject(): JSX.Element {
|
|||
<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={`/editTimeReport/${projectName}/${newWeeklyReport.week}`}
|
||||
to={`/editTimeReport/${projectName}/${newWeeklyReport.week}/${newWeeklyReport.signedBy ? "signed" : "unsigned"}`}
|
||||
key={index}
|
||||
className="border-b-2 border-black w-full"
|
||||
className="border-b-2 border-black w-full cursor-pointer hover:font-extrabold"
|
||||
>
|
||||
<div className="flex justify-between">
|
||||
<h1>
|
||||
|
|
|
@ -39,9 +39,9 @@ function AllTimeReportsInProject(): JSX.Element {
|
|||
<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}`}
|
||||
to={`/editOthersTR/${projectName}/${username}/${newWeeklyReport.week}/${newWeeklyReport.signedBy ? "signed" : "unsigned"}`}
|
||||
key={index}
|
||||
className="border-b-2 border-black w-full"
|
||||
className="border-b-2 border-black w-full hover:font-extrabold"
|
||||
>
|
||||
<div className="flex justify-between">
|
||||
<h1>
|
||||
|
|
|
@ -65,7 +65,7 @@ function DisplayUserProject(): JSX.Element {
|
|||
<Link
|
||||
to={`/PMViewUnsignedReport/${projectName}/${usernames[index]}/${unsignedReport.week}`}
|
||||
>
|
||||
<h1 className="underline cursor-pointer font-bold">
|
||||
<h1 className="cursor-pointer font-bold hover:font-extrabold hover:underline">
|
||||
View Report
|
||||
</h1>
|
||||
</Link>
|
||||
|
|
|
@ -45,7 +45,7 @@ function DisplayUserProject(): JSX.Element {
|
|||
onClick={() => void handleProjectClick(project.name)}
|
||||
key={project.id}
|
||||
>
|
||||
<h1 className="font-bold underline text-[30px] cursor-pointer">
|
||||
<h1 className="font-bold hover:underline text-[30px] cursor-pointer hover:font-extrabold">
|
||||
{project.name}
|
||||
</h1>
|
||||
</div>
|
||||
|
|
|
@ -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<void> => {
|
||||
|
@ -59,7 +60,7 @@ export default function GetWeeklyReport(): JSX.Element {
|
|||
};
|
||||
|
||||
void fetchWeeklyReport();
|
||||
}, [projectName, fetchedWeek, token]);
|
||||
}, [projectName, fetchedWeek, signedOrUnsigned, token]);
|
||||
|
||||
const handleUpdateWeeklyReport = async (): Promise<void> => {
|
||||
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"}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -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"}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -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"}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -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"}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -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"}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -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"}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<Button
|
||||
text="Submit changes"
|
||||
onClick={(): void => {
|
||||
return;
|
||||
}}
|
||||
type="submit"
|
||||
/>
|
||||
{signedOrUnsigned !== "signed" && (
|
||||
<Button
|
||||
text="Submit changes"
|
||||
onClick={(): void => {
|
||||
return;
|
||||
}}
|
||||
type="submit"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -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<void> => {
|
||||
|
@ -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<boolean> => {
|
||||
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<boolean> => {
|
||||
const response = await api.deleteWeeklyReport(reportId, token);
|
||||
console.log(response);
|
||||
if (response.success) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1 className="text-[30px] font-bold">{username}'s Report</h1>
|
||||
|
@ -153,6 +179,48 @@ export default function OtherUsersTR(): JSX.Element {
|
|||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div className="flex space-x-4">
|
||||
{signedOrUnsigned === "signed" && (
|
||||
<Button
|
||||
text="Unsign Report"
|
||||
onClick={(): void => {
|
||||
void (async (): Promise<void> => {
|
||||
const success = await handleUnsignWeeklyReport();
|
||||
if (success) {
|
||||
alert("Report successfully unsigned!");
|
||||
navigate(-1);
|
||||
} else {
|
||||
alert("Failed to unsign report");
|
||||
return;
|
||||
}
|
||||
})();
|
||||
}}
|
||||
type={"button"}
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
text="Delete Time Report"
|
||||
onClick={(): void => {
|
||||
void (async (): Promise<void> => {
|
||||
const confirmDelete = window.confirm(
|
||||
"Are you sure you want to delete this report? This action cannot be undone.",
|
||||
);
|
||||
if (!confirmDelete) {
|
||||
return;
|
||||
}
|
||||
const success = await handleDeleteWeeklyReport();
|
||||
if (success) {
|
||||
alert("Report successfully deleted!");
|
||||
navigate(-1);
|
||||
} else {
|
||||
alert("Failed to delete report");
|
||||
return;
|
||||
}
|
||||
})();
|
||||
}}
|
||||
type={"button"}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
|
|
@ -8,22 +8,22 @@ function PMProjectMenu(): JSX.Element {
|
|||
<h1 className="font-bold text-[30px] mb-[20px]">{projectName}</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-[5vh] p-[30px]">
|
||||
<Link to={`/timeReports/${projectName}/`}>
|
||||
<h1 className="font-bold underline text-[30px] cursor-pointer">
|
||||
<h1 className="font-bold hover:underline text-[30px] cursor-pointer hover:font-extrabold">
|
||||
Your Time Reports
|
||||
</h1>
|
||||
</Link>
|
||||
<Link to={`/newTimeReport/${projectName}`}>
|
||||
<h1 className="font-bold underline text-[30px] cursor-pointer">
|
||||
<h1 className="font-bold hover:underline text-[30px] cursor-pointer hover:font-extrabold">
|
||||
New Time Report
|
||||
</h1>
|
||||
</Link>
|
||||
<Link to={`/projectMembers/${projectName}`}>
|
||||
<h1 className="font-bold underline text-[30px] cursor-pointer">
|
||||
<h1 className="font-bold hover:underline text-[30px] cursor-pointer hover:font-extrabold">
|
||||
Statistics
|
||||
</h1>
|
||||
</Link>
|
||||
<Link to={`/unsignedReports/${projectName}`}>
|
||||
<h1 className="font-bold underline text-[30px] cursor-pointer">
|
||||
<h1 className="font-bold hover:underline text-[30px] cursor-pointer hover:font-extrabold">
|
||||
Unsigned Time Reports
|
||||
</h1>
|
||||
</Link>
|
||||
|
|
|
@ -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<void> => {
|
||||
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 (
|
||||
<>
|
||||
<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]">
|
||||
{projectMembers.map((projectMember: ProjectMember, index: number) => (
|
||||
<h1 key={index} className="border-b-2 border-black w-full">
|
||||
<div className="flex justify-between">
|
||||
<div className="flex">
|
||||
<h1>{projectMember.Username}</h1>
|
||||
<span className="ml-6 mr-2 font-bold">Role:</span>
|
||||
<h1>{projectMember.UserRole}</h1>
|
||||
</div>
|
||||
<div className="flex">
|
||||
<div className="ml-auto flex space-x-4">
|
||||
<Link
|
||||
to={`/otherUsersTimeReports/${projectName}/${projectMember.Username}`}
|
||||
>
|
||||
<h1 className="underline cursor-pointer font-bold">
|
||||
View Reports
|
||||
</h1>
|
||||
</Link>
|
||||
{projectMembers.map((projectMember: ProjectMember, index: number) => {
|
||||
if (projectMember.Username === "admin") {
|
||||
return null; // Skip rendering for admin user
|
||||
}
|
||||
return (
|
||||
<h1 key={index} className="border-b-2 border-black w-full">
|
||||
<div className="flex justify-between">
|
||||
<div className="flex">
|
||||
<h1>{projectMember.Username}</h1>
|
||||
<span className="ml-6 mr-2 font-bold">Role:</span>
|
||||
<h1>{projectMember.UserRole}</h1>
|
||||
</div>
|
||||
<div className="flex">
|
||||
<div className="ml-auto flex space-x-4">
|
||||
{projectMember.Username !==
|
||||
localStorage.getItem("username") && (
|
||||
<h1
|
||||
className="cursor-pointer font-bold hover:font-extrabold hover:underline"
|
||||
onClick={() => {
|
||||
confirm(
|
||||
"Are you sure you want to delete this user? This action cannot be undone.",
|
||||
) &&
|
||||
void handleUserDeleteClick(projectMember.Username);
|
||||
}}
|
||||
>
|
||||
Delete User
|
||||
</h1>
|
||||
)}
|
||||
<Link
|
||||
to={`/otherUsersTimeReports/${projectName}/${projectMember.Username}`}
|
||||
>
|
||||
<h1 className="cursor-pointer font-bold hover:font-extrabold hover:underline">
|
||||
View Reports
|
||||
</h1>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</h1>
|
||||
))}
|
||||
</h1>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -14,6 +14,7 @@ export default function TimePerRole(): JSX.Element {
|
|||
const [own_work, setOwnWork] = useState<number>(0);
|
||||
const [study, setStudy] = useState<number>(0);
|
||||
const [testing, setTesting] = useState<number>(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 (
|
||||
<>
|
||||
<h1 className="font-bold text-[30px] mb-[20px]">
|
||||
Total Time Per Activity In: {projectName}{" "}
|
||||
Total Time Per Activity For All Members 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">
|
||||
|
@ -129,6 +130,12 @@ export default function TimePerRole(): JSX.Element {
|
|||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr className="h-[10vh] font-bold font-">
|
||||
<td>In Total:</td>
|
||||
<td>
|
||||
<h1>{total}</h1>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
@ -16,12 +16,12 @@ function UserProjectMenu(): JSX.Element {
|
|||
<h1 className="font-bold text-[30px] mb-[20px]">{projectName}</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]">
|
||||
<Link to={`/timeReports/${projectName}/`}>
|
||||
<h1 className="font-bold underline text-[30px] cursor-pointer">
|
||||
<h1 className="font-bold hover:underline text-[30px] cursor-pointer hover:font-extrabold">
|
||||
Your Time Reports
|
||||
</h1>
|
||||
</Link>
|
||||
<Link to={`/newTimeReport/${projectName}`}>
|
||||
<h1 className="font-bold underline text-[30px] cursor-pointer">
|
||||
<h1 className="font-bold hover:underline text-[30px] cursor-pointer hover:font-extrabold">
|
||||
New Time Report
|
||||
</h1>
|
||||
</Link>
|
||||
|
|
150
frontend/src/Components/UserStatistics.tsx
Normal file
150
frontend/src/Components/UserStatistics.tsx
Normal file
|
@ -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<number>(0);
|
||||
const [meeting, setMeeting] = useState<number>(0);
|
||||
const [admin, setAdmin] = useState<number>(0);
|
||||
const [own_work, setOwnWork] = useState<number>(0);
|
||||
const [study, setStudy] = useState<number>(0);
|
||||
const [testing, setTesting] = useState<number>(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<void> => {
|
||||
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 (
|
||||
<>
|
||||
<h1 className="font-bold text-[30px] mb-[20px]">
|
||||
Total Time 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={development}
|
||||
readOnly
|
||||
/>
|
||||
</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={meeting}
|
||||
readOnly
|
||||
/>
|
||||
</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={admin}
|
||||
readOnly
|
||||
/>
|
||||
</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={own_work}
|
||||
readOnly
|
||||
/>
|
||||
</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={study}
|
||||
readOnly
|
||||
/>
|
||||
</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={testing}
|
||||
readOnly
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr className="h-[10vh] font-bold font-">
|
||||
<td>In Total:</td>
|
||||
<td>
|
||||
<h1>{total}</h1>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -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 = (
|
||||
<>
|
||||
<AllTimeReportsInProjectOtherUser />
|
||||
|
@ -11,6 +15,15 @@ function PMOtherUsersTR(): JSX.Element {
|
|||
|
||||
const buttons = (
|
||||
<>
|
||||
<Link to={`/viewStatistics/${projectName}/${username}`}>
|
||||
<Button
|
||||
text={`Statistics: ${username}`}
|
||||
onClick={(): void => {
|
||||
return;
|
||||
}}
|
||||
type={"button"}
|
||||
/>
|
||||
</Link>
|
||||
<BackButton />
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -16,7 +16,7 @@ function PMProjectMembers(): JSX.Element {
|
|||
<>
|
||||
<Link to={`/PMtimeactivity/${projectName}`}>
|
||||
<Button
|
||||
text="Time / Activity"
|
||||
text="Statistics"
|
||||
onClick={(): void => {
|
||||
return;
|
||||
}}
|
||||
|
|
20
frontend/src/Pages/UserPages/UserViewStatistics.tsx
Normal file
20
frontend/src/Pages/UserPages/UserViewStatistics.tsx
Normal file
|
@ -0,0 +1,20 @@
|
|||
import BackButton from "../../Components/BackButton";
|
||||
import BasicWindow from "../../Components/BasicWindow";
|
||||
import UserStatistics from "../../Components/UserStatistics";
|
||||
|
||||
function UserNewTimeReportPage(): JSX.Element {
|
||||
const content = (
|
||||
<>
|
||||
<UserStatistics />
|
||||
</>
|
||||
);
|
||||
|
||||
const buttons = (
|
||||
<>
|
||||
<BackButton />
|
||||
</>
|
||||
);
|
||||
|
||||
return <BasicWindow content={content} buttons={buttons} />;
|
||||
}
|
||||
export default UserNewTimeReportPage;
|
|
@ -1,10 +1,12 @@
|
|||
import BasicWindow from "../../Components/BasicWindow";
|
||||
import BackButton from "../../Components/BackButton";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useParams, Link } from "react-router-dom";
|
||||
import AllTimeReportsInProject from "../../Components/AllTimeReportsInProject";
|
||||
import Button from "../../Components/Button";
|
||||
|
||||
function UserViewTimeReportsPage(): JSX.Element {
|
||||
const { projectName } = useParams();
|
||||
const username = localStorage.getItem("username");
|
||||
|
||||
const content = (
|
||||
<>
|
||||
|
@ -17,6 +19,15 @@ function UserViewTimeReportsPage(): JSX.Element {
|
|||
|
||||
const buttons = (
|
||||
<>
|
||||
<Link to={`/viewStatistics/${projectName}/${username}`}>
|
||||
<Button
|
||||
text="Statistics"
|
||||
onClick={(): void => {
|
||||
return;
|
||||
}}
|
||||
type={"button"}
|
||||
/>
|
||||
</Link>
|
||||
<BackButton />
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -9,6 +9,7 @@ import AdminMenuPage from "./Pages/AdminPages/AdminMenuPage.tsx";
|
|||
import UserEditTimeReportPage from "./Pages/UserPages/UserEditTimeReportPage.tsx";
|
||||
import UserNewTimeReportPage from "./Pages/UserPages/UserNewTimeReportPage.tsx";
|
||||
import UserViewTimeReportsPage from "./Pages/UserPages/UserViewTimeReportsPage.tsx";
|
||||
import UserViewStatistics from "./Pages/UserPages/UserViewStatistics.tsx";
|
||||
import PMChangeRole from "./Pages/ProjectManagerPages/PMChangeRole.tsx";
|
||||
import PMOtherUsersTR from "./Pages/ProjectManagerPages/PMOtherUsersTR.tsx";
|
||||
import PMProjectMembers from "./Pages/ProjectManagerPages/PMProjectMembers.tsx";
|
||||
|
@ -54,9 +55,13 @@ const router = createBrowserRouter([
|
|||
element: <UserViewTimeReportsPage />,
|
||||
},
|
||||
{
|
||||
path: "/editTimeReport/:projectName/:fetchedWeek",
|
||||
path: "/editTimeReport/:projectName/:fetchedWeek/:signedOrUnsigned",
|
||||
element: <UserEditTimeReportPage />,
|
||||
},
|
||||
{
|
||||
path: "/viewStatistics/:projectName/:username",
|
||||
element: <UserViewStatistics />,
|
||||
},
|
||||
{
|
||||
path: "/changeRole/:projectName/:username",
|
||||
element: <PMChangeRole />,
|
||||
|
@ -66,7 +71,7 @@ const router = createBrowserRouter([
|
|||
element: <PMOtherUsersTR />,
|
||||
},
|
||||
{
|
||||
path: "/editOthersTR/:projectName/:username/:fetchedWeek",
|
||||
path: "/editOthersTR/:projectName/:username/:fetchedWeek/:signedOrUnsigned",
|
||||
element: <PMViewOtherUsersTR />,
|
||||
},
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue