package handlers import ( "apjournal/config" "apjournal/internal/database/repos" "apjournal/internal/models" "apjournal/pkg/cache" "html/template" "log/slog" "net/http" "os" "strconv" "time" ) var defUS = models.UserScore{} // Handlers structure type Handlers struct { cfg config.Config log *slog.Logger repo repos.FullRepo mc cache.Cache } // NewHandlers constructor func NewHandlers( cfg config.Config, l *slog.Logger, repo repos.FullRepo, ) *Handlers { if l == nil { l = slog.New(slog.NewJSONHandler(os.Stdout, nil)) } h := &Handlers{ cfg: cfg, log: l, repo: repo, mc: cache.MemCache, } return h } func (h *Handlers) Ping(w http.ResponseWriter, r *http.Request) { h.log.Info("got ping request") w.Write([]byte("pong")) } func (h *Handlers) MainPage(w http.ResponseWriter, r *http.Request) { tmpl, err := template.ParseGlob("components/*.html") if err != nil { abortWithError(w, err.Error()) return } // get recommendations defUS.Recommendations, err = h.fetchRecommendations("", 5) if err != nil { panic(err) } usernameRaw := r.Context().Value("username") h.log.Info("got mainpage request", "username", usernameRaw) if usernameRaw == nil { tmpl.ExecuteTemplate(w, "main", defUS) return } username := usernameRaw.(string) if username == "" { tmpl.ExecuteTemplate(w, "main", defUS) return } userScore, err := h.repo.DBUserScoreGet(username) if err != nil { h.log.Warn("got db err", "err", err) tmpl.ExecuteTemplate(w, "main", defUS) return } userScore.Actions, err = h.repo.DBActionList(username) if err != nil { abortWithError(w, err.Error()) return } userScore.Recommendations, err = h.fetchRecommendations(username, 5) if err != nil { abortWithError(w, err.Error()) return } tmpl.ExecuteTemplate(w, "main", userScore) } func (h *Handlers) HandleForm(w http.ResponseWriter, r *http.Request) { r.ParseForm() h.log.Info("got postform request", "payload", r.PostForm) magnitude := uint8(1) mS := r.PostFormValue("magnitude") if mS != "1" { u64, err := strconv.ParseUint(mS, 10, 64) magnitude = uint8(u64) if err != nil { h.log.Warn("failed to parse magnitude", "error", err, "payload", r.PostForm) magnitude = uint8(1) } } repeat := false var at models.ActionType switch r.PostFormValue("act_type") { case "plus": at = models.ActionTypePlus case "minus": at = models.ActionTypeMinus repeat = true default: h.log.Warn("uknown actiontype", "type", r.PostFormValue("act_type")) } // if r.PostFormValue("repeatable") == "on" { // repeat = true // } // convert map to action object act := models.Action{ Name: r.PostFormValue("name"), Magnitude: magnitude, Type: at, Repeatable: repeat, CreatedAt: time.Now(), } // get username from ctx username := r.Context().Value("username").(string) h.log.Info("got username from ctx", "username", username) userScore, err := h.repo.DBUserScoreGet(username) if err != nil { abortWithError(w, err.Error()) return } act.Username = userScore.Username if err := h.repo.DBActionCreate(&act); err != nil { abortWithError(w, err.Error()) return } http.Redirect(w, r, "/", 302) } func (h *Handlers) UserScoreWithActionsByUsername( username string, ) (*models.UserScore, error) { userScore, err := h.repo.DBUserScoreGet(username) if err != nil { return nil, err } list, err := h.repo.DBActionList(username) if err != nil { return nil, err } userScore.Actions = list return userScore, nil } func (h *Handlers) HandleDoneAction(w http.ResponseWriter, r *http.Request) { r.ParseForm() actionName := r.PostFormValue("name") username := r.Context().Value("username").(string) h.log.Info("got postform request", "name", actionName, "username", username) userScore, err := h.UserScoreWithActionsByUsername(username) if err != nil { abortWithError(w, err.Error()) return } // get action by name action, err := h.repo.DBActionGetByName(actionName) magnitude := int8(action.Magnitude) if action.Type == models.ActionTypeMinus { magnitude *= -1 } // change counter of user score userScore.Score += magnitude // disable action if repetable if err := h.repo.DBActionDone(actionName); err != nil { abortWithError(w, err.Error()) return } // update score in db if err := h.repo.DBUserScoreUpdate(userScore); err != nil { abortWithError(w, err.Error()) return } tmpl := template.Must(template.ParseGlob("components/*.html")) tmpl.ExecuteTemplate(w, "main", userScore) }