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 ( +
+ { + props.setUsername(e.target.value); + }} + value={props.username} + /> + { + props.setPassword(e.target.value); + }} + value={props.password} + /> +