Merge branch 'gruppPP' into gruppDM
This commit is contained in:
commit
3c8b7f9da2
10 changed files with 152 additions and 70 deletions
94
frontend/src/Components/AddProject.tsx
Normal file
94
frontend/src/Components/AddProject.tsx
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
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<Project>) => {
|
||||||
|
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 (
|
||||||
|
<div className="flex flex-col h-fit w-screen items-center justify-center">
|
||||||
|
<div className="border-4 border-black bg-white flex flex-col items-center justify-center h-fit w-fit rounded-3xl content-center pl-20 pr-20">
|
||||||
|
<form
|
||||||
|
className="bg-white rounded px-8 pt-6 pb-8 mb-4 items-center justify-center flex flex-col w-fit h-fit"
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
CreateProject({ name: name, description: description });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={Logo}
|
||||||
|
className="logo w-[7vw] mb-10 mt-10"
|
||||||
|
alt="TTIME Logo"
|
||||||
|
/>
|
||||||
|
<h3 className="pb-4 mb-2 text-center font-bold text-[18px]">
|
||||||
|
Create a new project
|
||||||
|
</h3>
|
||||||
|
<InputField
|
||||||
|
label="Name"
|
||||||
|
type="text"
|
||||||
|
value={name}
|
||||||
|
onChange={(e) => {
|
||||||
|
setName(e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<InputField
|
||||||
|
label="Description"
|
||||||
|
type="text"
|
||||||
|
value={description}
|
||||||
|
onChange={(e) => {
|
||||||
|
setDescription(e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Button
|
||||||
|
text="Create"
|
||||||
|
onClick={(): void => {
|
||||||
|
return;
|
||||||
|
}}
|
||||||
|
type="submit"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<p className="text-center text-gray-500 text-xs"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AddProject;
|
|
@ -5,7 +5,7 @@ function Header({ username }: { username: string }): JSX.Element {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
const handleLogout = (): void => {
|
const handleLogout = (): void => {
|
||||||
// Add any logout logic here
|
localStorage.clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -10,17 +10,21 @@ function LoginCheck(props: {
|
||||||
username: string;
|
username: string;
|
||||||
password: string;
|
password: string;
|
||||||
setAuthority: Dispatch<SetStateAction<number>>;
|
setAuthority: Dispatch<SetStateAction<number>>;
|
||||||
}): number {
|
}): void {
|
||||||
const user: NewUser = {
|
const user: NewUser = {
|
||||||
username: props.username,
|
username: props.username,
|
||||||
password: props.password,
|
password: props.password,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
localStorage.clear();
|
||||||
|
|
||||||
api
|
api
|
||||||
.login(user)
|
.login(user)
|
||||||
.then((response: APIResponse<string>) => {
|
.then((response: APIResponse<string>) => {
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
if (response.data !== undefined) {
|
if (response.data !== undefined) {
|
||||||
const token = response.data;
|
const token = response.data;
|
||||||
|
localStorage.setItem("accessToken", token);
|
||||||
//TODO: change so that it checks for user type (admin, user, pm) instead
|
//TODO: change so that it checks for user type (admin, user, pm) instead
|
||||||
if (token !== "" && props.username === "admin") {
|
if (token !== "" && props.username === "admin") {
|
||||||
props.setAuthority((prevAuth) => {
|
props.setAuthority((prevAuth) => {
|
||||||
|
@ -42,14 +46,12 @@ function LoginCheck(props: {
|
||||||
console.error("Token was undefined");
|
console.error("Token was undefined");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.error("Token could not be fetched");
|
console.error("Token could not be fetched/No such user");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error("An error occurred during login:", error);
|
console.error("An error occurred during login:", error);
|
||||||
});
|
});
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default LoginCheck;
|
export default LoginCheck;
|
||||||
|
|
|
@ -3,34 +3,9 @@ import { NewUser } from "../Types/goTypes";
|
||||||
import { api } from "../API/API";
|
import { api } from "../API/API";
|
||||||
import Logo from "../assets/Logo.svg";
|
import Logo from "../assets/Logo.svg";
|
||||||
import Button from "./Button";
|
import Button from "./Button";
|
||||||
|
import InputField from "./InputField";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
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 function Register(): JSX.Element {
|
export default function Register(): JSX.Element {
|
||||||
const [username, setUsername] = useState<string>();
|
const [username, setUsername] = useState<string>();
|
||||||
const [password, setPassword] = useState<string>();
|
const [password, setPassword] = useState<string>();
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { User } from "../Types/goTypes";
|
import { PublicUser } from "../Types/goTypes";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The props for the UserProps component
|
* The props for the UserProps component
|
||||||
*/
|
*/
|
||||||
interface UserProps {
|
interface UserProps {
|
||||||
users: User[];
|
users: PublicUser[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,7 +23,7 @@ export function UserListAdmin(props: UserProps): JSX.Element {
|
||||||
<div>
|
<div>
|
||||||
<ul className="font-bold underline text-[30px] cursor-pointer padding">
|
<ul className="font-bold underline text-[30px] cursor-pointer padding">
|
||||||
{props.users.map((user) => (
|
{props.users.map((user) => (
|
||||||
<Link to="/admin-view-user" key={user.userId} state={user.username}>
|
<Link to="/adminUserInfo" key={user.userId} state={user.username}>
|
||||||
<li className="pt-5" key={user.userId}>
|
<li className="pt-5" key={user.userId}>
|
||||||
{user.username}
|
{user.username}
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -1,25 +1,13 @@
|
||||||
|
import AddProject from "../../Components/AddProject";
|
||||||
|
import BackButton from "../../Components/BackButton";
|
||||||
import BasicWindow from "../../Components/BasicWindow";
|
import BasicWindow from "../../Components/BasicWindow";
|
||||||
import Button from "../../Components/Button";
|
|
||||||
|
|
||||||
function AdminAddProject(): JSX.Element {
|
function AdminAddProject(): JSX.Element {
|
||||||
const content = <></>;
|
const content = <AddProject />;
|
||||||
|
|
||||||
const buttons = (
|
const buttons = (
|
||||||
<>
|
<>
|
||||||
<Button
|
<BackButton />
|
||||||
text="Finish"
|
|
||||||
onClick={(): void => {
|
|
||||||
return;
|
|
||||||
}}
|
|
||||||
type="button"
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
text="Back"
|
|
||||||
onClick={(): void => {
|
|
||||||
return;
|
|
||||||
}}
|
|
||||||
type="button"
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
import BackButton from "../../Components/BackButton";
|
||||||
import BasicWindow from "../../Components/BasicWindow";
|
import BasicWindow from "../../Components/BasicWindow";
|
||||||
import Button from "../../Components/Button";
|
import Button from "../../Components/Button";
|
||||||
|
|
||||||
|
@ -6,20 +8,16 @@ function AdminManageProjects(): JSX.Element {
|
||||||
|
|
||||||
const buttons = (
|
const buttons = (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Link to="/addProject">
|
||||||
text="Add Project"
|
<Button
|
||||||
onClick={(): void => {
|
text="Add Project"
|
||||||
return;
|
onClick={(): void => {
|
||||||
}}
|
return;
|
||||||
type="button"
|
}}
|
||||||
/>
|
type="button"
|
||||||
<Button
|
/>
|
||||||
text="Back"
|
</Link>
|
||||||
onClick={(): void => {
|
<BackButton />
|
||||||
return;
|
|
||||||
}}
|
|
||||||
type="button"
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,14 @@ import BasicWindow from "../../Components/BasicWindow";
|
||||||
import Button from "../../Components/Button";
|
import Button from "../../Components/Button";
|
||||||
import BackButton from "../../Components/BackButton";
|
import BackButton from "../../Components/BackButton";
|
||||||
import { UserListAdmin } from "../../Components/UserListAdmin";
|
import { UserListAdmin } from "../../Components/UserListAdmin";
|
||||||
import { User } from "../../Types/Users";
|
import { PublicUser } from "../../Types/goTypes";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
function AdminManageUsers(): JSX.Element {
|
function AdminManageUsers(): JSX.Element {
|
||||||
//TODO: Change so that it reads users from database
|
//TODO: Change so that it reads users from database
|
||||||
const users: User[] = [];
|
const users: PublicUser[] = [];
|
||||||
for (let i = 1; i <= 20; i++) {
|
for (let i = 1; i <= 20; i++) {
|
||||||
users.push({ id: i, userName: "Example User " + i });
|
users.push({ userId: "id" + i, username: "Example User " + i });
|
||||||
}
|
}
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
@ -28,7 +28,7 @@ function AdminManageUsers(): JSX.Element {
|
||||||
<Button
|
<Button
|
||||||
text="Add User"
|
text="Add User"
|
||||||
onClick={(): void => {
|
onClick={(): void => {
|
||||||
navigate("/admin-add-user");
|
navigate("/adminAddUser");
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -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-manage-users">
|
<Link to="/adminManageUser">
|
||||||
<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-manage-projects">
|
<Link to="/adminManageProject">
|
||||||
<h1 className="font-bold underline text-[30px] cursor-pointer">
|
<h1 className="font-bold underline text-[30px] cursor-pointer">
|
||||||
Manage Projects
|
Manage Projects
|
||||||
</h1>
|
</h1>
|
||||||
|
|
|
@ -5,6 +5,11 @@ import { createBrowserRouter, RouterProvider } from "react-router-dom";
|
||||||
import App from "./Pages/App";
|
import App from "./Pages/App";
|
||||||
import AdminMenuPage from "./Pages/AdminPages/AdminMenuPage";
|
import AdminMenuPage from "./Pages/AdminPages/AdminMenuPage";
|
||||||
import YourProjectsPage from "./Pages/YourProjectsPage";
|
import YourProjectsPage from "./Pages/YourProjectsPage";
|
||||||
|
import AdminAddProject from "./Pages/AdminPages/AdminAddProject";
|
||||||
|
import AdminManageProjects from "./Pages/AdminPages/AdminManageProjects";
|
||||||
|
import AdminManageUsers from "./Pages/AdminPages/AdminManageUsers";
|
||||||
|
import AdminAddUser from "./Pages/AdminPages/AdminAddUser";
|
||||||
|
import AdminViewUserInfo from "./Pages/AdminPages/AdminViewUserInfo";
|
||||||
|
|
||||||
// This is where the routes are mounted
|
// This is where the routes are mounted
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
|
@ -24,6 +29,26 @@ const router = createBrowserRouter([
|
||||||
path: "/user",
|
path: "/user",
|
||||||
element: <YourProjectsPage />,
|
element: <YourProjectsPage />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/addProject",
|
||||||
|
element: <AdminAddProject />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/adminAddUser",
|
||||||
|
element: <AdminAddUser />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/adminUserInfo",
|
||||||
|
element: <AdminViewUserInfo />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/adminManageProject",
|
||||||
|
element: <AdminManageProjects />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/adminManageUser",
|
||||||
|
element: <AdminManageUsers />,
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Semi-hacky way to get the root element
|
// Semi-hacky way to get the root element
|
||||||
|
|
Loading…
Reference in a new issue