Merge branch 'frontend' into gruppDM

This commit is contained in:
Davenludd 2024-03-17 15:28:20 +01:00
commit b1f57e5ed8
28 changed files with 433 additions and 346 deletions

View file

@ -2,7 +2,6 @@ package database
import (
"embed"
"os"
"path/filepath"
"ttime/internal/types"
@ -19,7 +18,7 @@ type Database interface {
PromoteToAdmin(username string) error
GetUserId(username string) (int, error)
AddProject(name string, description string, username string) error
Migrate(dirname string) error
Migrate() error
GetProjectId(projectname string) (int, error)
AddWeeklyReport(projectName string, userName string, week int, developmentTime int, meetingTime int, adminTime int, ownWorkTime int, studyTime int, testingTime int) error
AddUserToProject(username string, projectname string, role string) error
@ -259,13 +258,18 @@ func (d *Db) GetAllUsersApplication() ([]string, error) {
// Reads a directory of migration files and applies them to the database.
// This will eventually be used on an embedded directory
func (d *Db) Migrate(dirname string) error {
func (d *Db) Migrate() error {
// Read the embedded scripts directory
files, err := scripts.ReadDir("migrations")
if err != nil {
return err
}
if len(files) == 0 {
println("No migration files found")
return nil
}
tr := d.MustBegin()
// Iterate over each SQL file and execute it
@ -275,8 +279,7 @@ func (d *Db) Migrate(dirname string) error {
}
// This is perhaps not the most elegant way to do this
sqlFile := filepath.Join("migrations", file.Name())
sqlBytes, err := os.ReadFile(sqlFile)
sqlBytes, err := scripts.ReadFile("migrations/" + file.Name())
if err != nil {
return err
}

View file

@ -8,7 +8,7 @@ import (
func setupState() (Database, error) {
db := DbConnect(":memory:")
err := db.Migrate("../../migrations")
err := db.Migrate()
if err != nil {
return nil, err
}

View file

@ -43,6 +43,11 @@ func main() {
// Connect to the database
db := database.DbConnect(conf.DbPath)
// Migrate the database
if err = db.Migrate(); err != nil {
fmt.Println("Error migrating database: ", err)
}
// Get our global state
gs := handlers.NewGlobalState(db)
// Create the server

View file

@ -0,0 +1,18 @@
import { useNavigate } from "react-router-dom";
function BackButton(): JSX.Element {
const navigate = useNavigate();
const goBack = (): void => {
navigate(-1);
};
return (
<button
onClick={goBack}
className="inline-block py-1 px-8 font-bold bg-orange-500 text-white border-2 border-black rounded-full cursor-pointer mt-5 mb-5 transition-colors duration-10 hover:bg-orange-600 hover:text-gray-300 font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; font-size: 4vh;"
>
Back
</button>
);
}
export default BackButton;

View file

@ -0,0 +1,24 @@
import { useEffect } from "react";
const BackgroundAnimation = (): JSX.Element => {
useEffect(() => {
const images = [
"src/assets/1.jpg",
"src/assets/2.jpg",
"src/assets/3.jpg",
"src/assets/4.jpg",
];
// Pre-load images
for (const i of images) {
console.log(i);
}
// Start animation
document.body.style.animation = "backgroundTransition 30s infinite";
}, []);
return <></>;
};
export default BackgroundAnimation;

View file

@ -0,0 +1,41 @@
/**
* A customizable input field
* @param props - Settings for the field
* @returns {JSX.Element} The input field
* @example
* <InputField
* type="text"
* label="Example"
* onChange={(e) => {
* setExample(e.target.value);
* }}
* value={example}
* />
*/
function InputField(props: {
label: string;
type: string;
value: string;
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
}): JSX.Element {
return (
<div className="mb-4">
<label
className="block text-gray-700 text-sm font-sans font-bold mb-2"
htmlFor={props.label}
>
{props.label}
</label>
<input
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.label}
value={props.value}
onChange={props.onChange}
/>
</div>
);
}
export default InputField;

View file

@ -0,0 +1,35 @@
import { NewUser } from "../Types/Users";
function LoginCheck(props: { username: string; password: string }): number {
//Example users for testing without backend, remove when using backend
const admin: NewUser = {
userName: "admin",
password: "123",
};
const pmanager: NewUser = {
userName: "pmanager",
password: "123",
};
const user: NewUser = {
userName: "user",
password: "123",
};
//TODO: Compare with db instead when finished
if (props.username === admin.userName && props.password === admin.password) {
return 1;
} else if (
props.username === pmanager.userName &&
props.password === pmanager.password
) {
return 2;
} else if (
props.username === user.userName &&
props.password === user.password
) {
return 3;
}
return 0;
}
export default LoginCheck;

View file

@ -0,0 +1,55 @@
import { Dispatch, FormEventHandler, SetStateAction } from "react";
import Button from "./Button";
import InputField from "./InputField";
/**
* A login field complete with input fields
* and a button for submitting the information
* @param props - Settings
* @returns {JSX.Element} A login component
* @example
* <Login
* handleSubmit={handleSubmit}
* setUsername={setUsername}
* setPassword={setPassword}
* username={username}
* password={password}
* />
*/
function Login(props: {
handleSubmit: FormEventHandler<HTMLFormElement>;
setUsername: Dispatch<SetStateAction<string>>;
setPassword: Dispatch<SetStateAction<string>>;
username: string;
password: string;
}): JSX.Element {
return (
<form className="flex flex-col items-center" onSubmit={props.handleSubmit}>
<InputField
type="text"
label="Username"
onChange={(e) => {
props.setUsername(e.target.value);
}}
value={props.username}
/>
<InputField
type="password"
label="Password"
onChange={(e) => {
props.setPassword(e.target.value);
}}
value={props.password}
/>
<Button
text="Login"
onClick={(): void => {
return;
}}
type={"submit"}
/>
</form>
);
}
export default Login;

View file

@ -0,0 +1,35 @@
import { Link } from "react-router-dom";
import { Project } from "../Types/Project";
/**
* The props for the ProjectsProps component
*/
interface ProjectProps {
projects: Project[];
}
/**
* A list of projects for users, that links the user to the right project page
* thanks to the state property
* @param props - The projects to display
* @returns {JSX.Element} The project list
* @example
* const projects = [{ id: 1, name: "Random name" }];
* return <ProjectList projects={projects} />;
*/
export function ProjectListUser(props: ProjectProps): JSX.Element {
return (
<div>
<ul className="font-bold underline text-[30px] cursor-pointer">
{props.projects.map((project) => (
<Link to="/project" key={project.id} state={project.name}>
<li className="pt-5" key={project.id}>
{project.name}
</li>
</Link>
))}
</ul>
</div>
);
}

View file

@ -0,0 +1,35 @@
import { Link } from "react-router-dom";
import { User } from "../Types/Users";
/**
* The props for the UserProps component
*/
interface UserProps {
users: User[];
}
/**
* 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: "Random name" }];
* return <UserList users={users} />;
*/
export function UserListAdmin(props: UserProps): JSX.Element {
return (
<div>
<ul className="font-bold underline text-[30px] cursor-pointer padding">
{props.users.map((user) => (
<Link to="/admin-view-user" key={user.id} state={user.userName}>
<li className="pt-5" key={user.id}>
{user.userName}
</li>
</Link>
))}
</ul>
</div>
);
}

View file

@ -1,25 +1,38 @@
import BasicWindow from "../../Components/BasicWindow";
import Button from "../../Components/Button";
import BackButton from "../../Components/BackButton";
import { UserListAdmin } from "../../Components/UserListAdmin";
import { User } from "../../Types/Users";
import { useNavigate } from "react-router-dom";
function AdminManageUsers(): JSX.Element {
const content = <></>;
//TODO: Change so that it reads users from database
const users: User[] = [];
for (let i = 1; i <= 20; i++) {
users.push({ id: i, userName: "Example User " + i });
}
const navigate = useNavigate();
const content = (
<>
<h1 className="font-bold text-[30px] mb-[20px]">Manage Users</h1>
<div className="border-4 border-black bg-white flex flex-col items-center h-[65vh] w-[50vw] rounded-3xl content-center overflow-scroll space-y-[10vh] p-[30px]">
<UserListAdmin users={users} />
</div>
</>
);
const buttons = (
<>
<Button
text="Add User"
onClick={(): void => {
return;
}}
type="button"
/>
<Button
text="Back"
onClick={(): void => {
return;
navigate("/admin-add-user");
}}
type="button"
/>
<BackButton />
</>
);

View file

@ -6,12 +6,12 @@ function AdminMenuPage(): JSX.Element {
<>
<h1 className="font-bold text-[30px] mb-[20px]">Administrator Menu</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="/admin-users-page">
<Link to="/admin-manage-users">
<h1 className="font-bold underline text-[30px] cursor-pointer">
Manage Users
</h1>
</Link>
<Link to="/admin-projects-page">
<Link to="/admin-manage-projects">
<h1 className="font-bold underline text-[30px] cursor-pointer">
Manage Projects
</h1>

View file

@ -1,8 +1,17 @@
import { useLocation } from "react-router-dom";
import BasicWindow from "../../Components/BasicWindow";
import Button from "../../Components/Button";
import BackButton from "../../Components/BackButton";
function AdminViewUserInfo(): JSX.Element {
const content = <></>;
const content = (
<>
<h1 className="font-bold text-[30px] mb-[20px]">{useLocation().state}</h1>
<div className="border-4 border-black bg-white flex flex-col items-center h-[65vh] w-[50vw] rounded-3xl content-center overflow-scroll space-y-[10vh] p-[30px]">
<p>Put relevant info on user from database here</p>
</div>
</>
);
const buttons = (
<>
@ -13,13 +22,7 @@ function AdminViewUserInfo(): JSX.Element {
}}
type="button"
/>
<Button
text="Back"
onClick={(): void => {
return;
}}
type="button"
/>
<BackButton />
</>
);

View file

@ -0,0 +1,20 @@
import { useState } from "react";
import LoginPage from "./LoginPage";
import { useNavigate } from "react-router-dom";
function App(): JSX.Element {
const navigate = useNavigate();
const [authority, setAuthority] = useState(0);
if (authority === 1) {
navigate("/admin");
} else if (authority === 2) {
navigate("/pm");
} else if (authority === 3) {
navigate("/user");
}
return <LoginPage setAuthority={setAuthority} />;
}
export default App;

View file

@ -1,36 +1,31 @@
import Button from "../Components/Button";
import Logo from "/src/assets/Logo.svg";
import "./LoginPage.css";
import { useEffect } from "react";
import { Link } from "react-router-dom";
import { Dispatch, FormEvent, SetStateAction, useState } from "react";
import BackgroundAnimation from "../Components/BackgroundAnimation";
import LoginField from "../Components/LoginField";
import LoginCheck from "../Components/LoginCheck";
const PreloadBackgroundAnimation = (): JSX.Element => {
useEffect(() => {
const images = [
"src/assets/1.jpg",
"src/assets/2.jpg",
"src/assets/3.jpg",
"src/assets/4.jpg",
];
function LoginPage(props: {
setAuthority: Dispatch<SetStateAction<number>>;
}): JSX.Element {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
// Pre-load images
for (const i of images) {
console.log(i);
/* On submit (enter or button click) check if username and password match any user
and if so, redirect to correct page */
function handleSubmit(event: FormEvent<HTMLFormElement>): void {
event.preventDefault();
props.setAuthority((prevAuth) => {
prevAuth = LoginCheck({ username: username, password: password });
return prevAuth;
});
}
// Start animation
document.body.style.animation = "backgroundTransition 30s infinite";
}, []);
return <></>;
};
function LoginPage(): JSX.Element {
return (
<>
<PreloadBackgroundAnimation />
<BackgroundAnimation />
<div
className="flex flex-col h-screen w-screen items-center justify-center"
className="flex flex-col h-screen items-center justify-center bg-cover bg-fixed"
style={{
animation: "backgroundTransition 30s infinite",
backgroundSize: "cover",
@ -51,34 +46,13 @@ function LoginPage(): JSX.Element {
{" "}
Please log in to continue{" "}
</h2>
<input
className="border-2 border-black mb-3 rounded-lg w-[20vw] p-1"
type="text"
placeholder="Username"
<LoginField
handleSubmit={handleSubmit}
setUsername={setUsername}
setPassword={setPassword}
username={username}
password={password}
/>
<input
className="border-2 border-black mb-3 rounded-lg w-[20vw] p-1"
type="password"
placeholder="Password"
/>
<Link to="/your-projects">
<Button
text="Login"
onClick={(): void => {
return;
}}
type="button"
/>
</Link>
<Link to="/register">
<Button
text="Register new user"
onClick={(): void => {
return;
}}
type="button"
/>
</Link>
</div>
</div>
</>

View file

@ -1,5 +1,6 @@
import BasicWindow from "../../Components/BasicWindow";
import Button from "../../Components/Button";
import BackButton from "../../Components/BackButton";
function ChangeRole(): JSX.Element {
const content = <></>;
@ -13,13 +14,7 @@ function ChangeRole(): JSX.Element {
}}
type="button"
/>
<Button
text="Back"
onClick={(): void => {
return;
}}
type="button"
/>
<BackButton />
</>
);

View file

@ -1,18 +1,12 @@
import BasicWindow from "../../Components/BasicWindow";
import Button from "../../Components/Button";
import BackButton from "../../Components/BackButton";
function PMOtherUsersTR(): JSX.Element {
const content = <></>;
const buttons = (
<>
<Button
text="Back"
onClick={(): void => {
return;
}}
type="button"
/>
<BackButton />
</>
);

View file

@ -1,32 +1,30 @@
import BasicWindow from "../../Components/BasicWindow";
import Button from "../../Components/Button";
import BackButton from "../../Components/BackButton";
import { Link } from "react-router-dom";
function PMProjectMembers(): JSX.Element {
const content = <></>;
const buttons = (
<>
<Link to="/PM-time-activity">
<Button
text="Time / Activity"
onClick={(): void => {
return;
}}
type="button"
/>
</Link>
<Link to="/PM-time-role">
<Button
text="Time / Role"
onClick={(): void => {
return;
}}
type="button"
/>
<Button
text="Back"
onClick={(): void => {
return;
}}
type="button"
/>
</Link>
<BackButton />
</>
);

View file

@ -1,39 +1,36 @@
import { Link } from "react-router-dom";
import BasicWindow from "../../Components/BasicWindow";
import Button from "../../Components/Button";
import { JSX } from "react/jsx-runtime";
function PMProjectPage(): JSX.Element {
const content = (
<>
<h1 className="font-bold text-[30px] mb-[20px]">ProjectNameExample</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="/project-page">
<h1 className="font-bold underline text-[30px] cursor-pointer">
Your Time Reports
</h1>
</Link>
<Link to="/new-time-report">
<h1 className="font-bold underline text-[30px] cursor-pointer">
New Time Report
</h1>
</Link>
<Link to="/project-members">
<h1 className="font-bold underline text-[30px] cursor-pointer">
Statistics
</h1>
</Link>
<Link to="/PM-unsigned-reports">
<h1 className="font-bold underline text-[30px] cursor-pointer">
Unsigned Time Reports
</h1>
</Link>
</div>
</>
);
const buttons = (
<>
<Button
text="Back"
onClick={(): void => {
return;
}}
type="button"
/>
</>
);
return <BasicWindow username="Admin" content={content} buttons={buttons} />;
return <BasicWindow username="Admin" content={content} buttons={undefined} />;
}
export default PMProjectPage;

View file

@ -14,13 +14,7 @@ function PMTotalTimeActivity(): JSX.Element {
const buttons = (
<>
<Button
text="Back"
onClick={(): void => {
return;
}}
type="button"
/>
<BackButton />
</>
);

View file

@ -1,18 +1,12 @@
import BasicWindow from "../../Components/BasicWindow";
import Button from "../../Components/Button";
import BackButton from "../../Components/BackButton";
function PMTotalTimeRole(): JSX.Element {
const content = <></>;
const buttons = (
<>
<Button
text="Back"
onClick={(): void => {
return;
}}
type="button"
/>
<BackButton />
</>
);

View file

@ -1,18 +1,12 @@
import BasicWindow from "../../Components/BasicWindow";
import Button from "../../Components/Button";
import BackButton from "../../Components/BackButton";
function PMUnsignedReports(): JSX.Element {
const content = <></>;
const buttons = (
<>
<Button
text="Back"
onClick={(): void => {
return;
}}
type="button"
/>
<BackButton />
</>
);

View file

@ -28,13 +28,7 @@ function PMViewUnsignedReport(): JSX.Element {
}}
type="button"
/>
<Button
text="Back"
onClick={(): void => {
return;
}}
type="button"
/>
<BackButton />
</>
);

View file

@ -19,13 +19,7 @@ function UserEditTimeReportPage(): JSX.Element {
}}
type="button"
/>
<Button
text="Back"
onClick={(): void => {
return;
}}
type="button"
/>
<BackButton />
</>
);

View file

@ -1,15 +1,17 @@
import { Link } from "react-router-dom";
import { Link, useLocation } from "react-router-dom";
import BasicWindow from "../../Components/BasicWindow";
import Button from "../../Components/Button";
import BackButton from "../../Components/BackButton";
function UserProjectPage(): JSX.Element {
const content = (
<>
<h1 className="font-bold text-[30px] mb-[20px]">ProjectNameExample</h1>
<h1 className="font-bold text-[30px] mb-[20px]">{useLocation().state}</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="/project-page">
<h1 className="font-bold underline text-[30px] cursor-pointer">
Your Time Reports
</h1>
</Link>
<Link to="/new-time-report">
<h1 className="font-bold underline text-[30px] cursor-pointer">
New Time Report
@ -21,15 +23,7 @@ function UserProjectPage(): JSX.Element {
const buttons = (
<>
<Link to="/your-projects">
<Button
text="Back"
onClick={(): void => {
return;
}}
type="button"
/>
</Link>
<BackButton />
</>
);

View file

@ -1,18 +1,17 @@
import BasicWindow from "../../Components/BasicWindow";
import Button from "../../Components/Button";
import BackButton from "../../Components/BackButton";
function UserViewTimeReportsPage(): JSX.Element {
const content = <></>;
const content = (
<>
<h1 className="font-bold text-[30px] mb-[20px]">Your Time Reports</h1>
{/* Här kan du inkludera logiken för att visa användarens tidrapporter */}
</>
);
const buttons = (
<>
<Button
text="Back"
onClick={(): void => {
return;
}}
type="button"
/>
<BackButton />
</>
);

View file

@ -1,25 +1,25 @@
import { Link } from "react-router-dom";
import BasicWindow from "../Components/BasicWindow";
import { ProjectListUser } from "../Components/ProjectListUser";
import { Project } from "../Types/Project";
function YourProjectsPage(): JSX.Element {
//TODO: Change so that it reads projects from database
const projects: Project[] = [];
for (let i = 1; i <= 20; i++) {
projects.push({
id: i,
name: "Example Project " + i,
description: "good",
created: "now",
owner: "me",
});
}
const content = (
<>
<h1 className="font-bold text-[30px] mb-[20px]">Your Projects</h1>
<div className="border-4 border-black bg-white flex flex-col items-center justify-between min-h-[65vh] h-fit w-[50vw] rounded-3xl content-center overflow-scroll space-y-[10px] p-[30px]">
<Link to="/project">
<h1 className="underline text-[24px] cursor-pointer font-bold">
ProjectNameExample
</h1>
</Link>
<h1 className="underline text-[24px] cursor-pointer font-bold">
ProjectNameExample2
</h1>
<h1 className="underline text-[24px] cursor-pointer font-bold">
ProjectNameExample3
</h1>
<h1 className="underline text-[24px] cursor-pointer font-bold">
ProjectNameExample4
</h1>
<div className="border-4 border-black bg-white flex flex-col items-center h-[65vh] w-[50vw] rounded-3xl content-center overflow-scroll space-y-[10vh] p-[30px]">
<ProjectListUser projects={projects} />
</div>
</>
);

View file

@ -2,148 +2,27 @@ import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import LoginPage from "./Pages/LoginPage.tsx";
import YourProjectsPage from "./Pages/YourProjectsPage.tsx";
import UserProjectPage from "./Pages/UserPages/UserProjectPage.tsx";
import Register from "./Components/Register.tsx";
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 PMChangeRole from "./Pages/ProjectManagerPages/PMChangeRole.tsx";
import PMOtherUsersTR from "./Pages/ProjectManagerPages/PMOtherUsersTR.tsx";
import PMProjectMembers from "./Pages/ProjectManagerPages/PMProjectMembers.tsx";
import PMProjectPage from "./Pages/ProjectManagerPages/PMProjectPage.tsx";
import PMTotalTimeActivity from "./Pages/ProjectManagerPages/PMTotalTimeActivity.tsx";
import PMTotalTimeRole from "./Pages/ProjectManagerPages/PMTotalTimeRole.tsx";
import PMUnsignedReports from "./Pages/ProjectManagerPages/PMUnsignedReports.tsx";
import PMViewUnsignedReport from "./Pages/ProjectManagerPages/PMViewUnsignedReport.tsx";
import AdminManageUsers from "./Pages/AdminPages/AdminManageUsers.tsx";
import AdminViewUserInfo from "./Pages/AdminPages/AdminViewUserInfo.tsx";
import AdminManageProjects from "./Pages/AdminPages/AdminManageProjects.tsx";
import AdminAddProject from "./Pages/AdminPages/AdminAddProject.tsx";
import AdminAddUser from "./Pages/AdminPages/AdminAddUser.tsx";
import AdminChangeUsername from "./Pages/AdminPages/AdminChangeUsername.tsx";
import AdminProjectAddMember from "./Pages/AdminPages/AdminProjectAddMember.tsx";
import AdminProjectChangeUserRole from "./Pages/AdminPages/AdminProjectChangeUserRole.tsx";
import AdminProjectManageMembers from "./Pages/AdminPages/AdminProjectManageMembers.tsx";
import AdminProjectStatistics from "./Pages/AdminPages/AdminProjectStatistics.tsx";
import AdminProjectViewMemberInfo from "./Pages/AdminPages/AdminProjectViewMemberInfo.tsx";
import AdminProjectPage from "./Pages/AdminPages/AdminProjectPage.tsx";
import App from "./Pages/App";
import AdminMenuPage from "./Pages/AdminPages/AdminMenuPage";
import YourProjectsPage from "./Pages/YourProjectsPage";
// This is where the routes are mounted
const router = createBrowserRouter([
{
path: "/",
element: <LoginPage />,
element: <App />,
},
{
path: "/your-projects",
element: <YourProjectsPage />,
},
{
path: "/edit-time-report",
element: <UserEditTimeReportPage />,
},
{
path: "/new-time-report",
element: <UserNewTimeReportPage />,
},
{
path: "/project",
element: <UserProjectPage />,
},
{
path: "/register",
element: <Register />,
},
{
path: "/project-page",
element: <UserViewTimeReportsPage />,
},
{
path: "/change-role",
element: <PMChangeRole />,
},
{
path: "/other-users-time-reports",
element: <PMOtherUsersTR />,
},
{
path: "/project-members",
element: <PMProjectMembers />,
},
{
path: "/PM-project-page",
element: <PMProjectPage />,
},
{
path: "/PM-time-activity",
element: <PMTotalTimeActivity />,
},
{
path: "/PM-time-role",
element: <PMTotalTimeRole />,
},
{
path: "/PM-unsigned-reports",
element: <PMUnsignedReports />,
},
{
path: "/PM-view-unsigned-report",
element: <PMViewUnsignedReport />,
},
{
path: "/admin-add-project",
element: <AdminAddProject />,
},
{
path: "/admin-add-user",
element: <AdminAddUser />,
},
{
path: "/admin-change-username",
element: <AdminChangeUsername />,
},
{
path: "/admin-manage-projects",
element: <AdminManageProjects />,
},
{
path: "/admin-manage-users",
element: <AdminManageUsers />,
},
{
path: "/admin-menu",
path: "/admin",
element: <AdminMenuPage />,
},
{
path: "/admin-project-add-member",
element: <AdminProjectAddMember />,
path: "/pm",
element: <YourProjectsPage />,
},
{
path: "/admin-project-change-user-role",
element: <AdminProjectChangeUserRole />,
},
{
path: "/admin-project-manage-members",
element: <AdminProjectManageMembers />,
},
{
path: "/admin-project-page",
element: <AdminProjectPage />,
},
{
path: "/admin-project-statistics",
element: <AdminProjectStatistics />,
},
{
path: "/admin-project-view-members",
element: <AdminProjectViewMemberInfo />,
},
{
path: "/admin-view-user",
element: <AdminViewUserInfo />,
path: "/user",
element: <YourProjectsPage />,
},
]);