diff --git a/backend/internal/handlers/global_state.go b/backend/internal/handlers/global_state.go index 932451d..566d549 100644 --- a/backend/internal/handlers/global_state.go +++ b/backend/internal/handlers/global_state.go @@ -34,17 +34,29 @@ type GlobalState interface { // UpdateCollection(c *fiber.Ctx) error // To update a collection // DeleteCollection(c *fiber.Ctx) error // To delete a collection // SignCollection(c *fiber.Ctx) error // To sign a collection - ListAllUsers(c *fiber.Ctx) error // To get a list of all users in the application database - ListAllUsersProject(c *fiber.Ctx) error // To get a list of all users for a specific project - ProjectRoleChange(c *fiber.Ctx) error // To change a users role in a project + GetButtonCount(c *fiber.Ctx) error // For demonstration purposes + IncrementButtonCount(c *fiber.Ctx) error // For demonstration purposes + ListAllUsers(c *fiber.Ctx) error // To get a list of all users in the application database + ListAllUsersProject(c *fiber.Ctx) error // To get a list of all users for a specific project + ProjectRoleChange(c *fiber.Ctx) error // To change a users role in a project } // "Constructor" func NewGlobalState(db database.Database) GlobalState { - return &GState{Db: db} + return &GState{Db: db, ButtonCount: 0} } // The global state, which implements all the handlers type GState struct { - Db database.Database + Db database.Database + ButtonCount int +} + +func (gs *GState) GetButtonCount(c *fiber.Ctx) error { + return c.Status(200).JSON(fiber.Map{"pressCount": gs.ButtonCount}) +} + +func (gs *GState) IncrementButtonCount(c *fiber.Ctx) error { + gs.ButtonCount++ + return c.Status(200).JSON(fiber.Map{"pressCount": gs.ButtonCount}) } diff --git a/backend/main.go b/backend/main.go index da89043..3e2fb75 100644 --- a/backend/main.go +++ b/backend/main.go @@ -61,6 +61,11 @@ func main() { // Register our unprotected routes server.Post("/api/register", gs.Register) + + // Register handlers for example button count + server.Get("/api/button", gs.GetButtonCount) + server.Post("/api/button", gs.IncrementButtonCount) + server.Post("/api/login", gs.Login) // Every route from here on will require a valid JWT @@ -68,7 +73,6 @@ func main() { SigningKey: jwtware.SigningKey{Key: []byte("secret")}, })) - // Protected routes (require a valid JWT bearer token authentication header) server.Post("/api/submitReport", gs.SubmitWeeklyReport) server.Get("/api/getUserProjects", gs.GetUserProjects) server.Post("/api/loginrenew", gs.LoginRenew) diff --git a/frontend/src/API/API.ts b/frontend/src/API/API.ts index 6078513..e8566b6 100644 --- a/frontend/src/API/API.ts +++ b/frontend/src/API/API.ts @@ -46,7 +46,6 @@ interface API { username: string, token: string, ): Promise>; - /** Gets a project from id*/ getProject(id: number): Promise>; } @@ -150,10 +149,7 @@ export const api: API = { } }, - async getUserProjects( - username: string, - token: string, - ): Promise> { + async getUserProjects(token: string): Promise> { try { const response = await fetch("/api/getUserProjects", { method: "GET", @@ -161,7 +157,6 @@ export const api: API = { "Content-Type": "application/json", Authorization: "Bearer " + token, }, - body: JSON.stringify({ username }), }); if (!response.ok) { diff --git a/frontend/src/Components/AddProject.tsx b/frontend/src/Components/AddProject.tsx deleted file mode 100644 index 45814e3..0000000 --- a/frontend/src/Components/AddProject.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { useState } from "react"; -import { APIResponse, api } from "../API/API"; -import { NewProject, Project } from "../Types/goTypes"; -import InputField from "./InputField"; -import Logo from "../assets/Logo.svg"; -import Button from "./Button"; - -/** - * Tries to add a project to the system - * @param props - Project name and description - * @returns {boolean} True if created, false if not - */ -function CreateProject(props: { name: string; description: string }): boolean { - const project: NewProject = { - name: props.name, - description: props.description, - }; - - let created = false; - - api - .createProject(project, localStorage.getItem("accessToken") ?? "") - .then((response: APIResponse) => { - if (response.success) { - created = true; - } else { - console.error(response.message); - } - }) - .catch((error) => { - console.error("An error occurred during creation:", error); - }); - return created; -} - -/** - * Tries to add a project to the system - * @returns {JSX.Element} UI for project adding - */ -function AddProject(): JSX.Element { - const [name, setName] = useState(""); - const [description, setDescription] = useState(""); - - return ( -
-
-
{ - e.preventDefault(); - CreateProject({ name: name, description: description }); - }} - > - TTIME Logo -

