feat: claimable gifts

This commit is contained in:
Teajey 2024-05-07 21:29:07 +12:00
parent ad1c53a611
commit 3890c93928
Signed by: Teajey
GPG Key ID: 970E790FE834A713
5 changed files with 101 additions and 14 deletions

View File

@ -45,3 +45,21 @@ func (ctx *Context) WishlistDelete(w http.ResponseWriter, r *http.Request) {
} }
http.Redirect(w, r, "/", http.StatusSeeOther) http.Redirect(w, r, "/", http.StatusSeeOther)
} }
func (ctx *Context) UpdateClaim(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")
claims := r.Form["claim"]
unclaims := r.Form["unclaim"]
err := user.ClaimGifts(claims, unclaims)
println("err?", err)
if err != nil {
http.Error(w, "Failed to update claim...", http.StatusInternalServerError)
return
}
http.Redirect(w, r, "/"+userReference, http.StatusSeeOther)
}

View File

@ -8,8 +8,10 @@ import (
) )
type ForeignWishlistProps struct { type ForeignWishlistProps struct {
Username string CurrentUserId string
Gifts []db.Gift Username string
UserReference string
Gifts []db.Gift
} }
func (ctx *Context) ViewForeignWishlist(w http.ResponseWriter, r *http.Request) { func (ctx *Context) ViewForeignWishlist(w http.ResponseWriter, r *http.Request) {
@ -31,9 +33,10 @@ func (ctx *Context) ViewForeignWishlist(w http.ResponseWriter, r *http.Request)
} }
gifts, err := otherUser.GetGifts() gifts, err := otherUser.GetGifts()
if err != nil { if err != nil {
log.Printf("An error occurred while fetching %s's wishlist: %s\n", otherUser.Name, err)
http.Error(w, "An error occurred while fetching this user's wishlist :(", http.StatusInternalServerError) http.Error(w, "An error occurred while fetching this user's wishlist :(", http.StatusInternalServerError)
return return
} }
p := ForeignWishlistProps{Username: otherUser.Name, Gifts: gifts} p := ForeignWishlistProps{CurrentUserId: user.Id, Username: otherUser.Name, UserReference: userReference, Gifts: gifts}
templates.Execute(w, "foreign_wishlist.gotmpl", p) templates.Execute(w, "foreign_wishlist.gotmpl", p)
} }

View File

@ -14,8 +14,10 @@ type User struct {
} }
type Gift struct { type Gift struct {
Id string Id string
Name string Name string
ClaimantId string
ClaimantName string
} }
func queryForUser(query string, args ...any) (*User, error) { func queryForUser(query string, args ...any) (*User, error) {
@ -78,7 +80,7 @@ func (u *User) GetPassHash() ([]byte, error) {
} }
func (u *User) GetGifts() ([]Gift, error) { func (u *User) GetGifts() ([]Gift, error) {
stmt := "SELECT gift.id, gift.name FROM gift JOIN user ON gift.recipient_id = user.id WHERE user.id = ?" stmt := "SELECT gift.id, gift.name, claimant.id, claimant.name FROM gift JOIN user ON gift.recipient_id = user.id LEFT JOIN user AS claimant ON gift.claimant_id = claimant.id WHERE user.id = ? ORDER BY gift.name DESC"
rows, err := database.Query(stmt, u.Id) rows, err := database.Query(stmt, u.Id)
if err != nil { if err != nil {
return nil, err return nil, err
@ -88,10 +90,14 @@ func (u *User) GetGifts() ([]Gift, error) {
for rows.Next() { for rows.Next() {
var id string var id string
var name string var name string
rows.Scan(&id, &name) var claimantId string
var claimantName string
rows.Scan(&id, &name, &claimantId, &claimantName)
gift := Gift{ gift := Gift{
Id: id, Id: id,
Name: name, Name: name,
ClaimantId: claimantId,
ClaimantName: claimantName,
} }
gifts = append(gifts, gift) gifts = append(gifts, gift)
} }
@ -123,3 +129,38 @@ func (u *User) RemoveGift(id string) error {
} }
return nil return nil
} }
func (u *User) executeClaims(tx *sql.Tx, claims, unclaims []string) error {
claimStmt := "UPDATE gift SET claimant_id = ? WHERE id = ?"
unclaimStmt := "UPDATE gift SET claimant_id = NULL WHERE id = ?"
for _, id := range claims {
println("exec claim:", claimStmt, u.Id, id)
_, err := tx.Exec(claimStmt, u.Id, id)
if err != nil {
return err
}
}
for _, id := range unclaims {
_, err := tx.Exec(unclaimStmt, id)
if err != nil {
return err
}
}
return nil
}
func (u *User) ClaimGifts(claims, unclaims []string) error {
tx, err := database.Begin()
if err != nil {
return err
}
err = u.executeClaims(tx, claims, unclaims)
if err != nil {
err = tx.Rollback()
return err
}
err = tx.Commit()
return err
}

View File

@ -36,6 +36,7 @@ func main() {
protectedMux.HandleFunc("GET /", ctx.Home) protectedMux.HandleFunc("GET /", ctx.Home)
protectedMux.HandleFunc("GET /{userReference}", ctx.ViewForeignWishlist) protectedMux.HandleFunc("GET /{userReference}", ctx.ViewForeignWishlist)
protectedMux.HandleFunc("POST /{userReference}/update_claim", ctx.UpdateClaim)
protectedMux.HandleFunc("POST /wishlist/add", ctx.WishlistAdd) protectedMux.HandleFunc("POST /wishlist/add", ctx.WishlistAdd)
protectedMux.HandleFunc("POST /wishlist/delete", ctx.WishlistDelete) protectedMux.HandleFunc("POST /wishlist/delete", ctx.WishlistDelete)
protectedMux.HandleFunc("POST /logout", authMiddleware.LogoutPost) protectedMux.HandleFunc("POST /logout", authMiddleware.LogoutPost)

View File

@ -8,9 +8,33 @@
</ul> </ul>
</nav> </nav>
<h2>{{.Username}}'s list</h2> <h2>{{.Username}}'s list</h2>
<ul> <form method="post" action="/{{.UserReference}}/update_claim" autocomplete="off">
{{range .Gifts}} <input type="submit" value="Update">
<li>{{.Name}}</li> <ul>
{{end}} {{range .Gifts}}
</ul> <li>
{{if eq .ClaimantId $.CurrentUserId}}
<label>
<input type="checkbox" name="unclaim" value="{{.Id}}">
{{.Name}}
</label>
<span style="color: blue;">Claimed by you</span>
{{else}}
{{if .ClaimantId}}
<label>
<input type="checkbox" disabled>
{{.Name}}
</label>
<span style="color: red;">Claimed by {{.ClaimantName}}</span>
{{else}}
<label>
<input type="checkbox" name="claim" value="{{.Id}}">
{{.Name}}
</label>
{{end}}
{{end}}
</li>
{{end}}
</ul>
</form>
{{end}} {{end}}