From aa023cf89e051a9f3282dd39d7509132d28c2788 Mon Sep 17 00:00:00 2001 From: Sam Rolfe Date: Fri, 7 Aug 2026 18:18:49 +1000 Subject: [PATCH] Phase 3: HTMX inline tag editing, swap animations, loading indicators, Alpine phone validation --- frontend/internal/handlers/handlers.go | 2 +- frontend/internal/handlers/tags.go | 20 +++++++++++ frontend/main.go | 1 + frontend/templates/account-panel.html | 1 + frontend/templates/base.html | 9 +++++ frontend/templates/tag-edit-inline.html | 45 +++++++++++++++++++++++++ frontend/templates/tag-list.html | 4 +-- frontend/templates/tag-public.html | 10 +++--- todo.txt | 4 +-- 9 files changed, 87 insertions(+), 9 deletions(-) create mode 100644 frontend/templates/tag-edit-inline.html diff --git a/frontend/internal/handlers/handlers.go b/frontend/internal/handlers/handlers.go index 3baf063..6430527 100644 --- a/frontend/internal/handlers/handlers.go +++ b/frontend/internal/handlers/handlers.go @@ -52,7 +52,7 @@ func LoadTemplates() (Templates, error) { "index": {dir + "/index.html"}, "register": {dir + "/register.html"}, "login": {dir + "/login.html"}, - "account": {dir + "/account.html", dir + "/account-panel.html", dir + "/tag-list.html"}, + "account": {dir + "/account.html", dir + "/account-panel.html", dir + "/tag-list.html", dir + "/tag-edit-inline.html"}, "edit": {dir + "/tag-edit.html"}, "public": {dir + "/tag-public.html"}, "notfound": {dir + "/not-found.html"}, diff --git a/frontend/internal/handlers/tags.go b/frontend/internal/handlers/tags.go index 6571e10..ca24809 100644 --- a/frontend/internal/handlers/tags.go +++ b/frontend/internal/handlers/tags.go @@ -87,6 +87,16 @@ func (a *App) EditTagPage(w http.ResponseWriter, r *http.Request) { a.render(w, r, "edit", "Edit tag", tag, "") } +// EditInlinePage returns the compact inline edit form for HTMX row editing. +func (a *App) EditInlinePage(w http.ResponseWriter, r *http.Request) { + uid, _ := auth.GetUserID(r) + tag, ok := a.loadOwnedTag(w, r, uid) + if !ok { + return + } + a.renderPartial(w, "account", "tag-edit-inline", tag) +} + func (a *App) EditTag(w http.ResponseWriter, r *http.Request) { uid, _ := auth.GetUserID(r) tag, ok := a.loadOwnedTag(w, r, uid) @@ -112,6 +122,16 @@ func (a *App) EditTag(w http.ResponseWriter, r *http.Request) { http.Error(w, "internal error", http.StatusInternalServerError) return } + // If this was an HTMX inline edit, return the refreshed account panel. + if r.Header.Get("HX-Request") == "true" { + tags, err := a.Queries.ListTagsByOwner(r.Context(), ownerID(uid)) + if err != nil { + http.Error(w, "internal error", http.StatusInternalServerError) + return + } + a.renderPartial(w, "account", "account-panel", accountData{Tags: tags}) + return + } http.Redirect(w, r, "/account", http.StatusSeeOther) } diff --git a/frontend/main.go b/frontend/main.go index cec8ada..2c58315 100644 --- a/frontend/main.go +++ b/frontend/main.go @@ -70,6 +70,7 @@ func main() { mux.Handle("GET /account", app.RequireAuth(app.Account)) mux.Handle("POST /account/tags", app.RequireAuth(app.AddTag)) mux.Handle("GET /account/tags/{id}/edit", app.RequireAuth(app.EditTagPage)) + mux.Handle("GET /account/tags/{id}/edit/inline", app.RequireAuth(app.EditInlinePage)) mux.Handle("POST /account/tags/{id}/edit", app.RequireAuth(app.EditTag)) mux.Handle("POST /account/tags/{id}/delete", app.RequireAuth(app.DeleteTag)) diff --git a/frontend/templates/account-panel.html b/frontend/templates/account-panel.html index b835065..167831f 100644 --- a/frontend/templates/account-panel.html +++ b/frontend/templates/account-panel.html @@ -6,6 +6,7 @@
+ Adding…
diff --git a/frontend/templates/base.html b/frontend/templates/base.html index 74f1c6e..254edfe 100644 --- a/frontend/templates/base.html +++ b/frontend/templates/base.html @@ -8,6 +8,15 @@ +