feat: todo list

This commit is contained in:
Teajey 2024-05-13 17:33:49 +12:00
parent 583e5d6beb
commit 8dc6d3363b
Signed by: Teajey
GPG Key ID: 970E790FE834A713
6 changed files with 125 additions and 35 deletions

View File

@ -42,42 +42,32 @@ func (ctx *Context) WishlistDelete(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/", http.StatusSeeOther)
}
func (ctx *Context) updateClaims(w http.ResponseWriter, r *http.Request) {
user := ctx.Auth.ExpectUser(r)
userReference := r.PathValue("userReference")
claims := r.Form["unclaimed"]
unclaims := r.Form["claimed"]
err := user.ClaimGifts(claims, unclaims)
if err != nil {
http.Error(w, "Failed to update claim...", http.StatusInternalServerError)
return
}
http.Redirect(w, r, "/"+userReference, http.StatusSeeOther)
}
func (ctx *Context) completeGifts(w http.ResponseWriter, r *http.Request) {
user := ctx.Auth.ExpectUser(r)
userReference := r.PathValue("userReference")
claims := r.Form["claimed"]
err := user.CompleteGifts(claims)
if err != nil {
http.Error(w, "Failed to complete gifts...", http.StatusInternalServerError)
return
}
http.Redirect(w, r, "/"+userReference, http.StatusSeeOther)
}
func (ctx *Context) UpdateForeignWishlist(w http.ResponseWriter, r *http.Request) {
user := ctx.Auth.ExpectUser(r)
if err := r.ParseForm(); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
userReference := r.PathValue("userReference")
switch r.Form.Get("mode") {
case "claim":
ctx.updateClaims(w, r)
claims := r.Form["unclaimed"]
unclaims := r.Form["claimed"]
err := user.ClaimGifts(claims, unclaims)
if err != nil {
http.Error(w, "Failed to update claim...", http.StatusInternalServerError)
return
}
case "complete":
ctx.completeGifts(w, r)
claims := r.Form["claimed"]
err := user.CompleteGifts(claims)
if err != nil {
log.Printf("Failed to complete gifts: %s\n", err)
http.Error(w, "Failed to complete gifts...", http.StatusInternalServerError)
return
}
default:
http.Error(w, "Invalid mode", http.StatusBadRequest)
}
http.Redirect(w, r, "/"+userReference, http.StatusSeeOther)
}

View File

@ -10,6 +10,7 @@ import (
type HomeProps struct {
Username string
Gifts []db.Gift
Todo []db.Gift
Reference string
}
@ -20,6 +21,11 @@ func (ctx *Context) Home(w http.ResponseWriter, r *http.Request) {
http.Error(w, "An error occurred while fetching your wishlist :(", http.StatusInternalServerError)
return
}
p := HomeProps{Username: user.Name, Gifts: gifts, Reference: user.Reference}
todo, err := user.GetTodo()
if err != nil {
http.Error(w, "An error occurred while fetching your wishlist :(", http.StatusInternalServerError)
return
}
p := HomeProps{Username: user.Name, Gifts: gifts, Todo: todo, Reference: user.Reference}
templates.Execute(w, "home.gotmpl", p)
}

34
context/todo_update.go Normal file
View File

@ -0,0 +1,34 @@
package context
import (
"log"
"net/http"
)
func (ctx *Context) TodoUpdate(w http.ResponseWriter, r *http.Request) {
user := ctx.Auth.ExpectUser(r)
if err := r.ParseForm(); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
switch r.Form.Get("mode") {
case "unclaim":
unclaims := r.Form["gift"]
err := user.ClaimGifts([]string{}, unclaims)
if err != nil {
http.Error(w, "Failed to update claim...", http.StatusInternalServerError)
return
}
case "complete":
claims := r.Form["gift"]
err := user.CompleteGifts(claims)
if err != nil {
log.Printf("Failed to complete gifts: %s\n", err)
http.Error(w, "Failed to complete gifts...", http.StatusInternalServerError)
return
}
default:
http.Error(w, "Invalid mode", http.StatusBadRequest)
}
http.Redirect(w, r, "/", http.StatusSeeOther)
}

