diff --git a/Justfile b/Justfile index cb905e4..432fbd1 100644 --- a/Justfile +++ b/Justfile @@ -15,7 +15,7 @@ remove-podman-containers: # Saves the release container to a tarball, pigz is just gzip but multithreaded save-release: build-container-release - podman save --format=oci-archive ttime-server | pigz -9 > ttime-server_`date -I`_`git rev-parse --short HEAD`.tar.gz + podman save --format=oci-archive ttime-server | pigz -9 > ttime-server.tar.gz # Loads the release container from a tarball load-release file: diff --git a/backend/internal/database/db.go b/backend/internal/database/db.go index bc6e1e8..ad408a7 100644 --- a/backend/internal/database/db.go +++ b/backend/internal/database/db.go @@ -204,22 +204,15 @@ func (d *Db) AddProject(name string, description string, username string) error tx := d.MustBegin() _, err := tx.Exec(projectInsert, name, description, username) if err != nil { - if err := tx.Rollback(); err != nil { - return err - } + tx.Rollback() return err } _, err = tx.Exec(changeUserRole, "project_manager", username, name) if err != nil { - if err := tx.Rollback(); err != nil { - return err - } + tx.Rollback() return err } - if err := tx.Commit(); err != nil { - return err - } - + tx.Commit() return err } diff --git a/frontend/src/API/API.ts b/frontend/src/API/API.ts index 8fd66d3..6078513 100644 --- a/frontend/src/API/API.ts +++ b/frontend/src/API/API.ts @@ -42,7 +42,10 @@ interface API { token: string, ): Promise>; /** Gets all the projects of a user*/ - getUserProjects(token: string): Promise>; + getUserProjects( + username: string, + token: string, + ): Promise>; /** Gets a project from id*/ getProject(id: number): Promise>; } @@ -147,7 +150,10 @@ export const api: API = { } }, - async getUserProjects(token: string): Promise> { + async getUserProjects( + username: string, + token: string, + ): Promise> { try { const response = await fetch("/api/getUserProjects", { method: "GET", @@ -155,6 +161,7 @@ export const api: API = { "Content-Type": "application/json", Authorization: "Bearer " + token, }, + body: JSON.stringify({ username }), }); if (!response.ok) { @@ -169,7 +176,7 @@ export const api: API = { } catch (e) { return Promise.resolve({ success: false, - message: "API fucked", + message: "Failed to get user projects", }); } }, diff --git a/frontend/src/Components/AdminUserList.tsx b/frontend/src/Components/AdminUserList.tsx deleted file mode 100644 index e69de29..0000000 diff --git a/frontend/src/Components/DeleteUser.tsx b/frontend/src/Components/DeleteUser.tsx deleted file mode 100644 index db49724..0000000 --- a/frontend/src/Components/DeleteUser.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { User } from "../Types/goTypes"; -import { api, APIResponse } from "../API/API"; - -/** - * Use to remove a user from the system - * @param props - The username of user to remove - * @returns {boolean} True if removed, false if not - * @example - * const exampleUsername = "user"; - * DeleteUser({ usernameToDelete: exampleUsername }); - */ - -function DeleteUser(props: { usernameToDelete: string }): boolean { - //console.log(props.usernameToDelete); FOR DEBUG - let removed = false; - api - .removeUser( - props.usernameToDelete, - localStorage.getItem("accessToken") ?? "", - ) - .then((response: APIResponse) => { - if (response.success) { - removed = true; - } else { - console.error(response.message); - } - }) - .catch((error) => { - console.error("An error occurred during creation:", error); - }); - return removed; -} - -export default DeleteUser; diff --git a/frontend/src/Components/Header.tsx b/frontend/src/Components/Header.tsx index 5cdb421..819c5de 100644 --- a/frontend/src/Components/Header.tsx +++ b/frontend/src/Components/Header.tsx @@ -1,6 +1,5 @@ import { useState } from "react"; import { Link } from "react-router-dom"; -import backgroundImage from "../assets/1.jpg"; function Header(): JSX.Element { const [isOpen, setIsOpen] = useState(false); @@ -12,7 +11,7 @@ function Header(): JSX.Element { return (
(); - const [developmentTime, setDevelopmentTime] = useState(); - const [meetingTime, setMeetingTime] = useState(); - const [adminTime, setAdminTime] = useState(); - const [ownWorkTime, setOwnWorkTime] = useState(); - const [studyTime, setStudyTime] = useState(); - const [testingTime, setTestingTime] = 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 { projectName } = useParams(); + const projectName = useContext(ProjectNameContext); const token = localStorage.getItem("accessToken") ?? ""; const handleNewWeeklyReport = async (): Promise => { const newWeeklyReport: NewWeeklyReport = { - projectName: projectName ?? "", - week: week ?? 0, - developmentTime: developmentTime ?? 0, - meetingTime: meetingTime ?? 0, - adminTime: adminTime ?? 0, - ownWorkTime: ownWorkTime ?? 0, - studyTime: studyTime ?? 0, - testingTime: testingTime ?? 0, + projectName, + week, + developmentTime, + meetingTime, + adminTime, + ownWorkTime, + studyTime, + testingTime, }; await api.submitWeeklyReport(newWeeklyReport, token); @@ -58,9 +59,7 @@ export default function NewWeeklyReport(): JSX.Element { setWeek(weekNumber); }} onKeyDown={(event) => { - const keyValue = event.key; - if (!/\d/.test(keyValue) && keyValue !== "Backspace") - event.preventDefault(); + event.preventDefault(); }} onPaste={(event) => { event.preventDefault(); diff --git a/frontend/src/Components/UserInfoModal.tsx b/frontend/src/Components/UserInfoModal.tsx deleted file mode 100644 index a22ef01..0000000 --- a/frontend/src/Components/UserInfoModal.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { Link } from "react-router-dom"; -import Button from "./Button"; -import DeleteUser from "./DeleteUser"; -import UserProjectListAdmin from "./UserProjectListAdmin"; - -function UserInfoModal(props: { - isVisible: boolean; - username: string; - onClose: () => void; -}): JSX.Element { - if (!props.isVisible) return <>; - - return ( -
-
-

{props.username}

- -

- (Change Username) -

- -
-

- Member of these projects: -

-
- -
-
-
-
-
-
- ); -} - -export default UserInfoModal; diff --git a/frontend/src/Components/UserListAdmin.tsx b/frontend/src/Components/UserListAdmin.tsx index 3d2bcae..b86076a 100644 --- a/frontend/src/Components/UserListAdmin.tsx +++ b/frontend/src/Components/UserListAdmin.tsx @@ -1,6 +1,5 @@ -import { useState } from "react"; +import { Link } from "react-router-dom"; import { PublicUser } from "../Types/goTypes"; -import UserInfoModal from "./UserInfoModal"; /** * The props for the UserProps component @@ -10,52 +9,27 @@ interface UserProps { } /** - * A list of users for admin manage users page, that sets an onClick - * function for eact user
  • element, which displays a modul with - * user info. - * @param props - An array of users users to display + * A list of users for admin manage users page, that links admin to the right user page + * thanks to the state property + * @param props - The users to display * @returns {JSX.Element} The user list * @example - * const users = [{ id: 1, userName: "ExampleName" }]; + * const users = [{ id: 1, userName: "Random name" }]; * return ; */ export function UserListAdmin(props: UserProps): JSX.Element { - const [modalVisible, setModalVisible] = useState(false); - const [username, setUsername] = useState(""); - - const handleClick = (username: string): void => { - setUsername(username); - setModalVisible(true); - }; - - const handleClose = (): void => { - setUsername(""); - setModalVisible(false); - }; - return ( - <> - -
    -
      - {props.users.map((user) => ( -
    • { - handleClick(user.username); - }} - > +
      +
        + {props.users.map((user) => ( + +
      • {user.username}
      • - ))} -
      -
      - + + ))} +
    +
    ); } diff --git a/frontend/src/Components/UserProjectListAdmin.tsx b/frontend/src/Components/UserProjectListAdmin.tsx index 1b7b923..69258a1 100644 --- a/frontend/src/Components/UserProjectListAdmin.tsx +++ b/frontend/src/Components/UserProjectListAdmin.tsx @@ -1,17 +1,17 @@ -import { useEffect, useState } from "react"; +import React, { useEffect, useState } from "react"; import { api } from "../API/API"; import { Project } from "../Types/goTypes"; -function UserProjectListAdmin(): JSX.Element { +const UserProjectListAdmin: React.FC = () => { const [projects, setProjects] = useState([]); useEffect(() => { const fetchProjects = async (): Promise => { try { const token = localStorage.getItem("accessToken") ?? ""; - // const username = props.username; + const username = "NoUser"; // getUsernameFromContext(); // Assuming you have a function to get the username from your context - const response = await api.getUserProjects(token); + const response = await api.getUserProjects(username, token); if (response.success) { setProjects(response.data ?? []); } else { @@ -26,16 +26,18 @@ function UserProjectListAdmin(): JSX.Element { }, []); return ( -
    +
    +

    User Projects

      {projects.map((project) => (
    • {project.name} + {/* Add any additional project details you want to display */}
    • ))}
    ); -} +}; export default UserProjectListAdmin; diff --git a/frontend/src/Pages/AdminPages/AdminChangeUsername.tsx b/frontend/src/Pages/AdminPages/AdminChangeUsername.tsx index 7eb2e2e..1756433 100644 --- a/frontend/src/Pages/AdminPages/AdminChangeUsername.tsx +++ b/frontend/src/Pages/AdminPages/AdminChangeUsername.tsx @@ -1,4 +1,3 @@ -import BackButton from "../../Components/BackButton"; import BasicWindow from "../../Components/BasicWindow"; import Button from "../../Components/Button"; @@ -14,7 +13,13 @@ function AdminChangeUsername(): JSX.Element { }} type="button" /> - +
    - ); -} diff --git a/frontend/src/Pages/UserPages/UserProjectPage.tsx b/frontend/src/Pages/UserPages/UserProjectPage.tsx index 80a0035..20fe6d7 100644 --- a/frontend/src/Pages/UserPages/UserProjectPage.tsx +++ b/frontend/src/Pages/UserPages/UserProjectPage.tsx @@ -1,20 +1,18 @@ -import { Link, useLocation, useParams } from "react-router-dom"; +import { Link, useLocation } from "react-router-dom"; import BasicWindow from "../../Components/BasicWindow"; import BackButton from "../../Components/BackButton"; function UserProjectPage(): JSX.Element { - const { projectName } = useParams(); - const content = ( <>

    {useLocation().state}

    - +

    Your Time Reports

    - +

    New Time Report

    diff --git a/frontend/src/Pages/YourProjectsPage.tsx b/frontend/src/Pages/YourProjectsPage.tsx index a3cd47a..32ba0ed 100644 --- a/frontend/src/Pages/YourProjectsPage.tsx +++ b/frontend/src/Pages/YourProjectsPage.tsx @@ -11,8 +11,9 @@ function UserProjectPage(): JSX.Element { const [selectedProject, setSelectedProject] = useState(""); const getProjects = async (): Promise => { - const token = localStorage.getItem("accessToken") ?? ""; - const response = await api.getUserProjects(token); + const username = localStorage.getItem("username") ?? ""; // replace with actual username + const token = localStorage.getItem("accessToken") ?? ""; // replace with actual token + const response = await api.getUserProjects(username, token); console.log(response); if (response.success) { setProjects(response.data ?? []); @@ -35,7 +36,7 @@ function UserProjectPage(): JSX.Element {
    {projects.map((project, index) => ( { handleProjectClick(project.name); }} diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 1c39ae9..193b692 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -29,14 +29,12 @@ import AdminProjectManageMembers from "./Pages/AdminPages/AdminProjectManageMemb import AdminProjectStatistics from "./Pages/AdminPages/AdminProjectStatistics.tsx"; import AdminProjectViewMemberInfo from "./Pages/AdminPages/AdminProjectViewMemberInfo.tsx"; import AdminProjectPage from "./Pages/AdminPages/AdminProjectPage.tsx"; -import NotFoundPage from "./Pages/NotFoundPage.tsx"; // This is where the routes are mounted const router = createBrowserRouter([ { path: "/", element: , - errorElement: , }, { path: "/admin", @@ -46,25 +44,29 @@ const router = createBrowserRouter([ path: "/pm", element: , }, + { + path: "/user", + element: , + }, { path: "/yourProjects", element: , }, { - path: "/project/:projectName", - element: , + path: "/editTimeReport", + element: , }, { - path: "/newTimeReport/:projectName", + path: "/newTimeReport", element: , }, { - path: "/projectPage/:projectName", - element: , + path: "/project", + element: , }, { - path: "/editTimeReport", - element: , + path: "/projectPage", + element: , }, { path: "/changeRole",