diff --git a/backend/internal/database/db.go b/backend/internal/database/db.go index 12b0ee1..d444b85 100644 --- a/backend/internal/database/db.go +++ b/backend/internal/database/db.go @@ -47,8 +47,6 @@ type Database interface { GetUserName(id int) (string, error) UnsignWeeklyReport(reportId int, projectManagerId int) error DeleteReport(reportID int) error - ChangeProjectName(projectName string, newProjectName string) error - ChangeUserPassword(username string, password string) error } // This struct is a wrapper type that holds the database connection @@ -672,14 +670,3 @@ func (d *Db) DeleteReport(reportID int) error { _, err := d.Exec("DELETE FROM weekly_reports WHERE report_id = ?", reportID) return err } - -// ChangeProjectName is a handler that changes the name of a project -func (d *Db) ChangeProjectName(projectName string, newProjectName string) error { - _, err := d.Exec("UPDATE projects SET name = ? WHERE name = ?", newProjectName, projectName) - return err -} - -func (d *Db) ChangeUserPassword(username string, password string) error { - _, err := d.Exec("UPDATE users SET password = ? WHERE username = ?", password, username) - return err -} diff --git a/backend/internal/database/db_test.go b/backend/internal/database/db_test.go index 7b599f2..f24175a 100644 --- a/backend/internal/database/db_test.go +++ b/backend/internal/database/db_test.go @@ -1092,53 +1092,3 @@ func TestDeleteReport(t *testing.T) { } } - -func TestChangeProjectName(t *testing.T) { - db, err := setupAdvancedState() - if err != nil { - t.Error("setupState failed:", err) - } - - // Promote user to Admin - err = db.PromoteToAdmin("demouser") - if err != nil { - t.Error("PromoteToAdmin failed:", err) - } - - // Change project name - err = db.ChangeProjectName("projecttest", "newprojectname") - if err != nil { - t.Error("ChangeProjectName failed:", err) - } - - // Check if the project name was changed - projects, err := db.GetAllProjects() - if err != nil { - t.Error("GetAllProjects failed:", err) - } - if projects[0].Name != "newprojectname" { - t.Error("ChangeProjectName failed: expected newprojectname, got", projects[0].Name) - } -} - -func TestChangeUserPassword(t *testing.T) { - db, err := setupState() - if err != nil { - t.Error("setupState failed:", err) - } - - // Add a user - _ = db.AddUser("testuser", "password") - - // Change user password - err = db.ChangeUserPassword("testuser", "newpassword") - if err != nil { - t.Error("ChangeUserPassword failed:", err) - } - - // Check if the password was changed - if !db.CheckUser("testuser", "newpassword") { - t.Error("ChangeUserPassword failed: password not changed") - } - -} diff --git a/backend/internal/database/sample_data/0010_sample_data.sql b/backend/internal/database/sample_data/0010_sample_data.sql index f519608..70499b0 100644 --- a/backend/internal/database/sample_data/0010_sample_data.sql +++ b/backend/internal/database/sample_data/0010_sample_data.sql @@ -1,220 +1,58 @@ INSERT OR IGNORE INTO users(username, password) -VALUES ("admin", "123"), - ("user", "123"), - ("user2", "123"), - ("John", "123"), - ("Emma", "123"), - ("Michael", "123"), - ("Liam", "123"), - ("Oliver", "123"), - ("Amelia", "123"), - ("Benjamin", "123"), - ("Mia", "123"), - ("Elijah", "123"), - ("Charlotte", "123"), - ("Henry", "123"), - ("Harper", "123"), - ("Lucas", "123"), - ("Emily", "123"), - ("Alexander", "123"), - ("Daniel", "123"), - ("Ella", "123"), - ("Matthew", "123"), - ("Madison", "123"), - ("Samuel", "123"), - ("Avery", "123"), - ("Sofia", "123"), - ("David", "123"), - ("Victoria", "123"), - ("Jackson", "123"), - ("Abigail", "123"), - ("Gabriel", "123"), - ("Luna", "123"), - ("Wyatt", "123"), - ("Chloe", "123"), - ("Nora", "123"), - ("Joshua", "123"), - ("Hazel", "123"), - ("Riley", "123"), - ("Scarlett", "123"), - ("Aria", "123"), - ("Carter", "123"), - ("Grace", "123"), - ("Jayden", "123"), - ("Hannah", "123"), - ("Zoe", "123"), - ("Luke", "123"), - ("Sophia", "123"), - ("Jack", "123"), - ("Isabella", "123"), - ("William", "123"), - ("Mason", "123"), - ("Evelyn", "123"), - ("James", "123"), - ("Cynthia", "123"), - ("Abraham", "123"), - ("Ava", "123"), - ("Aiden", "123"), - ("Natalie", "123"), - ("Lily", "123"), - ("Olivia", "123"), - ("Alexander", "123"), - ("Ethan", "123"), - ("Mila", "123"), - ("Evelyn", "123"), - ("Logan", "123"), - ("Riley", "123"), - ("Grace", "123"), - ("Arnold", "123"), - ("Connor", "123"), - ("Samantha", "123"), - ("Emma", "123"), - ("Sarah", "123"), - ("Nathan", "123"), - ("Layla", "123"), - ("Ryan", "123"), - ("Zoey", "123"), - ("Megan", "123"), - ("Christian", "123"), - ("Eva", "123"), - ("Isaac", "123"), - ("Michaela", "123"), - ("Caroline", "123"), - ("Elijah", "123"), - ("Elena", "123"), - ("Julian", "123"), - ("Sophie", "123"), - ("Gabriella", "123"), - ("Cole", "123"), - ("Hannah", "123"), - ("Lucy", "123"), - ("Katherine", "123"), - ("Benjamin", "123"), - ("Ella", "123"), - ("Evan", "123"); +VALUES ("admin", "123"); -INSERT OR IGNORE INTO projects(name, description, owner_user_id) -VALUES ("projecttest1", "Description for projecttest1", 1), - ("projecttest2", "Description for projecttest2", 1), - ("projecttest3", "Description for projecttest3", 1), - ("projecttest4", "Description for projecttest4", 1), - ("projecttest5", "Description for projecttest5", 1), - ("projecttest6", "Description for projecttest6", 1), - ("projecttest7", "Description for projecttest7", 1), - ("projecttest8", "Description for projecttest8", 1), - ("projecttest9", "Description for projecttest9", 1), - ("projecttest10", "Description for projecttest10", 1), - ("projecttest11", "Description for projecttest11", 1), - ("projecttest12", "Description for projecttest12", 1), - ("projecttest13", "Description for projecttest13", 1), - ("projecttest14", "Description for projecttest14", 1), - ("projecttest15", "Description for projecttest15", 1); +INSERT OR IGNORE INTO users(username, password) +VALUES ("user", "123"); + +INSERT OR IGNORE INTO users(username, password) +VALUES ("user2", "123"); + +INSERT OR IGNORE INTO site_admin VALUES (1); + +INSERT OR IGNORE INTO projects(name,description,owner_user_id) +VALUES ("projecttest","test project", 1); + +INSERT OR IGNORE INTO projects(name,description,owner_user_id) +VALUES ("projecttest2","test project2", 1); + +INSERT OR IGNORE INTO projects(name,description,owner_user_id) +VALUES ("projecttest3","test project3", 1); INSERT OR IGNORE INTO user_roles(user_id,project_id,p_role) -VALUES (1,1,"project_manager"), - (1,2,"project_manager"), - (1,3,"project_manager"), - (1,4,"project_manager"), - (1,5,"project_manager"), - (1,6,"project_manager"), - (1,7,"project_manager"), - (1,8,"project_manager"), - (1,9,"project_manager"), - (1,10,"project_manager"), - (1,11,"project_manager"), - (1,12,"project_manager"), - (1,13,"project_manager"), - (1,14,"project_manager"), - (1,15,"project_manager"), - (2,1,"project_manager"), - (2,2,"member"), - (2,3,"member"), - (2,4,"member"), - (2,5,"member"), - (2,6,"member"), - (2,7,"member"), - (2,8,"member"), - (2,9,"member"), - (2,10,"member"), - (2,11,"member"), - (2,12,"member"), - (2,13,"member"), - (2,14,"member"), - (2,15,"member"), - (3,1,"member"), - (3,2,"member"), - (3,3,"member"), - (3,4,"member"), - (3,5,"member"), - (3,6,"member"), - (3,7,"member"), - (3,8,"member"), - (3,9,"member"), - (3,10,"member"), - (3,11,"member"), - (3,12,"member"), - (3,13,"member"), - (3,14,"member"), - (3,15,"member"), - (4,1,"member"), - (4,2,"member"), - (4,3,"member"), - (4,4,"member"), - (4,5,"member"), - (4,6,"member"), - (4,7,"member"), - (4,8,"member"), - (4,9,"member"), - (4,10,"member"), - (4,11,"member"), - (4,12,"member"), - (4,13,"member"), - (4,14,"member"), - (4,15,"member"), - (5,1,"member"), - (5,2,"member"), - (5,3,"member"), - (5,4,"member"), - (5,5,"member"), - (5,6,"member"), - (5,7,"member"), - (5,8,"member"), - (5,9,"member"), - (5,10,"member"), - (5,11,"member"), - (5,12,"member"), - (5,13,"member"), - (5,14,"member"), - (5,15,"member"); +VALUES (1,1,"project_manager"); + +INSERT OR IGNORE INTO user_roles(user_id,project_id,p_role) +VALUES (1,2,"project_manager"); + +INSERT OR IGNORE INTO user_roles(user_id,project_id,p_role) +VALUES (1,3,"project_manager"); + +INSERT OR IGNORE INTO user_roles(user_id,project_id,p_role) +VALUES (2,1,"member"); + +INSERT OR IGNORE INTO user_roles(user_id,project_id,p_role) +VALUES (3,1,"member"); + +INSERT OR IGNORE INTO user_roles(user_id,project_id,p_role) +VALUES (3,2,"member"); + +INSERT OR IGNORE INTO user_roles(user_id,project_id,p_role) +VALUES (3,3,"member"); + +INSERT OR IGNORE INTO user_roles(user_id,project_id,p_role) +VALUES (2,1,"project_manager"); INSERT OR IGNORE INTO weekly_reports (user_id, project_id, week, development_time, meeting_time, admin_time, own_work_time, study_time, testing_time, signed_by) -VALUES (2, 1, 12, 100, 50, 30, 150, 80, 20, NULL), - (3, 1, 12, 200, 80, 20, 200, 100, 30, NULL), - (3, 1, 14, 150, 70, 40, 180, 90, 25, NULL), - (3, 2, 12, 120, 60, 35, 160, 85, 15, NULL), - (3, 3, 12, 180, 90, 25, 190, 110, 40, NULL), - (2, 1, 13, 130, 70, 40, 170, 95, 35, NULL), - (3, 1, 15, 140, 60, 50, 200, 120, 30, NULL), - (2, 2, 11, 110, 50, 45, 140, 70, 25, NULL), - (3, 3, 14, 170, 80, 30, 180, 100, 35, NULL), - (3, 3, 15, 200, 100, 20, 220, 130, 45, NULL), - (2, 4, 12, 120, 60, 40, 160, 80, 30, NULL), - (3, 5, 14, 150, 70, 30, 180, 90, 25, NULL), - (3, 5, 15, 180, 90, 20, 190, 110, 35, NULL), - (2, 6, 11, 100, 50, 35, 130, 60, 20, NULL), - (3, 7, 14, 170, 80, 25, 180, 100, 30, NULL), - (2, 8, 12, 130, 70, 30, 170, 90, 25, NULL), - (2, 8, 13, 150, 80, 20, 180, 110, 35, NULL), - (3, 9, 12, 140, 60, 40, 180, 100, 30, NULL), - (3, 10, 11, 120, 50, 45, 150, 70, 25, NULL), - (2, 11, 13, 110, 60, 35, 140, 80, 30, NULL), - (3, 12, 12, 160, 70, 30, 180, 100, 35, NULL), - (3, 12, 13, 180, 90, 25, 190, 110, 40, NULL), - (3, 12, 14, 200, 100, 20, 220, 130, 45, NULL), - (2, 13, 11, 100, 50, 45, 130, 60, 20, NULL), - (2, 13, 12, 120, 60, 40, 160, 80, 30, NULL), - (3, 14, 13, 140, 70, 30, 160, 90, 35, NULL), - (3, 15, 12, 150, 80, 25, 180, 100, 30, NULL), - (3, 15, 13, 170, 90, 20, 190, 110, 35, NULL); +VALUES (2, 1, 12, 20, 10, 5, 30, 15, 10, NULL); -INSERT OR IGNORE INTO site_admin VALUES (1); \ No newline at end of file +INSERT OR IGNORE INTO weekly_reports (user_id, project_id, week, development_time, meeting_time, admin_time, own_work_time, study_time, testing_time, signed_by) +VALUES (3, 1, 12, 20, 10, 5, 30, 15, 10, NULL); + +INSERT OR IGNORE INTO weekly_reports (user_id, project_id, week, development_time, meeting_time, admin_time, own_work_time, study_time, testing_time, signed_by) +VALUES (3, 1, 14, 20, 10, 5, 30, 15, 10, NULL); + +INSERT OR IGNORE INTO weekly_reports (user_id, project_id, week, development_time, meeting_time, admin_time, own_work_time, study_time, testing_time, signed_by) +VALUES (3, 2, 12, 20, 10, 5, 30, 15, 10, NULL); + +INSERT OR IGNORE INTO weekly_reports (user_id, project_id, week, development_time, meeting_time, admin_time, own_work_time, study_time, testing_time, signed_by) +VALUES (3, 3, 12, 20, 10, 5, 30, 15, 10, NULL); diff --git a/backend/internal/handlers/projects/ChangeProjectName.go b/backend/internal/handlers/projects/ChangeProjectName.go deleted file mode 100644 index f6831db..0000000 --- a/backend/internal/handlers/projects/ChangeProjectName.go +++ /dev/null @@ -1,43 +0,0 @@ -package projects - -import ( - db "ttime/internal/database" - - "github.com/gofiber/fiber/v2" - "github.com/gofiber/fiber/v2/log" - "github.com/golang-jwt/jwt/v5" -) - -// ChangeProjectName is a handler that changes the name of a project -func ChangeProjectName(c *fiber.Ctx) error { - - //check token and get username of current user - user := c.Locals("user").(*jwt.Token) - claims := user.Claims.(jwt.MapClaims) - username := claims["name"].(string) - - // Extract the necessary parameters from the request - projectName := c.Params("projectName") - newProjectName := c.Query("newProjectName") - - // Check if user is site admin - issiteadmin, err := db.GetDb(c).IsSiteAdmin(username) - if err != nil { - log.Warn("Error checking if siteadmin:", err) - return c.Status(500).SendString(err.Error()) - } else if !issiteadmin { - log.Warn("User is not siteadmin") - return c.Status(401).SendString("User is not siteadmin") - } - - - // Perform the project name change - err = db.GetDb(c).ChangeProjectName(projectName, newProjectName) - if err != nil { - log.Warn("Error changing project name:", err) - return c.Status(500).SendString(err.Error()) - } - - // Return a success message - return c.Status(200).SendString("Project name changed successfully") -} diff --git a/backend/internal/handlers/reports/Statistics.go b/backend/internal/handlers/reports/Statistics.go index dac017d..8afa0f0 100644 --- a/backend/internal/handlers/reports/Statistics.go +++ b/backend/internal/handlers/reports/Statistics.go @@ -16,7 +16,6 @@ func GetStatistics(c *fiber.Ctx) error { // Extract project name from query parameters projectName := c.Query("projectName") - userNameParam := c.Query("userName") log.Info(username, " trying to get statistics for project: ", projectName) @@ -25,23 +24,18 @@ func GetStatistics(c *fiber.Ctx) error { return c.Status(400).SendString("Missing project name") } - // Check if the user is a project manager + // If the user is not a project manager, they can't view statistics pm, err := db.GetDb(c).IsProjectManager(username, projectName) if err != nil { log.Info("Error checking if user is project manager:", err) return c.Status(500).SendString(err.Error()) } - // Bail if the user is not a PM or checking its own statistics - if !pm && userNameParam != "" && userNameParam != username { - log.Info("Unauthorized access for user: ", username, "trying to access project: ", projectName, "statistics for user: ", userNameParam) + if !pm { + log.Info("Unauthorized access") return c.Status(403).SendString("Unauthorized access") } - if pm && userNameParam != "" { - username = userNameParam - } - // Retrieve statistics for the project from the database statistics, err := db.GetDb(c).ReportStatistics(username, projectName) if err != nil { diff --git a/backend/internal/handlers/users/ChangeUserPassword.go b/backend/internal/handlers/users/ChangeUserPassword.go deleted file mode 100644 index 1596247..0000000 --- a/backend/internal/handlers/users/ChangeUserPassword.go +++ /dev/null @@ -1,42 +0,0 @@ -package users - -import ( - db "ttime/internal/database" - - "github.com/gofiber/fiber/v2" - "github.com/gofiber/fiber/v2/log" - "github.com/golang-jwt/jwt/v5" -) - -// ChangeUserPassword is a handler that changes the password of a user -func ChangeUserPassword(c *fiber.Ctx) error { - - //Check token and get username of current user - user := c.Locals("user").(*jwt.Token) - claims := user.Claims.(jwt.MapClaims) - admin := claims["name"].(string) - - // Extract the necessary parameters from the request - username := c.Params("username") - newPassword := c.Query("newPassword") - - // Check if user is site admin - issiteadmin, err := db.GetDb(c).IsSiteAdmin(admin) - if err != nil { - log.Warn("Error checking if siteadmin:", err) - return c.Status(500).SendString(err.Error()) - } else if !issiteadmin { - log.Warn("User is not siteadmin") - return c.Status(401).SendString("User is not siteadmin") - } - - // Perform the password change - err = db.GetDb(c).ChangeUserPassword(username, newPassword) - if err != nil { - log.Warn("Error changing password:", err) - return c.Status(500).SendString(err.Error()) - } - - // Return a success message - return c.Status(200).SendString("Password changed successfully") -} diff --git a/backend/main.go b/backend/main.go index 0c66369..8a3466a 100644 --- a/backend/main.go +++ b/backend/main.go @@ -110,7 +110,6 @@ func main() { api.Post("/promoteToAdmin", users.PromoteToAdmin) api.Put("/changeUserName", users.ChangeUserName) api.Delete("/userdelete/:username", users.UserDelete) // Perhaps just use POST to avoid headaches - api.Put("/changeUserPassword/:username", users.ChangeUserPassword) // All project related routes // projectGroup := api.Group("/project") // Not currently in use @@ -126,7 +125,6 @@ func main() { api.Delete("/removeUserFromProject/:projectName", projects.RemoveUserFromProject) api.Delete("/removeProject/:projectName", projects.RemoveProject) api.Delete("/project/:projectID", projects.DeleteProject) - api.Put("/changeProjectName/:projectName", projects.ChangeProjectName) // All report related routes // reportGroup := api.Group("/report") // Not currently in use diff --git a/frontend/src/API/API.ts b/frontend/src/API/API.ts index 67768c2..eb9f3f0 100644 --- a/frontend/src/API/API.ts +++ b/frontend/src/API/API.ts @@ -269,32 +269,7 @@ interface API { getStatistics( projectName: string, token: string, - userName?: string, ): Promise>; - - /** - * Changes the name of a project - * @param {string} projectName The name of the project - * @param {string} newProjectName The new name of the project - * @param {string} token The authentication token - */ - changeProjectName( - projectName: string, - newProjectName: string, - token: string, - ): Promise>; - - /** - * Changes the password of a user - * @param {string} username The username of the user - * @param {string} newPassword The new password - * @param {string} token The authentication token - */ - changeUserPassword( - username: string, - newPassword: string, - token: string, - ): Promise>; } /** An instance of the API */ @@ -701,11 +676,7 @@ export const api: API = { }); if (!response.ok) { - return { - success: false, - data: `${response.status}`, - message: "Failed to login", - }; + return { success: false, message: "Failed to login" }; } else { const data = (await response.json()) as { token: string }; // Update the type of 'data' return { success: true, data: data.token }; @@ -1004,13 +975,12 @@ export const api: API = { } }, async getStatistics( - projectName: string, token: string, - userName?: string, + projectName: string, ): Promise> { try { const response = await fetch( - `/api/getStatistics/?projectName=${projectName}&userName=${userName ?? ""}`, + `/api/getStatistics/?projectName=${projectName}`, { method: "GET", headers: { @@ -1030,58 +1000,4 @@ export const api: API = { return { success: false, message: "Failed to get statistics" }; } }, - - async changeProjectName( - projectName: string, - newProjectName: string, - token: string, - ): Promise> { - try { - const response = await fetch( - `/api/changeProjectName/${projectName}?newProjectName=${newProjectName}`, - { - method: "PUT", - headers: { - "Content-Type": "application/json", - Authorization: "Bearer " + token, - }, - }, - ); - - if (!response.ok) { - return { success: false, message: "Failed to change project name" }; - } else { - return { success: true, message: "Project name changed" }; - } - } catch (e) { - return { success: false, message: "Failed to change project name" }; - } - }, - - async changeUserPassword( - username: string, - newPassword: string, - token: string, - ): Promise> { - try { - const response = await fetch( - `/api/changeUserPassword/${username}?newPassword=${newPassword}`, - { - method: "PUT", - headers: { - "Content-Type": "application/json", - Authorization: "Bearer " + token, - }, - }, - ); - - if (!response.ok) { - return { success: false, message: "Failed to change password" }; - } else { - return { success: true, message: "Password changed" }; - } - } catch (e) { - return { success: false, message: "Failed to change password" }; - } - }, }; diff --git a/frontend/src/Components/AddProject.tsx b/frontend/src/Components/AddProject.tsx index 8c9c566..c8a1c66 100644 --- a/frontend/src/Components/AddProject.tsx +++ b/frontend/src/Components/AddProject.tsx @@ -1,13 +1,9 @@ import { useState } from "react"; import { api } from "../API/API"; import { NewProject } from "../Types/goTypes"; +import InputField from "./InputField"; import Logo from "../assets/Logo.svg"; import Button from "./Button"; -import { useNavigate } from "react-router-dom"; -import ProjectNameInput from "./Inputs/ProjectNameInput"; -import DescriptionInput from "./Inputs/DescriptionInput"; -import { alphanumeric } from "../Data/regex"; -import { projNameHighLimit, projNameLowLimit } from "../Data/constants"; /** * Provides UI for adding a project to the system. @@ -16,26 +12,11 @@ import { projNameHighLimit, projNameLowLimit } from "../Data/constants"; function AddProject(): JSX.Element { const [name, setName] = useState(""); const [description, setDescription] = useState(""); - const navigate = useNavigate(); /** * Tries to add a project to the system */ const handleCreateProject = async (): Promise => { - if ( - !alphanumeric.test(name) || - name.length > projNameHighLimit || - name.length < projNameLowLimit - ) { - alert( - "Please provide valid project name: \n-Between 10-99 characters \n-No special characters (.-!?/*)", - ); - return; - } - if (description.length > projNameHighLimit) { - alert("Please provide valid description: \n-Max 100 characters"); - return; - } const project: NewProject = { name: name.replace(/ /g, ""), description: description.trim(), @@ -49,7 +30,6 @@ function AddProject(): JSX.Element { alert(`${project.name} added!`); setDescription(""); setName(""); - navigate("/admin"); } else { alert("Project not added, name could be taken"); console.error(response.message); @@ -64,7 +44,7 @@ function AddProject(): JSX.Element {
{ e.preventDefault(); void handleCreateProject(); @@ -72,29 +52,33 @@ function AddProject(): JSX.Element { > TTIME Logo

Create a new project

- { - e.preventDefault(); - setName(e.target.value); - }} - /> -
- { - e.preventDefault(); - setDescription(e.target.value); - }} - placeholder={"Description (Optional)"} - /> -
+
+ { + e.preventDefault(); + setName(e.target.value); + }} + /> + { + e.preventDefault(); + setDescription(e.target.value); + }} + /> +
+
diff --git a/frontend/src/Components/EditWeeklyReport.tsx b/frontend/src/Components/EditWeeklyReport.tsx index 5037a76..d56ee42 100644 --- a/frontend/src/Components/EditWeeklyReport.tsx +++ b/frontend/src/Components/EditWeeklyReport.tsx @@ -18,13 +18,12 @@ export default function GetWeeklyReport(): JSX.Element { const [testingTime, setTestingTime] = useState(0); const token = localStorage.getItem("accessToken") ?? ""; - const { projectName, fetchedWeek, signedOrUnsigned } = useParams<{ + const { projectName, fetchedWeek } = useParams<{ projectName: string; fetchedWeek: string; - signedOrUnsigned: string; }>(); const username = localStorage.getItem("userName") ?? ""; - console.log(projectName, fetchedWeek, signedOrUnsigned); + console.log(projectName, fetchedWeek); useEffect(() => { const fetchWeeklyReport = async (): Promise => { @@ -60,7 +59,7 @@ export default function GetWeeklyReport(): JSX.Element { }; void fetchWeeklyReport(); - }, [projectName, fetchedWeek, signedOrUnsigned, token]); + }, [projectName, fetchedWeek, token]); const handleUpdateWeeklyReport = async (): Promise => { const updateWeeklyReport: UpdateWeeklyReport = { @@ -140,12 +139,6 @@ export default function GetWeeklyReport(): JSX.Element { ) event.preventDefault(); }} - onClick={() => { - if (signedOrUnsigned === "signed") { - alert("You cannot edit a signed report."); - } - }} - readOnly={signedOrUnsigned === "signed"} /> @@ -175,12 +168,6 @@ export default function GetWeeklyReport(): JSX.Element { ) event.preventDefault(); }} - onClick={() => { - if (signedOrUnsigned === "signed") { - alert("You cannot edit a signed report."); - } - }} - readOnly={signedOrUnsigned === "signed"} /> @@ -210,12 +197,6 @@ export default function GetWeeklyReport(): JSX.Element { ) event.preventDefault(); }} - onClick={() => { - if (signedOrUnsigned === "signed") { - alert("You cannot edit a signed report."); - } - }} - readOnly={signedOrUnsigned === "signed"} /> @@ -245,12 +226,6 @@ export default function GetWeeklyReport(): JSX.Element { ) event.preventDefault(); }} - onClick={() => { - if (signedOrUnsigned === "signed") { - alert("You cannot edit a signed report."); - } - }} - readOnly={signedOrUnsigned === "signed"} /> @@ -280,12 +255,6 @@ export default function GetWeeklyReport(): JSX.Element { ) event.preventDefault(); }} - onClick={() => { - if (signedOrUnsigned === "signed") { - alert("You cannot edit a signed report."); - } - }} - readOnly={signedOrUnsigned === "signed"} /> @@ -315,26 +284,18 @@ export default function GetWeeklyReport(): JSX.Element { ) event.preventDefault(); }} - onClick={() => { - if (signedOrUnsigned === "signed") { - alert("You cannot edit a signed report."); - } - }} - readOnly={signedOrUnsigned === "signed"} /> - {signedOrUnsigned !== "signed" && ( -
diff --git a/frontend/src/Components/InputField.tsx b/frontend/src/Components/InputField.tsx index 5a5cdaf..699d8fa 100644 --- a/frontend/src/Components/InputField.tsx +++ b/frontend/src/Components/InputField.tsx @@ -4,21 +4,19 @@ * @returns {JSX.Element} The input field * @example * { * setExample(e.target.value); * }} + * value={example} * /> */ function InputField(props: { - label?: string; - placeholder?: string; - type?: string; - value?: string; - onChange?: (e: React.ChangeEvent) => void; + label: string; + type: string; + value: string; + onChange: (e: React.ChangeEvent) => void; }): JSX.Element { return (
@@ -32,7 +30,7 @@ function InputField(props: { className="appearance-none border-2 border-black rounded-2xl w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id={props.label} type={props.type} - placeholder={props.placeholder} + placeholder={props.label} value={props.value} onChange={props.onChange} /> diff --git a/frontend/src/Components/Inputs/DescriptionInput.tsx b/frontend/src/Components/Inputs/DescriptionInput.tsx deleted file mode 100644 index 43e046c..0000000 --- a/frontend/src/Components/Inputs/DescriptionInput.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { projDescHighLimit, projDescLowLimit } from "../../Data/constants"; - -export default function DescriptionInput(props: { - desc: string; - placeholder: string; - onChange: (e: React.ChangeEvent) => void; -}): JSX.Element { - return ( - <> - -
- {props.desc.length > projDescHighLimit && ( -

- Description must be under 100 characters -

- )} - {props.desc.length <= projDescHighLimit && - props.desc.length > projDescLowLimit && ( -

- Valid project description! -

- )} -
- - ); -} diff --git a/frontend/src/Components/Inputs/PasswordInput.tsx b/frontend/src/Components/Inputs/PasswordInput.tsx deleted file mode 100644 index 9f67e98..0000000 --- a/frontend/src/Components/Inputs/PasswordInput.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { passwordLength } from "../../Data/constants"; -import { lowercase } from "../../Data/regex"; - -export default function PasswordInput(props: { - password: string; - onChange: (e: React.ChangeEvent) => void; -}): JSX.Element { - const password = props.password; - return ( - <> - -
- {password.length === passwordLength && - lowercase.test(props.password) && ( -

- Valid password! -

- )} - {password.length !== passwordLength && ( -

- Password must be 6 characters -

- )} - {!lowercase.test(password) && password !== "" && ( -

- No number, uppercase or special
characters allowed -

- )} -
- - ); -} diff --git a/frontend/src/Components/Inputs/ProjectNameInput.tsx b/frontend/src/Components/Inputs/ProjectNameInput.tsx deleted file mode 100644 index de28c12..0000000 --- a/frontend/src/Components/Inputs/ProjectNameInput.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { projNameHighLimit, projNameLowLimit } from "../../Data/constants"; -import { alphanumeric } from "../../Data/regex"; - -export default function ProjectNameInput(props: { - name: string; - onChange: (e: React.ChangeEvent) => void; -}): JSX.Element { - const name = props.name; - return ( - <> - = projNameLowLimit && - name.length <= projNameHighLimit && - alphanumeric.test(name) - ? "border-2 border-green-500 dark:border-green-500 focus-visible:border-green-500 outline-none rounded-2xl w-full py-2 px-3 text-gray-700 leading-tight" - : "border-2 border-red-600 dark:border-red-600 focus:border-red-600 outline-none rounded-2xl w-full py-2 px-3 text-gray-700 leading-tight" - } - spellCheck="false" - id="New name" - type="text" - placeholder="Project name" - value={name} - onChange={props.onChange} - /> -
- {!alphanumeric.test(name) && name !== "" && ( -

- No special characters allowed -

- )} - {(name.length < projNameLowLimit || - name.length > projNameHighLimit) && ( -

- Project name must be 10-99 characters -

- )} - {alphanumeric.test(props.name) && - name.length >= projNameLowLimit && - name.length <= projNameHighLimit && ( -

- Valid project name! -

- )} -
- - ); -} diff --git a/frontend/src/Components/Inputs/UsernameInput.tsx b/frontend/src/Components/Inputs/UsernameInput.tsx deleted file mode 100644 index 8f653ba..0000000 --- a/frontend/src/Components/Inputs/UsernameInput.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { usernameLowLimit, usernameUpLimit } from "../../Data/constants"; -import { alphanumeric } from "../../Data/regex"; - -export default function UsernameInput(props: { - username: string; - onChange: (e: React.ChangeEvent) => void; -}): JSX.Element { - const username = props.username; - return ( - <> - = usernameLowLimit && - username.length <= usernameUpLimit && - alphanumeric.test(props.username) - ? "border-2 border-green-500 dark:border-green-500 focus-visible:border-green-500 outline-none rounded-2xl w-full py-2 px-3 text-gray-700 leading-tight" - : "border-2 border-red-600 dark:border-red-600 focus:border-red-600 outline-none rounded-2xl w-full py-2 px-3 text-gray-700 leading-tight" - } - spellCheck="false" - id="New username" - type="text" - placeholder="Username" - value={username} - onChange={props.onChange} - /> -
- {alphanumeric.test(username) && - username.length >= usernameLowLimit && - username.length <= usernameUpLimit && ( -

- Valid username! -

- )} - {!alphanumeric.test(username) && username !== "" && ( -

- No special characters allowed -

- )} - {!( - username.length >= usernameLowLimit && - username.length <= usernameUpLimit - ) && ( -

- Username must be 5-10 characters -

- )} -
- - ); -} diff --git a/frontend/src/Components/LoginCheck.tsx b/frontend/src/Components/LoginCheck.tsx index 50ffb98..f44d7f3 100644 --- a/frontend/src/Components/LoginCheck.tsx +++ b/frontend/src/Components/LoginCheck.tsx @@ -11,10 +11,6 @@ function LoginCheck(props: { password: string; setAuthority: Dispatch>; }): void { - if (props.username === "" || props.password === "") { - alert("Please enter username and password to login"); - return; - } const user: NewUser = { username: props.username, password: props.password, @@ -46,15 +42,7 @@ function LoginCheck(props: { console.error("Token was undefined"); } } else { - if (response.data === "500") { - console.error(response.message); - alert("No connection/Error"); - } else { - console.error( - "Token could not be fetched/No such user" + response.message, - ); - alert("Incorrect login information"); - } + console.error("Token could not be fetched/No such user"); } }) .catch((error) => { diff --git a/frontend/src/Components/LoginField.tsx b/frontend/src/Components/LoginField.tsx index 8d0aa62..dda1714 100644 --- a/frontend/src/Components/LoginField.tsx +++ b/frontend/src/Components/LoginField.tsx @@ -33,7 +33,6 @@ function Login(props: { props.setUsername(e.target.value); }} value={props.username} - placeholder={"Username"} />
- ); -} diff --git a/frontend/src/Components/OtherUsersTR.tsx b/frontend/src/Components/OtherUsersTR.tsx index 40e0b94..ce7761c 100644 --- a/frontend/src/Components/OtherUsersTR.tsx +++ b/frontend/src/Components/OtherUsersTR.tsx @@ -1,8 +1,7 @@ import { useState, useEffect } from "react"; import { WeeklyReport } from "../Types/goTypes"; import { api } from "../API/API"; -import { useParams, useNavigate } from "react-router-dom"; -import Button from "./Button"; +import { useParams } from "react-router-dom"; /** * Renders the component for editing a weekly report. @@ -18,14 +17,11 @@ 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 => { @@ -49,7 +45,6 @@ export default function OtherUsersTR(): JSX.Element { studyTime: 0, testingTime: 0, }; - setReportId(report.reportId); setWeek(report.week); setDevelopmentTime(report.developmentTime); setMeetingTime(report.meetingTime); @@ -65,27 +60,6 @@ export default function OtherUsersTR(): JSX.Element { void fetchUsersWeeklyReport(); }); - const handleUnsignWeeklyReport = async (): Promise => { - const response = await api.unsignReport(reportId, token); - console.log(response); - console.log(reportId); - if (response.success) { - return true; - } else { - return false; - } - }; - - const handleDeleteWeeklyReport = async (): Promise => { - const response = await api.deleteWeeklyReport(reportId, token); - console.log(response); - if (response.success) { - return true; - } - return false; - }; - const navigate = useNavigate(); - return ( <>

{username}'s Report

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

{projectName}

-

+

Your Time Reports

-

+

New Time Report

-

+

Statistics

-

+

Unsigned Time Reports

diff --git a/frontend/src/Components/ProjectInfoModal.tsx b/frontend/src/Components/ProjectInfoModal.tsx index 4be3397..1f98d79 100644 --- a/frontend/src/Components/ProjectInfoModal.tsx +++ b/frontend/src/Components/ProjectInfoModal.tsx @@ -4,62 +4,19 @@ import GetUsersInProject, { ProjectMember } from "./GetUsersInProject"; import { Link } from "react-router-dom"; import GetProjectTimes, { projectTimes } from "./GetProjectTimes"; import DeleteProject from "./DeleteProject"; -import InputField from "./InputField"; -import ProjectNameInput from "./Inputs/ProjectNameInput"; -import { alphanumeric } from "../Data/regex"; -import { projNameHighLimit, projNameLowLimit } from "../Data/constants"; -import ChangeProjectName from "./ChangeProjectName"; function ProjectInfoModal(props: { projectname: string; onClose: () => void; - onClick: (username: string, userRole: string) => void; + onClick: (username: string) => void; }): JSX.Element { - const [showInput, setShowInput] = useState(false); const [users, setUsers] = useState([]); const [times, setTimes] = useState(); - const [search, setSearch] = useState(""); - const [newProjName, setNewProjName] = useState(""); const totalTime = useRef(0); GetUsersInProject({ projectName: props.projectname, setUsersProp: setUsers }); GetProjectTimes({ setTimesProp: setTimes, projectName: props.projectname }); - const handleChangeNameView = (): void => { - if (showInput) { - setNewProjName(""); - setShowInput(false); - } else { - setShowInput(true); - } - }; - - const handleClickChangeName = (): void => { - if ( - newProjName.length > projNameHighLimit || - newProjName.length < projNameLowLimit || - !alphanumeric.test(newProjName) - ) { - alert( - "Please provide valid project name: \n-Between 10-99 characters \n-No special characters (.-!?/*)", - ); - return; - } - - if ( - confirm( - `Are you sure you want to change name of ${props.projectname} to ${newProjName}?`, - ) - ) { - ChangeProjectName({ - projectName: props.projectname, - newProjectName: newProjName, - }); - } else { - alert("Name was not changed!"); - } - }; - useEffect(() => { if (times?.totalTime !== undefined) { totalTime.current = times.totalTime; @@ -71,88 +28,44 @@ function ProjectInfoModal(props: { className="fixed inset-0 bg-black bg-opacity-30 backdrop-blur-sm flex justify-center items-center" > -
+
-

{props.projectname}

-

- (Change project name) -

- {showInput && ( - <> -

Change name:

-
- -
-
-
- - )} -

Statistics:

-
-

Number of members: {users.length}

-

+

+ {props.projectname} +

+
+

Statistics:

+
+
+

Number of members: {users.length}

+

Total time reported:{" "} {Math.floor(totalTime.current / 60 / 24) + " d "} {Math.floor((totalTime.current / 60) % 24) + " h "} {(totalTime.current % 60) + " m "}

-

Project members:

-
- { - setSearch(e.target.value); - }} - /> -
    - {users - .filter((user) => { - return search.toLowerCase() === "" - ? user.Username - : user.Username.toLowerCase().includes( - search.toLowerCase(), - ); - }) - .map((user) => ( -
  • { - props.onClick(user.Username, user.UserRole); - }} - > - - Name: {user.Username} -
    - Role: {user.UserRole} -
    -
  • - ))} +
    +

    Project members:

    +
    +
    +
      +
      + {users.map((user) => ( +
    • { + props.onClick(user.Username); + }} + > + + Name: {user.Username} +
      + Role: {user.UserRole} +
      +
    • + ))}
    diff --git a/frontend/src/Components/ProjectListAdmin.tsx b/frontend/src/Components/ProjectListAdmin.tsx index 6461dae..294a131 100644 --- a/frontend/src/Components/ProjectListAdmin.tsx +++ b/frontend/src/Components/ProjectListAdmin.tsx @@ -2,7 +2,6 @@ import { useState } from "react"; import { NewProject } from "../Types/goTypes"; import ProjectInfoModal from "./ProjectInfoModal"; import MemberInfoModal from "./MemberInfoModal"; -import InputField from "./InputField"; /** * A list of projects for admin manage projects page, that sets an onClick @@ -22,12 +21,9 @@ export function ProjectListAdmin(props: { const [projectName, setProjectName] = useState(""); const [userModalVisible, setUserModalVisible] = useState(false); const [username, setUsername] = useState(""); - const [userRole, setUserRole] = useState(""); - const [search, setSearch] = useState(""); - const handleClickUser = (username: string, userRole: string): void => { + const handleClickUser = (username: string): void => { setUsername(username); - setUserRole(userRole); setUserModalVisible(true); }; @@ -43,13 +39,11 @@ export function ProjectListAdmin(props: { const handleCloseUser = (): void => { setUsername(""); - setUserRole(""); setUserModalVisible(false); }; return ( <> -

    Manage Projects

    {projectModalVisible && ( )}
    - { - setSearch(e.target.value); - }} - /> -
      - {props.projects - .filter((project) => { - return search.toLowerCase() === "" - ? project.name - : project.name.toLowerCase().includes(search.toLowerCase()); - }) - .map((project) => ( -
    • { - handleClickProject(project.name); - }} - > - {project.name} -
    • - ))} +
        + {props.projects.map((project) => ( +
      • { + handleClickProject(project.name); + }} + > + {project.name} +
      • + ))}
    diff --git a/frontend/src/Components/ProjectMembers.tsx b/frontend/src/Components/ProjectMembers.tsx index e06ed75..52e8559 100644 --- a/frontend/src/Components/ProjectMembers.tsx +++ b/frontend/src/Components/ProjectMembers.tsx @@ -1,7 +1,6 @@ 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(); @@ -12,68 +11,34 @@ function ProjectMembers(): JSX.Element { setUsersProp: setProjectMembers, }); - const handleUserDeleteClick = async (username: string): Promise => { - const token = localStorage.getItem("accessToken") ?? ""; - const response = await api.removeUserFromProject( - username, - projectName ?? "", - token, - ); - console.log(response.data); - - // Remove the deleted user from the state - setProjectMembers((prevMembers) => - prevMembers.filter((member) => member.Username !== username), - ); - }; - return ( <>

    All Members In: {projectName}{" "}

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

    -
    -
    -

    {projectMember.Username}

    - Role: -

    {projectMember.UserRole}

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

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

    - )} - -

    - View Reports -

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

    +
    +
    +

    {projectMember.Username}

    + Role: +

    {projectMember.UserRole}

    +
    +
    +
    + +

    + View Reports +

    +
    -

    - ); - })} +
    +

    + ))}
    ); diff --git a/frontend/src/Components/Register.tsx b/frontend/src/Components/Register.tsx index 7310e4f..be35a74 100644 --- a/frontend/src/Components/Register.tsx +++ b/frontend/src/Components/Register.tsx @@ -3,44 +3,25 @@ import { NewUser } from "../Types/goTypes"; import { api } from "../API/API"; import Logo from "../assets/Logo.svg"; import Button from "./Button"; -import UsernameInput from "./Inputs/UsernameInput"; -import PasswordInput from "./Inputs/PasswordInput"; -import { alphanumeric, lowercase } from "../Data/regex"; -import { - passwordLength, - usernameLowLimit, - usernameUpLimit, -} from "../Data/constants"; +import InputField from "./InputField"; /** * Renders a registration form for the admin to add new users in. * @returns The JSX element representing the registration form. */ export default function Register(): JSX.Element { - const [username, setUsername] = useState(""); - const [password, setPassword] = useState(""); - const [errMessage, setErrMessage] = useState(""); + const [username, setUsername] = useState(); + const [password, setPassword] = useState(); + const [errMessage, setErrMessage] = useState(); const handleRegister = async (): Promise => { - if ( - username.length > usernameUpLimit || - username.length < usernameLowLimit || - !alphanumeric.test(username) - ) { - alert( - "Please provide valid username: \n-Between 5-10 characters \n-No special characters (.-!?/*)", - ); - return; - } - if (password.length !== passwordLength || !lowercase.test(password)) { - alert( - "Please provide valid password: \n-Exactly 6 characters \n-No uppercase letters \n-No numbers \n-No special characters (.-!?/*)", - ); + if (username === "" || password === "") { + alert("Must provide username and password"); return; } const newUser: NewUser = { - username: username, - password: password, + username: username?.replace(/ /g, "") ?? "", + password: password ?? "", }; const response = await api.registerUser(newUser); if (response.success) { @@ -58,7 +39,7 @@ export default function Register(): JSX.Element {
    { e.preventDefault(); void handleRegister(); @@ -66,28 +47,31 @@ export default function Register(): JSX.Element { > TTIME Logo

    Register New User

    - - { - setUsername(e.target.value); - }} - /> -
    - { - setPassword(e.target.value); - }} - /> - -
    +
    + { + setUsername(e.target.value); + }} + /> + { + setPassword(e.target.value); + }} + /> +
    +
    - )}

    Member of these projects:

    @@ -189,9 +87,7 @@ function UserInfoModal(props: { text={"Close"} onClick={function (): void { setNewUsername(""); - setNewPassword(""); - setShowNameInput(false); - setShowPwordInput(false); + setShowInput(false); props.onClose(); }} type="button" diff --git a/frontend/src/Components/UserListAdmin.tsx b/frontend/src/Components/UserListAdmin.tsx index 23e49db..76cae9f 100644 --- a/frontend/src/Components/UserListAdmin.tsx +++ b/frontend/src/Components/UserListAdmin.tsx @@ -1,6 +1,5 @@ import { useState } from "react"; import UserInfoModal from "./UserInfoModal"; -import InputField from "./InputField"; /** * A list of users for admin manage users page, that sets an onClick @@ -16,7 +15,6 @@ import InputField from "./InputField"; export function UserListAdmin(props: { users: string[] }): JSX.Element { const [modalVisible, setModalVisible] = useState(false); const [username, setUsername] = useState(""); - const [search, setSearch] = useState(""); const handleClick = (username: string): void => { setUsername(username); @@ -30,39 +28,24 @@ export function UserListAdmin(props: { users: string[] }): JSX.Element { return ( <> -

    Manage Users

    - { - setSearch(e.target.value); - }} - /> -
      - {props.users - .filter((user) => { - return search.toLowerCase() === "" - ? user - : user.toLowerCase().includes(search.toLowerCase()); - }) - .map((user) => ( -
    • { - handleClick(user); - }} - > - {user} -
    • - ))} +
        + {props.users.map((user) => ( +
      • { + handleClick(user); + }} + > + {user} +
      • + ))}
    diff --git a/frontend/src/Components/UserProjectListAdmin.tsx b/frontend/src/Components/UserProjectListAdmin.tsx index 8f28ce9..bc85c5b 100644 --- a/frontend/src/Components/UserProjectListAdmin.tsx +++ b/frontend/src/Components/UserProjectListAdmin.tsx @@ -8,7 +8,7 @@ function UserProjectListAdmin(props: { username: string }): JSX.Element { GetProjects({ setProjectsProp: setProjects, username: props.username }); return ( -
    +
      {projects.map((project) => (
    • diff --git a/frontend/src/Components/UserProjectMenu.tsx b/frontend/src/Components/UserProjectMenu.tsx index 4be4dee..e307e90 100644 --- a/frontend/src/Components/UserProjectMenu.tsx +++ b/frontend/src/Components/UserProjectMenu.tsx @@ -16,12 +16,12 @@ function UserProjectMenu(): JSX.Element {

      {projectName}

      -

      +

      Your Time Reports

      -

      +

      New Time Report

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

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

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

      {total}

      -
      -
      -
      - - ); -} diff --git a/frontend/src/Data/constants.ts b/frontend/src/Data/constants.ts deleted file mode 100644 index c803ad4..0000000 --- a/frontend/src/Data/constants.ts +++ /dev/null @@ -1,36 +0,0 @@ -//Different character limits certain strings - -/** - * Allowed character length for password - */ -export const passwordLength = 6; - -/** - * Lower limit for username length - */ -export const usernameLowLimit = 5; - -/** - * Upper limit for password length - */ -export const usernameUpLimit = 10; - -/** - * Lower limit for project name length - */ -export const projNameLowLimit = 10; - -/** - * Upper limit for project name length - */ -export const projNameHighLimit = 99; - -/** - * Upper limit for project description length - */ -export const projDescLowLimit = 0; - -/** - * Upper limit for project description length - */ -export const projDescHighLimit = 99; diff --git a/frontend/src/Data/regex.ts b/frontend/src/Data/regex.ts deleted file mode 100644 index ceb22cd..0000000 --- a/frontend/src/Data/regex.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Only alphanumerical characters - */ -export const alphanumeric = /^[a-zA-Z0-9]+$/; - -/** - * Only lowercase letters - */ -export const lowercase = /^[a-z]+$/; diff --git a/frontend/src/Pages/AdminPages/AdminManageProjects.tsx b/frontend/src/Pages/AdminPages/AdminManageProjects.tsx index 296dc59..6c03c01 100644 --- a/frontend/src/Pages/AdminPages/AdminManageProjects.tsx +++ b/frontend/src/Pages/AdminPages/AdminManageProjects.tsx @@ -1,11 +1,11 @@ import { Link } from "react-router-dom"; +import BackButton from "../../Components/BackButton"; import BasicWindow from "../../Components/BasicWindow"; import Button from "../../Components/Button"; import { ProjectListAdmin } from "../../Components/ProjectListAdmin"; import { Project } from "../../Types/goTypes"; import GetProjects from "../../Components/GetProjects"; import { useState } from "react"; -import NavButton from "../../Components/NavButton"; function AdminManageProjects(): JSX.Element { const [projects, setProjects] = useState([]); @@ -13,7 +13,14 @@ function AdminManageProjects(): JSX.Element { setProjectsProp: setProjects, username: localStorage.getItem("username") ?? "", }); - const content = ; + const content = ( + <> +

      Manage Projects

      +
      + +
      + + ); const buttons = ( <> @@ -26,7 +33,7 @@ function AdminManageProjects(): JSX.Element { type="button" /> - + ); diff --git a/frontend/src/Pages/AdminPages/AdminManageUsers.tsx b/frontend/src/Pages/AdminPages/AdminManageUsers.tsx index 1c34662..353fddc 100644 --- a/frontend/src/Pages/AdminPages/AdminManageUsers.tsx +++ b/frontend/src/Pages/AdminPages/AdminManageUsers.tsx @@ -12,7 +12,14 @@ function AdminManageUsers(): JSX.Element { const navigate = useNavigate(); - const content = ; + const content = ( + <> +

      Manage Users

      +
      + +
      + + ); const buttons = ( <> diff --git a/frontend/src/Pages/AdminPages/AdminMenuPage.tsx b/frontend/src/Pages/AdminPages/AdminMenuPage.tsx index 52a4198..ed2118d 100644 --- a/frontend/src/Pages/AdminPages/AdminMenuPage.tsx +++ b/frontend/src/Pages/AdminPages/AdminMenuPage.tsx @@ -5,14 +5,14 @@ function AdminMenuPage(): JSX.Element { const content = ( <>

      Administrator Menu

      -
      +
      -

      +

      Manage Users

      -

      +

      Manage Projects

      diff --git a/frontend/src/Pages/AdminPages/AdminProjectAddMember.tsx b/frontend/src/Pages/AdminPages/AdminProjectAddMember.tsx index e28c338..fa592c9 100644 --- a/frontend/src/Pages/AdminPages/AdminProjectAddMember.tsx +++ b/frontend/src/Pages/AdminPages/AdminProjectAddMember.tsx @@ -1,12 +1,11 @@ import { useLocation } from "react-router-dom"; import AddUserToProject from "../../Components/AddUserToProject"; import BasicWindow from "../../Components/BasicWindow"; -import BackButton from "../../Components/BackButton"; function AdminProjectAddMember(): JSX.Element { const projectName = useLocation().search.slice(1); const content = ; - const buttons = ; + const buttons = <>; return ; } export default AdminProjectAddMember; diff --git a/frontend/src/Pages/UserPages/UserViewStatistics.tsx b/frontend/src/Pages/AdminPages/AdminProjectStatistics.tsx similarity index 52% rename from frontend/src/Pages/UserPages/UserViewStatistics.tsx rename to frontend/src/Pages/AdminPages/AdminProjectStatistics.tsx index afa4763..0110d65 100644 --- a/frontend/src/Pages/UserPages/UserViewStatistics.tsx +++ b/frontend/src/Pages/AdminPages/AdminProjectStatistics.tsx @@ -1,13 +1,8 @@ import BackButton from "../../Components/BackButton"; import BasicWindow from "../../Components/BasicWindow"; -import UserStatistics from "../../Components/UserStatistics"; -function UserNewTimeReportPage(): JSX.Element { - const content = ( - <> - - - ); +function AdminProjectStatistics(): JSX.Element { + const content = <>; const buttons = ( <> @@ -17,4 +12,4 @@ function UserNewTimeReportPage(): JSX.Element { return ; } -export default UserNewTimeReportPage; +export default AdminProjectStatistics; diff --git a/frontend/src/Pages/ProjectManagerPages/PMOtherUsersTR.tsx b/frontend/src/Pages/ProjectManagerPages/PMOtherUsersTR.tsx index b586b64..cb558b0 100644 --- a/frontend/src/Pages/ProjectManagerPages/PMOtherUsersTR.tsx +++ b/frontend/src/Pages/ProjectManagerPages/PMOtherUsersTR.tsx @@ -1,12 +1,8 @@ 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 = ( <> @@ -15,15 +11,6 @@ function PMOtherUsersTR(): JSX.Element { const buttons = ( <> - -