View File

@ -14,11 +14,13 @@ type User struct {
}
type Gift struct {
Id string
Name string
ClaimantId string
ClaimantName string
Sent bool
Id string
Name string
ClaimantId string
ClaimantName string
Sent bool
RecipientName string
RecipientRef string
}
func queryForUser(query string, args ...any) (*User, error) {
@ -111,6 +113,37 @@ func (u *User) GetGifts() ([]Gift, error) {
return gifts, nil
}
func (u *User) GetTodo() ([]Gift, error) {
stmt := "SELECT gift.id, gift.name, gift.sent, recipient.name, recipient.reference FROM gift JOIN user ON gift.claimant_id = user.id JOIN user AS recipient ON gift.recipient_id = recipient.id WHERE user.id = ? ORDER BY gift.sent, gift.name DESC"
rows, err := database.Query(stmt, u.Id)
if err != nil {
return nil, err
}
defer rows.Close()
gifts := []Gift{}
for rows.Next() {
var id string
var name string
var sent bool
var recipientName string
var recipientRef string
rows.Scan(&id, &name, &sent, &recipientName, &recipientRef)
gift := Gift{
Id: id,
Name: name,
Sent: sent,
RecipientName: recipientName,
RecipientRef: recipientRef,
}
gifts = append(gifts, gift)
}
err = rows.Err()
if err != nil {
return nil, err
}
return gifts, nil
}
func (u *User) AddGift(name string) error {
stmt := "INSERT INTO gift (name, recipient_id, creator_id) VALUES (?, ?, ?)"
_, err := database.Exec(stmt, name, u.Id, u.Id)

View File

@ -39,6 +39,7 @@ func main() {
protectedMux.HandleFunc("POST /{userReference}/update", ctx.UpdateForeignWishlist)
protectedMux.HandleFunc("POST /wishlist/add", ctx.WishlistAdd)
protectedMux.HandleFunc("POST /wishlist/delete", ctx.WishlistDelete)
protectedMux.HandleFunc("POST /todo/update", ctx.TodoUpdate)
protectedMux.HandleFunc("POST /logout", authMiddleware.LogoutPost)
http.Handle("/", authMiddleware)

View File

@ -10,7 +10,7 @@
<pre>{{.Reference}}</pre>
</dd>
</dl>
<h2>Your list</h2>
<h2>Your wishlist</h2>
<form method="post" action="/wishlist/delete" onchange="acceptNames(this, 'deleteSubmit', 'gift')" autocomplete="off">
<button id="deleteSubmit" type="submit" name="mode" value="delete" disabled>Delete</button>
<ul>
@ -26,6 +26,32 @@
</form>
<form method="post" action="/wishlist/add">
<input name="gift_name" required>
<input type="submit">
<button type="submit">Add gift idea</button>
</form>
<h2>Your todo list</h2>
<form method="post" action="/todo/update"
onchange="acceptNames(this, 'unclaimSubmit', 'gift'); acceptNames(this, 'completeSubmit', 'gift')" autocomplete="off">
<button id="unclaimSubmit" type="submit" name="mode" value="unclaim" disabled>Unclaim</button>
<button id="completeSubmit" type="submit" name="mode" value="complete" disabled>Complete</button>
<ul>
{{range .Todo}}
<li>
<label>
{{if .Sent}}
<input type="checkbox" disabled>
{{else}}
<input type="checkbox" name="gift" value="{{.Id}}">
{{end}}
<em>
{{if .Sent}}
<s>{{.Name}}</s>
{{else}}
{{.Name}}
{{end}}
</em> for <a href="/{{.RecipientRef}}">{{.RecipientName}}</a>
</label>
</li>
{{end}}
</ul>
</form>
{{end}}