- Create a new project -

- { - setName(e.target.value); - }} - /> - { - setDescription(e.target.value); - }} - /> -
-
- -

-
-
- ); -} - -export default AddProject; diff --git a/frontend/src/Components/BasicWindow.tsx b/frontend/src/Components/BasicWindow.tsx index d5fd3b6..1835d6a 100644 --- a/frontend/src/Components/BasicWindow.tsx +++ b/frontend/src/Components/BasicWindow.tsx @@ -2,15 +2,17 @@ import Header from "./Header"; import Footer from "./Footer"; function BasicWindow({ + username, content, buttons, }: { + username: string; content: React.ReactNode; buttons: React.ReactNode; }): JSX.Element { return (
-
+
{content}
{buttons}
diff --git a/frontend/src/Components/EditWeeklyReport.tsx b/frontend/src/Components/EditWeeklyReport.tsx deleted file mode 100644 index b0e8771..0000000 --- a/frontend/src/Components/EditWeeklyReport.tsx +++ /dev/null @@ -1,247 +0,0 @@ -import { useState, useEffect } from "react"; -import { NewWeeklyReport } from "../Types/goTypes"; -import { api } from "../API/API"; -import { useNavigate } from "react-router-dom"; -import Button from "./Button"; - -export default function GetWeeklyReport(): JSX.Element { - const [projectName, setProjectName] = useState(""); - 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 username = localStorage.getItem("username") ?? ""; - - useEffect(() => { - const fetchWeeklyReport = async (): Promise => { - const response = await api.getWeeklyReport( - username, - projectName, - week.toString(), - token, - ); - - if (response.success) { - const report: NewWeeklyReport = response.data ?? { - projectName: "", - week: 0, - developmentTime: 0, - meetingTime: 0, - adminTime: 0, - ownWorkTime: 0, - studyTime: 0, - testingTime: 0, - }; - setProjectName(report.projectName); - 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 fetchWeeklyReport(); - }, [projectName, token, username, week]); - - const handleNewWeeklyReport = async (): Promise => { - const newWeeklyReport: NewWeeklyReport = { - projectName, - week, - developmentTime, - meetingTime, - adminTime, - ownWorkTime, - studyTime, - testingTime, - }; - - await api.submitWeeklyReport(newWeeklyReport, token); - }; - - const navigate = useNavigate(); - - return ( - <> -
-
{ - if (week === 0) { - alert("Please enter a week number"); - e.preventDefault(); - return; - } - e.preventDefault(); - void handleNewWeeklyReport(); - navigate("/project"); - }} - > -
- { - const weekNumber = parseInt(e.target.value.split("-W")[1]); - setWeek(weekNumber); - }} - onKeyDown={(event) => { - event.preventDefault(); - }} - onPaste={(event) => { - event.preventDefault(); - }} - /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Activity - - Total Time (min) -
Development - { - setDevelopmentTime(parseInt(e.target.value)); - }} - onKeyDown={(event) => { - const keyValue = event.key; - if (!/\d/.test(keyValue) && keyValue !== "Backspace") - event.preventDefault(); - }} - /> -
Meeting - { - setMeetingTime(parseInt(e.target.value)); - }} - onKeyDown={(event) => { - const keyValue = event.key; - if (!/\d/.test(keyValue) && keyValue !== "Backspace") - event.preventDefault(); - }} - /> -
Administration - { - setAdminTime(parseInt(e.target.value)); - }} - onKeyDown={(event) => { - const keyValue = event.key; - if (!/\d/.test(keyValue) && keyValue !== "Backspace") - event.preventDefault(); - }} - /> -
Own Work - { - setOwnWorkTime(parseInt(e.target.value)); - }} - onKeyDown={(event) => { - const keyValue = event.key; - if (!/\d/.test(keyValue) && keyValue !== "Backspace") - event.preventDefault(); - }} - /> -
Studies - { - setStudyTime(parseInt(e.target.value)); - }} - onKeyDown={(event) => { - const keyValue = event.key; - if (!/\d/.test(keyValue) && keyValue !== "Backspace") - event.preventDefault(); - }} - /> -
Testing - { - setTestingTime(parseInt(e.target.value)); - }} - onKeyDown={(event) => { - const keyValue = event.key; - if (!/\d/.test(keyValue) && keyValue !== "Backspace") - event.preventDefault(); - }} - /> -
-
-
-
- - ); -} diff --git a/frontend/src/Components/Header.tsx b/frontend/src/Components/Header.tsx index 819c5de..ba0a939 100644 --- a/frontend/src/Components/Header.tsx +++ b/frontend/src/Components/Header.tsx @@ -1,11 +1,11 @@ import { useState } from "react"; import { Link } from "react-router-dom"; -function Header(): JSX.Element { +function Header({ username }: { username: string }): JSX.Element { const [isOpen, setIsOpen] = useState(false); const handleLogout = (): void => { - localStorage.clear(); + // Add any logout logic here }; return ( @@ -31,7 +31,7 @@ function Header(): JSX.Element { }} > {isOpen && ( diff --git a/frontend/src/Components/LoginCheck.tsx b/frontend/src/Components/LoginCheck.tsx index ce7d52c..3658cbf 100644 --- a/frontend/src/Components/LoginCheck.tsx +++ b/frontend/src/Components/LoginCheck.tsx @@ -10,22 +10,17 @@ function LoginCheck(props: { username: string; password: string; setAuthority: Dispatch>; -}): void { +}): number { const user: NewUser = { username: props.username, password: props.password, }; - - localStorage.clear(); - api .login(user) .then((response: APIResponse) => { if (response.success) { if (response.data !== undefined) { const token = response.data; - localStorage.setItem("accessToken", token); - localStorage.setItem("username", props.username); //TODO: change so that it checks for user type (admin, user, pm) instead if (token !== "" && props.username === "admin") { props.setAuthority((prevAuth) => { @@ -47,12 +42,14 @@ function LoginCheck(props: { console.error("Token was undefined"); } } else { - console.error("Token could not be fetched/No such user"); + console.error("Token could not be fetched"); } }) .catch((error) => { console.error("An error occurred during login:", error); }); + + return 0; } export default LoginCheck; diff --git a/frontend/src/Components/Register.tsx b/frontend/src/Components/Register.tsx index facca39..af77d36 100644 --- a/frontend/src/Components/Register.tsx +++ b/frontend/src/Components/Register.tsx @@ -3,9 +3,34 @@ import { NewUser } from "../Types/goTypes"; import { api } from "../API/API"; import Logo from "../assets/Logo.svg"; import Button from "./Button"; -import InputField from "./InputField"; import { useNavigate } from "react-router-dom"; +function InputField(props: { + label: string; + type: string; + value: string; + onChange: (e: React.ChangeEvent) => void; +}): JSX.Element { + return ( +
+ + +
+ ); +} + export default function Register(): JSX.Element { const [username, setUsername] = useState(); const [password, setPassword] = useState(); @@ -23,7 +48,6 @@ export default function Register(): JSX.Element { nav("/"); // Instantly navigate to the login page } else { setErrMessage(response.message ?? "Unknown error"); - console.error(errMessage); } }; @@ -61,6 +85,43 @@ export default function Register(): JSX.Element { setPassword(e.target.value); }} /> +
+ + { + setUsername(e.target.value); + }} + /> +
+
+ + { + setPassword(e.target.value); + }} + /> +
+ {errMessage &&

{errMessage}

}