diff --git a/backend/internal/database/db.go b/backend/internal/database/db.go
index ef365cd..320327a 100644
--- a/backend/internal/database/db.go
+++ b/backend/internal/database/db.go
@@ -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
}
diff --git a/backend/internal/database/db_test.go b/backend/internal/database/db_test.go
index 5438d66..9124c45 100644
--- a/backend/internal/database/db_test.go
+++ b/backend/internal/database/db_test.go
@@ -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
}
diff --git a/backend/main.go b/backend/main.go
index 9ba2556..7f0f81e 100644
--- a/backend/main.go
+++ b/backend/main.go
@@ -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
diff --git a/frontend/src/Components/BackButton.tsx b/frontend/src/Components/BackButton.tsx
new file mode 100644
index 0000000..7a1ac81
--- /dev/null
+++ b/frontend/src/Components/BackButton.tsx
@@ -0,0 +1,18 @@
+import { useNavigate } from "react-router-dom";
+
+function BackButton(): JSX.Element {
+ const navigate = useNavigate();
+ const goBack = (): void => {
+ navigate(-1);
+ };
+ return (
+
+ );
+}
+
+export default BackButton;
diff --git a/frontend/src/Components/BackgroundAnimation.tsx b/frontend/src/Components/BackgroundAnimation.tsx
new file mode 100644
index 0000000..5f402c0
--- /dev/null
+++ b/frontend/src/Components/BackgroundAnimation.tsx
@@ -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;
diff --git a/frontend/src/Components/InputField.tsx b/frontend/src/Components/InputField.tsx
new file mode 100644
index 0000000..639b4ca
--- /dev/null
+++ b/frontend/src/Components/InputField.tsx
@@ -0,0 +1,41 @@
+/**
+ * A customizable input field
+ * @param props - Settings for the field
+ * @returns {JSX.Element} The input field
+ * @example
+ * {
+ * setExample(e.target.value);
+ * }}
+ * value={example}
+ * />
+ */
+function InputField(props: {
+ label: string;
+ type: string;
+ value: string;
+ onChange: (e: React.ChangeEvent) => void;
+}): JSX.Element {
+ return (
+
+
+
+
+ );
+}
+
+export default InputField;
diff --git a/frontend/src/Components/LoginCheck.tsx b/frontend/src/Components/LoginCheck.tsx
new file mode 100644
index 0000000..ccf761d
--- /dev/null
+++ b/frontend/src/Components/LoginCheck.tsx
@@ -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;
diff --git a/frontend/src/Components/LoginField.tsx b/frontend/src/Components/LoginField.tsx
new file mode 100644
index 0000000..d7768c0
--- /dev/null
+++ b/frontend/src/Components/LoginField.tsx
@@ -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
+ *
+ */
+function Login(props: {
+ handleSubmit: FormEventHandler;
+ setUsername: Dispatch>;
+ setPassword: Dispatch>;
+ username: string;
+ password: string;
+}): JSX.Element {
+ return (
+
+ );
+}
+
+export default Login;
diff --git a/frontend/src/Components/ProjectListUser.tsx b/frontend/src/Components/ProjectListUser.tsx
new file mode 100644
index 0000000..0502159
--- /dev/null
+++ b/frontend/src/Components/ProjectListUser.tsx
@@ -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 ;
+ */
+
+export function ProjectListUser(props: ProjectProps): JSX.Element {
+ return (
+
+
+ {props.projects.map((project) => (
+
+
+ {project.name}
+
+
+ ))}
+
+
+ );
+}
diff --git a/frontend/src/Components/UserListAdmin.tsx b/frontend/src/Components/UserListAdmin.tsx
new file mode 100644
index 0000000..42fb094
--- /dev/null
+++ b/frontend/src/Components/UserListAdmin.tsx
@@ -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 ;
+ */
+
+export function UserListAdmin(props: UserProps): JSX.Element {
+ return (
+
+
+ {props.users.map((user) => (
+
+
+ {user.userName}
+
+
+ ))}
+
+
+ );
+}
diff --git a/frontend/src/Pages/AdminPages/AdminManageUsers.tsx b/frontend/src/Pages/AdminPages/AdminManageUsers.tsx
index cd38180..ac84194 100644
--- a/frontend/src/Pages/AdminPages/AdminManageUsers.tsx
+++ b/frontend/src/Pages/AdminPages/AdminManageUsers.tsx
@@ -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 = (
+ <>
+