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 ( import (
"embed" "embed"
"os"
"path/filepath" "path/filepath"
"ttime/internal/types" "ttime/internal/types"
@ -19,7 +18,7 @@ type Database interface {
PromoteToAdmin(username string) error PromoteToAdmin(username string) error
GetUserId(username string) (int, error) GetUserId(username string) (int, error)
AddProject(name string, description string, username string) error AddProject(name string, description string, username string) error
Migrate(dirname string) error Migrate() error
GetProjectId(projectname string) (int, 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 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 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. // Reads a directory of migration files and applies them to the database.
// This will eventually be used on an embedded directory // 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 // Read the embedded scripts directory
files, err := scripts.ReadDir("migrations") files, err := scripts.ReadDir("migrations")
if err != nil { if err != nil {
return err return err
} }
if len(files) == 0 {
println("No migration files found")
return nil
}
tr := d.MustBegin() tr := d.MustBegin()
// Iterate over each SQL file and execute it // 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 // This is perhaps not the most elegant way to do this
sqlFile := filepath.Join("migrations", file.Name()) sqlBytes, err := scripts.ReadFile("migrations/" + file.Name())
sqlBytes, err := os.ReadFile(sqlFile)
if err != nil { if err != nil {
return err return err
} }

View file

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

View file

@ -43,6 +43,11 @@ func main() {
// Connect to the database // Connect to the database
db := database.DbConnect(conf.DbPath) db := database.DbConnect(conf.DbPath)
// Migrate the database
if err = db.Migrate(); err != nil {
fmt.Println("Error migrating database: ", err)
}
// Get our global state // Get our global state
gs := handlers.NewGlobalState(db) gs := handlers.NewGlobalState(db)
// Create the server // 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 BasicWindow from "../../Components/BasicWindow";
import Button from "../../Components/Button"; 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 { 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 = ( const buttons = (
<> <>
<Button <Button
text="Add User" text="Add User"
onClick={(): void => { onClick={(): void => {
return; navigate("/admin-add-user");
}}
type="button"
/>
<Button
text="Back"
onClick={(): void => {
return;
}} }}
type="button" type="button"
/> />
<BackButton />
</> </>
); );

View file

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

View file

@ -1,8 +1,17 @@
import { useLocation } from "react-router-dom";
import BasicWindow from "../../Components/BasicWindow"; import BasicWindow from "../../Components/BasicWindow";
import Button from "../../Components/Button"; import Button from "../../Components/Button";
import BackButton from "../../Components/BackButton";
function AdminViewUserInfo(): JSX.Element { 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 = ( const buttons = (
<> <>
@ -13,13 +22,7 @@ function AdminViewUserInfo(): JSX.Element {
}} }}
type="button" type="button"
/> />
<Button <BackButton />
text="Back"
onClick={(): void => {
return;
}}
type="button"
/>
</> </>
); );

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 Logo from "/src/assets/Logo.svg";
import "./LoginPage.css"; import "./LoginPage.css";
import { useEffect } from "react"; import { Dispatch, FormEvent, SetStateAction, useState } from "react";
import { Link } from "react-router-dom"; import BackgroundAnimation from "../Components/BackgroundAnimation";
import LoginField from "../Components/LoginField";
import LoginCheck from "../Components/LoginCheck";
const PreloadBackgroundAnimation = (): JSX.Element => { function LoginPage(props: {
useEffect(() => { setAuthority: Dispatch<SetStateAction<number>>;
const images = [ }): JSX.Element {
"src/assets/1.jpg", const [username, setUsername] = useState("");
"src/assets/2.jpg", const [password, setPassword] = useState("");
"src/assets/3.jpg",
"src/assets/4.jpg",
];
// Pre-load images /* On submit (enter or button click) check if username and password match any user
for (const i of images) { and if so, redirect to correct page */
console.log(i); 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 ( return (
<> <>
<PreloadBackgroundAnimation /> <BackgroundAnimation />
<div <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={{ style={{
animation: "backgroundTransition 30s infinite", animation: "backgroundTransition 30s infinite",
backgroundSize: "cover", backgroundSize: "cover",
@ -51,34 +46,13 @@ function LoginPage(): JSX.Element {
{" "} {" "}
Please log in to continue{" "} Please log in to continue{" "}
</h2> </h2>
<input <LoginField
className="border-2 border-black mb-3 rounded-lg w-[20vw] p-1" handleSubmit={handleSubmit}
type="text" setUsername={setUsername}
placeholder="Username" 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>
</div> </div>
</> </>

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

View file

@ -1,18 +1,17 @@
import BasicWindow from "../../Components/BasicWindow"; import BasicWindow from "../../Components/BasicWindow";
import Button from "../../Components/Button"; import BackButton from "../../Components/BackButton";
function UserViewTimeReportsPage(): JSX.Element { 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 = ( const buttons = (
<> <>
<Button <BackButton />
text="Back"
onClick={(): void => {
return;
}}
type="button"
/>
</> </>
); );

View file

@ -1,25 +1,25 @@
import { Link } from "react-router-dom";
import BasicWindow from "../Components/BasicWindow"; import BasicWindow from "../Components/BasicWindow";
import { ProjectListUser } from "../Components/ProjectListUser";
import { Project } from "../Types/Project";
function YourProjectsPage(): JSX.Element { 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 = ( const content = (
<> <>
<h1 className="font-bold text-[30px] mb-[20px]">Your Projects</h1> <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]"> <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]">
<Link to="/project"> <ProjectListUser projects={projects} />
<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> </div>
</> </>
); );

View file

@ -2,148 +2,27 @@ import React from "react";
import ReactDOM from "react-dom/client"; import ReactDOM from "react-dom/client";
import "./index.css"; import "./index.css";
import { createBrowserRouter, RouterProvider } from "react-router-dom"; import { createBrowserRouter, RouterProvider } from "react-router-dom";
import LoginPage from "./Pages/LoginPage.tsx"; import App from "./Pages/App";
import YourProjectsPage from "./Pages/YourProjectsPage.tsx"; import AdminMenuPage from "./Pages/AdminPages/AdminMenuPage";
import UserProjectPage from "./Pages/UserPages/UserProjectPage.tsx"; import YourProjectsPage from "./Pages/YourProjectsPage";
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";
// This is where the routes are mounted // This is where the routes are mounted
const router = createBrowserRouter([ const router = createBrowserRouter([
{ {
path: "/", path: "/",
element: <LoginPage />, element: <App />,
}, },
{ {
path: "/your-projects", path: "/admin",
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",
element: <AdminMenuPage />, element: <AdminMenuPage />,
}, },
{ {
path: "/admin-project-add-member", path: "/pm",
element: <AdminProjectAddMember />, element: <YourProjectsPage />,
}, },
{ {
path: "/admin-project-change-user-role", path: "/user",
element: <AdminProjectChangeUserRole />, element: <YourProjectsPage />,
},
{
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 />,
}, },
]); ]);