diff --git a/backend/db/db.go b/backend/db/db.go index 238a99d..f5b75ab 100644 --- a/backend/db/db.go +++ b/backend/db/db.go @@ -11,11 +11,24 @@ import ( ) func getDbUrl() string { + envPath := "../.env" dbUsr := os.Getenv("POSTGRES_USER") dbHost := os.Getenv("POSTGRES_HOST") dbPassword := os.Getenv("POSTGRES_PASSWORD") dbName := os.Getenv("POSTGRES_DB") + if dbUsr == "" { + dbUsr = utils.GetEnvFileValue(envPath, "POSTGRES_USER") + } + if dbHost == "" { + dbHost = utils.GetEnvFileValue(envPath, "POSTGRES_HOST") + } + if dbPassword == "" { + dbPassword = utils.GetEnvFileValue(envPath, "POSTGRES_PASSWORD") + } + if dbName == "" { + dbName = utils.GetEnvFileValue(envPath, "POSTGRES_DB") + } return fmt.Sprintf("postgres://%s:%s@%s:5432/%s", dbUsr, dbPassword, dbHost, dbName) } diff --git a/backend/go.mod b/backend/go.mod index ef446ee..c80fc0b 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -13,6 +13,7 @@ require ( github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.14.0 // indirect github.com/goccy/go-json v0.10.2 // indirect + github.com/google/uuid v1.4.0 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect @@ -26,6 +27,7 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect + github.com/satori/go.uuid v1.2.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.11 // indirect golang.org/x/arch v0.3.0 // indirect diff --git a/backend/go.sum b/backend/go.sum index 724b37b..c54e2e8 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -27,6 +27,8 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= @@ -57,6 +59,8 @@ github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZ github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= diff --git a/backend/models/handler.go b/backend/models/handler.go index cd9beff..1b2dd47 100644 --- a/backend/models/handler.go +++ b/backend/models/handler.go @@ -6,6 +6,7 @@ import ( "github.com/gin-gonic/gin" "gorm.io/gorm" "net/http" + "reflect" "strconv" ) @@ -21,7 +22,7 @@ func (h Handler) AddTodo(c *gin.Context) { var todo Todo utils.CheckError(c.ShouldBindJSON(&todo)) - fmt.Println(todo) + if result := h.DB.Create(&todo); result.Error != nil { fmt.Println(result.Error) } @@ -36,10 +37,89 @@ func (h Handler) DeleteTodo(c *gin.Context) { statusCode := http.StatusAccepted if result := h.DB.First(&todo, todoId); result.Error != nil { - fmt.Println(result.Error) + fmt.Printf("Todo with id: %v could't be found\n", todoId) } h.DB.Delete(&todo) c.JSON(statusCode, gin.H{ - "message": "Successfully deleted", + "message": fmt.Sprintf("Successfully deleted with id: %v", todoId), + }) +} + +func (h Handler) GetAllTodos(c *gin.Context) { + var todos []Todo + statusCode := http.StatusAccepted + + if result := h.DB.Find(&todos); result.Error != nil || len(todos) == 0 { + statusCode = http.StatusNotFound + fmt.Println("Couldn't find todos") + } + + c.JSON(statusCode, gin.H{ + "todos": todos, + }) +} + +func (h Handler) GetTodo(c *gin.Context) { + var todo Todo + todoId, _ := strconv.Atoi(c.Param("id")) + statusCode := http.StatusAccepted + + if result := h.DB.First(&todo, todoId); result.Error != nil { + fmt.Printf("Todo with id: %v could't be found\n", todoId) + statusCode = http.StatusNotFound + } + + if statusCode == http.StatusAccepted { + c.JSON(statusCode, gin.H{ + "todo": todo, + }) + } else { + c.JSON(statusCode, gin.H{ + "message": fmt.Sprintf("Todo with id %v could't be found\n", todoId), + }) + } +} + +func updateTodoFields(storedTodo *Todo, updatedTodo Todo) { + storedValue := reflect.ValueOf(storedTodo).Elem() + updatedValue := reflect.ValueOf(updatedTodo) + + for i := 0; i < storedValue.NumField(); i++ { + field := storedValue.Type().Field(i) + fieldName := field.Name + storedFieldValue := storedValue.FieldByName(fieldName) + updatedFieldValue := updatedValue.FieldByName(fieldName) + + if !reflect.DeepEqual(updatedFieldValue.Interface(), reflect.Zero(field.Type).Interface()) { + storedFieldValue.Set(updatedFieldValue) + } + } +} + +func (h Handler) UpdateTodo(c *gin.Context) { + var updatedTodo Todo + var storedTodo Todo + todoId, _ := strconv.Atoi(c.Param("id")) + statusCode := http.StatusAccepted + + utils.CheckError(c.Bind(&updatedTodo)) + if result := h.DB.First(&storedTodo, todoId); result.Error != nil { + fmt.Printf("Todo with id: %v could't be found\n", todoId) + statusCode = http.StatusNotFound + } + + fmt.Println(updatedTodo) + fmt.Println(storedTodo) + if statusCode != http.StatusAccepted { + c.JSON(statusCode, gin.H{ + "message": fmt.Sprintf("Todo with id %v could't be found\n", todoId), + }) + return + } + updateTodoFields(&storedTodo, updatedTodo) + // h.DB.Save(&storedTodo) + fmt.Println(storedTodo) + c.JSON(statusCode, gin.H{ + "todo": storedTodo, }) } diff --git a/backend/models/todos.go b/backend/models/todos.go index 602529d..10445cd 100644 --- a/backend/models/todos.go +++ b/backend/models/todos.go @@ -1,7 +1,7 @@ package models type Todo struct { - Id int `json:"id" gorm:"primaryKey"` + Id int `json:"id" gorm:"primary_key;"` Title string `json:"title"` Description string `json:"description"` StartDate string `json:"startDate"` diff --git a/backend/router.go b/backend/router.go index 6df43c9..8571b46 100644 --- a/backend/router.go +++ b/backend/router.go @@ -9,7 +9,7 @@ import ( ) func RouteNotFound(c *gin.Context) { - c.JSON(http.StatusNotFound, gin.H{"message": "Bruh not found"}) + c.JSON(http.StatusNotFound, gin.H{"message": "The page that you are trying to reach doesn't exist"}) } func todosHandler(r *gin.Engine) { @@ -18,6 +18,9 @@ func todosHandler(r *gin.Engine) { r.POST("/todo", handler.AddTodo) r.DELETE("/todo/:id", handler.DeleteTodo) + r.GET("/todos", handler.GetAllTodos) + r.GET("/todo/:id", handler.GetTodo) + r.PATCH("/todo/:id", handler.UpdateTodo) } func router(r *gin.Engine) { diff --git a/docker-compose.yml b/docker-compose.yml index e5d91e7..75d2ec8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: '3.9' services: database: - container_name: postgres-db + container_name: db_bective image: postgres:12.8 restart: always env_file: @@ -11,23 +11,5 @@ services: - '5432:5432' volumes: - db:/var/lib/postgresql/data - backend: - container_name: backend_bective - env_file: - - .env - build: ./backend - ports: - - '8080:8080' - depends_on: - - database - restart: always - frontend: - container_name: frontend_bective - build: ./frontend - ports: - - '5173:5173' - depends_on: - - backend - restart: always volumes: db: diff --git a/docker-test-compose.yml b/docker-test-compose.yml new file mode 100644 index 0000000..4a8d0e8 --- /dev/null +++ b/docker-test-compose.yml @@ -0,0 +1,33 @@ +version: '3.9' + +services: + database: + container_name: db_bective + image: postgres:12.8 + restart: always + env_file: + - .env + ports: + - '5432:5432' + volumes: + - db:/var/lib/postgresql/data + backend: + container_name: backend_bective + env_file: + - .env + build: ./backend + ports: + - '8080:8080' + depends_on: + - database + restart: always + frontend: + container_name: frontend_bective + build: ./frontend + ports: + - '5173:5173' + depends_on: + - backend + restart: always +volumes: + db: diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 20e4bdc..479becc 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -3,6 +3,5 @@ WORKDIR /bective COPY package.json yarn.lock ./ RUN yarn install COPY . . -RUN yarn build EXPOSE 5173 -CMD ["yarn", "preview"] +CMD ["yarn", "dev"] diff --git a/frontend/src/components/Todos/GetTodo.tsx b/frontend/src/components/Todos/GetTodo.tsx index 3cf9342..95dd6bd 100644 --- a/frontend/src/components/Todos/GetTodo.tsx +++ b/frontend/src/components/Todos/GetTodo.tsx @@ -24,12 +24,12 @@ const GetTodoButton = () => { className={'get-todos-container'} style={{ backgroundColor: bgColorButton, color: colorText }} onMouseOver={() => { - setBgColorButton('rgb(49,45,45)'); - setColorText('rgb(239,94,94)'); + setBgColorButton('rgb(26,62,176)'); + setColorText('rgb(26,62,176)'); }} onMouseLeave={() => { - setBgColorButton('rgb(239,94,94)'); - setColorText('rgb(.gitignore,.gitignore,.gitignore)'); + setBgColorButton('rgb(26,62,176)'); + setColorText('rgb(26,62,176)'); }} >