package api import ( "github.com/gin-gonic/gin" "github.com/gissleh/stufflog/database" "github.com/gissleh/stufflog/internal/auth" "github.com/gissleh/stufflog/internal/generate" "github.com/gissleh/stufflog/internal/slerrors" "github.com/gissleh/stufflog/models" "github.com/gissleh/stufflog/services" "time" ) func Goal(g *gin.RouterGroup, db database.Database) { l := services.Loader{DB: db} g.GET("/", handler("goals", func(c *gin.Context) (interface{}, error) { filter := models.GoalFilter{} if value := c.Query("minTime"); value != "" { minTime, err := time.Parse(time.RFC3339Nano, value) if err != nil { return nil, slerrors.BadRequest("Invalid minTime") } minTime = minTime.UTC() filter.MinTime = &minTime } else { lastMonth := time.Now().Add(-30 * 24 * time.Hour).UTC() filter.MinTime = &lastMonth } if value := c.Query("maxTime"); value != "" { maxTime, err := time.Parse(time.RFC3339Nano, value) if err != nil { return nil, slerrors.BadRequest("Invalid maxTime") } maxTime = maxTime.UTC() filter.MaxTime = &maxTime } if value := c.Query("includesTime"); value != "" { includesTime, err := time.Parse(time.RFC3339Nano, value) if err != nil { return nil, slerrors.BadRequest("Invalid includesTime") } includesTime = includesTime.UTC() filter.IncludesTime = &includesTime } return l.ListGoals(c.Request.Context(), filter) })) g.GET("/:id", handler("goal", func(c *gin.Context) (interface{}, error) { return l.FindGoal(c.Request.Context(), c.Param("id")) })) g.POST("/", handler("goal", func(c *gin.Context) (interface{}, error) { goal := models.Goal{} err := c.BindJSON(&goal) if err != nil { return nil, slerrors.BadRequest("Invalid JSON") } goal.ID = generate.GoalID() goal.UserID = auth.UserID(c) if goal.Amount <= 0 { return nil, slerrors.BadRequest("Goal amount must be more than 0.") } if goal.StartTime.IsZero() { return nil, slerrors.BadRequest("Start time must be set.") } if goal.EndTime.IsZero() { return nil, slerrors.BadRequest("End time must be set.") } if !goal.EndTime.After(goal.StartTime) { return nil, slerrors.BadRequest("Start time must be before end time.") } goal.StartTime = goal.StartTime.UTC() goal.EndTime = goal.EndTime.UTC() group, err := db.Groups().Find(c.Request.Context(), goal.GroupID) if err != nil { return nil, err } goal.GroupID = group.ID if goal.ItemID != nil { item, err := l.FindItem(c.Request.Context(), *goal.ItemID) if err != nil { return nil, slerrors.BadRequest("Item could not be found.") } if item.GroupID != goal.GroupID { return nil, slerrors.BadRequest("Item is not in group.") } } err = db.Goals().Insert(c.Request.Context(), goal) if err != nil { return nil, err } return l.FindGoal(c.Request.Context(), goal.ID) })) g.PUT("/:id", handler("goal", func(c *gin.Context) (interface{}, error) { update := models.GoalUpdate{} err := c.BindJSON(&update) if err != nil { return nil, slerrors.BadRequest("Invalid JSON") } goal, err := l.FindGoal(c.Request.Context(), c.Param("id")) if err != nil { return nil, err } goal.StartTime = goal.StartTime.UTC() goal.EndTime = goal.EndTime.UTC() goal.Update(update) if goal.Amount <= 0 { return nil, slerrors.BadRequest("Goal amount must be more than 0.") } if !goal.EndTime.After(goal.StartTime) { return nil, slerrors.BadRequest("Start time must be before end time.") } if goal.ItemID != nil && update.ItemID != nil { item, err := l.FindItem(c.Request.Context(), *goal.ItemID) if err != nil { return nil, slerrors.BadRequest("Item could not be found.") } if item.GroupID != goal.GroupID { return nil, slerrors.BadRequest("Item is not in group.") } } err = db.Goals().Update(c.Request.Context(), goal.Goal) if err != nil { return nil, err } return goal, nil })) g.DELETE("/:id", handler("goal", func(c *gin.Context) (interface{}, error) { goal, err := l.FindGoal(c.Request.Context(), c.Param("id")) if err != nil { return nil, err } err = db.Goals().Delete(c.Request.Context(), goal.Goal) if err != nil { return nil, err } return goal, nil })) }