feat: todo list
This commit is contained in:
parent
583e5d6beb
commit
8dc6d3363b
|
|
@ -42,9 +42,15 @@ 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) updateClaims(w http.ResponseWriter, r *http.Request) {
|
func (ctx *Context) UpdateForeignWishlist(w http.ResponseWriter, r *http.Request) {
|
||||||
user := ctx.Auth.ExpectUser(r)
|
user := ctx.Auth.ExpectUser(r)
|
||||||
|
if err := r.ParseForm(); err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
userReference := r.PathValue("userReference")
|
userReference := r.PathValue("userReference")
|
||||||
|
switch r.Form.Get("mode") {
|
||||||
|
case "claim":
|
||||||
claims := r.Form["unclaimed"]
|
claims := r.Form["unclaimed"]
|
||||||
unclaims := r.Form["claimed"]
|
unclaims := r.Form["claimed"]
|
||||||
err := user.ClaimGifts(claims, unclaims)
|
err := user.ClaimGifts(claims, unclaims)
|
||||||
|
|
@ -52,32 +58,16 @@ func (ctx *Context) updateClaims(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Error(w, "Failed to update claim...", http.StatusInternalServerError)
|
http.Error(w, "Failed to update claim...", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
http.Redirect(w, r, "/"+userReference, http.StatusSeeOther)
|
case "complete":
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *Context) completeGifts(w http.ResponseWriter, r *http.Request) {
|
|
||||||
user := ctx.Auth.ExpectUser(r)
|
|
||||||
userReference := r.PathValue("userReference")
|
|
||||||
claims := r.Form["claimed"]
|
claims := r.Form["claimed"]
|
||||||
err := user.CompleteGifts(claims)
|
err := user.CompleteGifts(claims)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Printf("Failed to complete gifts: %s\n", err)
|
||||||
http.Error(w, "Failed to complete gifts...", http.StatusInternalServerError)
|
http.Error(w, "Failed to complete gifts...", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
http.Redirect(w, r, "/"+userReference, http.StatusSeeOther)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *Context) UpdateForeignWishlist(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if err := r.ParseForm(); err != nil {
|
|
||||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch r.Form.Get("mode") {
|
|
||||||
case "claim":
|
|
||||||
ctx.updateClaims(w, r)
|
|
||||||
case "complete":
|
|
||||||
ctx.completeGifts(w, r)
|
|
||||||
default:
|
default:
|
||||||
http.Error(w, "Invalid mode", http.StatusBadRequest)
|
http.Error(w, "Invalid mode", http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
http.Redirect(w, r, "/"+userReference, http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import (
|
||||||
type HomeProps struct {
|
type HomeProps struct {
|
||||||
Username string
|
Username string
|
||||||
Gifts []db.Gift
|
Gifts []db.Gift
|
||||||
|
Todo []db.Gift
|
||||||
Reference string
|
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)
|
http.Error(w, "An error occurred while fetching your wishlist :(", http.StatusInternalServerError)
|
||||||
return
|
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)
|
templates.Execute(w, "home.gotmpl", p)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
33
db/user.go
33
db/user.go
|
|
@ -19,6 +19,8 @@ type Gift struct {
|
||||||
ClaimantId string
|
ClaimantId string
|
||||||
ClaimantName string
|
ClaimantName string
|
||||||
Sent bool
|
Sent bool
|
||||||
|
RecipientName string
|
||||||
|
RecipientRef string
|
||||||
}
|
}
|
||||||
|
|
||||||
func queryForUser(query string, args ...any) (*User, error) {
|
func queryForUser(query string, args ...any) (*User, error) {
|
||||||
|
|
@ -111,6 +113,37 @@ func (u *User) GetGifts() ([]Gift, error) {
|
||||||
return gifts, nil
|
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 {
|
func (u *User) AddGift(name string) error {
|
||||||
stmt := "INSERT INTO gift (name, recipient_id, creator_id) VALUES (?, ?, ?)"
|
stmt := "INSERT INTO gift (name, recipient_id, creator_id) VALUES (?, ?, ?)"
|
||||||
_, err := database.Exec(stmt, name, u.Id, u.Id)
|
_, err := database.Exec(stmt, name, u.Id, u.Id)
|
||||||
|
|
|
||||||
1
main.go
1
main.go
|
|
@ -39,6 +39,7 @@ func main() {
|
||||||
protectedMux.HandleFunc("POST /{userReference}/update", ctx.UpdateForeignWishlist)
|
protectedMux.HandleFunc("POST /{userReference}/update", ctx.UpdateForeignWishlist)
|
||||||
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 /todo/update", ctx.TodoUpdate)
|
||||||
protectedMux.HandleFunc("POST /logout", authMiddleware.LogoutPost)
|
protectedMux.HandleFunc("POST /logout", authMiddleware.LogoutPost)
|
||||||
|
|
||||||
http.Handle("/", authMiddleware)
|
http.Handle("/", authMiddleware)
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
<pre>{{.Reference}}</pre>
|
<pre>{{.Reference}}</pre>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<h2>Your list</h2>
|
<h2>Your wishlist</h2>
|
||||||
<form method="post" action="/wishlist/delete" onchange="acceptNames(this, 'deleteSubmit', 'gift')" autocomplete="off">
|
<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>
|
<button id="deleteSubmit" type="submit" name="mode" value="delete" disabled>Delete</button>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
@ -26,6 +26,32 @@
|
||||||
</form>
|
</form>
|
||||||
<form method="post" action="/wishlist/add">
|
<form method="post" action="/wishlist/add">
|
||||||
<input name="gift_name" required>
|
<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>
|
</form>
|
||||||
{{end}}
|
{{end}}
|
||||||
Loading…
Reference in New Issue