add new habit pages
Marco Andronaco andronacomarco@gmail.com
Sun, 13 Oct 2024 16:18:56 +0200
6 files changed,
110 insertions(+),
7 deletions(-)
M
src/app/functions.go
→
src/app/functions.go
@@ -31,8 +31,9 @@ classBad = "bad"
) var ( - validUsername = regexp.MustCompile(`(?i)^[a-z0-9._-]+$`) - validEmail = regexp.MustCompile(`^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$`) + validUsername = regexp.MustCompile(`(?i)^[a-z0-9._-]+$`) + validEmail = regexp.MustCompile(`^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$`) + validHabitName = regexp.MustCompile(`(?i)^[a-z0-9._,\s)(-]+$`) ) func getUserByName(username string, excluding uint) (user User, err error) {@@ -56,6 +57,10 @@ return "", fmt.Errorf("invalid email")
} return email, nil +} + +func checkHabitName(name string) bool { + return len(name) < 50 && validHabitName.MatchString(name) } func login(w http.ResponseWriter, userID uint, remember bool) {@@ -146,9 +151,15 @@ return d.String()
} func toHabitDisplay(habit Habit) HabitDisplay { + var lastAck string + if habit.LastAck == nil { + lastAck = "-" + } else { + lastAck = formatDuration(time.Since(*habit.LastAck)) + } return HabitDisplay{ Name: habit.Name, - LastAck: formatDuration(time.Since(habit.LastAck)), + LastAck: lastAck, Disabled: habit.Disabled, Class: classGood, }
M
src/app/handlers.go
→
src/app/handlers.go
@@ -2,6 +2,7 @@ package app
import ( "net/http" + "strconv" "time" )@@ -31,6 +32,49 @@
xt.ExecuteTemplate(w, "habits.tmpl", data) } +func getNewPositiveHandler(w http.ResponseWriter, r *http.Request) { + data := map[string]interface{}{"Negative": false} + xt.ExecuteTemplate(w, "new.tmpl", data) +} + +func getNewNegativeHandler(w http.ResponseWriter, r *http.Request) { + data := map[string]interface{}{"Negative": true} + xt.ExecuteTemplate(w, "new.tmpl", data) +} + +func postNewHandler(w http.ResponseWriter, r *http.Request) { + negative := r.FormValue("negative") == "on" + name := r.FormValue("name") + + if !checkHabitName(name) { + http.Error(w, "Bad habit name.", http.StatusBadRequest) + } + + var days uint + if !negative { + res, err := strconv.ParseUint(r.FormValue("days"), 10, 64) + if err != nil { + http.Error(w, "Bad days value.", http.StatusBadRequest) + return + } + days = uint(res) + } + + user, ok := getLoggedUser(r) + if !ok { + http.Error(w, "Could not get logged user", http.StatusInternalServerError) + } + + db.Create(&Habit{ + UserID: user.ID, + Name: name, + Days: days, + Negative: negative, + }) + + http.Redirect(w, r, "/habits", http.StatusFound) +} + func getRegisterHandler(w http.ResponseWriter, r *http.Request) { xt.ExecuteTemplate(w, "auth-register.tmpl", nil) }@@ -41,6 +85,7 @@ if err != nil {
xt.ExecuteTemplate(w, "auth-login.tmpl", nil) return } + http.Redirect(w, r, "/habits", http.StatusFound) }
M
src/app/init.go
→
src/app/init.go
@@ -34,7 +34,7 @@ gorm.Model
UserID uint Name string Days uint - LastAck time.Time + LastAck *time.Time Negative bool Disabled bool@@ -115,9 +115,12 @@ if err != nil {
log.Fatal(err) } - // Handle routes + // App http.HandleFunc("GET /", getIndexHandler) http.HandleFunc("GET /habits", loginRequired(getHabitsHandler)) + http.HandleFunc("GET /new/positive", loginRequired(getNewPositiveHandler)) + http.HandleFunc("GET /new/negative", loginRequired(getNewNegativeHandler)) + http.HandleFunc("POST /new", loginRequired(postNewHandler)) // Auth http.HandleFunc("GET /register", getRegisterHandler)
M
static/style.css
→
static/style.css
@@ -11,3 +11,10 @@
label > input { max-width: 250px; } + +.habits-title { + display: grid; + grid-template-columns: auto auto; + justify-content: space-between; + align-items: center +}
M
templates/habits.tmpl
→
templates/habits.tmpl
@@ -5,7 +5,10 @@
{{define "content" -}} <h1>Welcome, <i>{{.User.Username}}</i>!</h1> <a href="/logout">Logout</a><br /> - <h4>Positive habits</h4> + <div class="habits-title"> + <h4>Positive habits</h4> + <a href="/new/positive" class="button">+ Add</a> + </div> <table> <thead> <tr>@@ -26,7 +29,10 @@ </tbody>
<tfoot></tfoot> </table> - <h4>Negative habits</h4> + <div class="habits-title"> + <h4>Negative habits</h4> + <a href="/new/negative" class="button">+ Add</a> + </div> <table> <thead> <tr>
A
templates/new.tmpl
@@ -0,0 +1,31 @@
+{{ extends "base.tmpl" }} + +{{define "title" -}}New habit{{end}} + +{{define "content" -}} + <h1>New habit</h1> + <h4> + {{ if .Negative }} + Which negative habit are you trying to stop? + {{ else }} + Which positive habit are you trying to get?<br /> + How often would you like to do it? + {{ end }} + </h4> + + <form method="post" action="/new"> + <label> + <span>Name:</span> + <input type="text" name="name" autocomplete="off" placeholder="Name" required /> + </label> + {{ if .Negative }} + <input type="hidden" name="negative" value="on" /> + {{ else }} + <label> + <span>Days:</span> + <input type="number" name="days" autocomplete="off" placeholder="Days" min="1" max="60" required /> + </label> + {{ end }} + <input type="submit" value="Create" /> + </form> +{{end}}