From 029c01cd32c069061a3d1ff7f30750fa44f669de Mon Sep 17 00:00:00 2001 From: Tim Wundenberg Date: Sat, 3 Jan 2026 20:53:56 +0100 Subject: [PATCH] feat(budget): further improvements --- internal/budget/handler.go | 93 ++++++++++++++------------ internal/budget/template.templ | 115 +++++++++++++++++++++++---------- internal/core/breadcrumb.templ | 13 ++++ internal/core/layout.templ | 16 +++-- static/js/layout.js | 15 ----- 5 files changed, 155 insertions(+), 97 deletions(-) create mode 100644 internal/core/breadcrumb.templ diff --git a/internal/budget/handler.go b/internal/budget/handler.go index d81ac9e..bac366e 100644 --- a/internal/budget/handler.go +++ b/internal/budget/handler.go @@ -2,7 +2,6 @@ package budget import ( "fmt" - "log/slog" "math" "net/http" "spend-sparrow/internal/core" @@ -33,6 +32,7 @@ func NewHandler(s Service, r *core.Render) Handler { func (h HandlerImpl) Handle(r *http.ServeMux) { r.Handle("GET /budget", h.handlePage()) + r.Handle("GET /budget/new", h.handleNew()) r.Handle("GET /budget/{id}", h.handleEdit()) r.Handle("POST /budget/{id}", h.handlePost()) // r.Handle("DELETE /budget/{id}", h.handleDelete()) @@ -59,7 +59,49 @@ func (h HandlerImpl) handlePage() http.HandlerFunc { } } +func (h HandlerImpl) handleNew() http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + core.UpdateSpan(r) + + user := core.GetUser(r) + if user == nil { + core.DoRedirect(w, r, "/auth/signin") + return + } + + comp := editNew() + h.r.RenderLayout(r, w, comp, user) + } +} + func (h HandlerImpl) handleEdit() http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + core.UpdateSpan(r) + + user := core.GetUser(r) + if user == nil { + core.DoRedirect(w, r, "/auth/signin") + return + } + + id, err := uuid.Parse(r.PathValue("id")) + if err != nil { + core.HandleError(w, r, fmt.Errorf("could not parse Id: %w", core.ErrBadRequest)) + return + } + + budget, err := h.s.Get(r.Context(), user, id) + if err != nil { + core.HandleError(w, r, fmt.Errorf("could not parse Id: %w", core.ErrBadRequest)) + return + } + + comp := edit(*budget) + h.r.RenderLayout(r, w, comp, user) + } +} + +func (h HandlerImpl) handlePost() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { core.UpdateSpan(r) @@ -83,35 +125,6 @@ func (h HandlerImpl) handleEdit() http.HandlerFunc { // } } - comp := editNew() - h.r.Render(r, w, comp) - } -} - -func (h HandlerImpl) handlePost() http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - core.UpdateSpan(r) - - user := core.GetUser(r) - if user == nil { - core.DoRedirect(w, r, "/auth/signin") - return - } - - var ( - id uuid.UUID - err error - ) - - idStr := r.PathValue("id") - if idStr != "new" { - id, err = uuid.Parse(idStr) - if err != nil { - core.HandleError(w, r, fmt.Errorf("could not parse Id: %w", core.ErrBadRequest)) - return - } - } - valueF, err := strconv.ParseFloat(r.FormValue("value"), 64) if err != nil { core.HandleError(w, r, fmt.Errorf("could not parse value: %w", core.ErrBadRequest)) @@ -120,9 +133,8 @@ func (h HandlerImpl) handlePost() http.HandlerFunc { value := int64(math.Round(valueF * DECIMALS_MULTIPLIER)) input := Budget{ - Id: id, Value: value, - Description: r.FormValue("description"), + Description: r.FormValue("name"), } var budget *Budget @@ -132,17 +144,14 @@ func (h HandlerImpl) handlePost() http.HandlerFunc { core.HandleError(w, r, err) return } - } else { - budget, err = h.s.Update(r.Context(), user, input) - if err != nil { - core.HandleError(w, r, err) - return - } + // } else { + // budget, err = h.s.Update(r.Context(), user, input) + // if err != nil { + // core.HandleError(w, r, err) + // return + // } } - // To disable unused variable - slog.Info("test", "item", budget) - // comp := item() - // h.r.Render(r, w, comp) + core.DoRedirect(w, r, "/budget/"+budget.Id.String()) } } diff --git a/internal/budget/template.templ b/internal/budget/template.templ index 89cb5d4..83787ea 100644 --- a/internal/budget/template.templ +++ b/internal/budget/template.templ @@ -1,9 +1,12 @@ package budget -import "spend-sparrow/internal/template/svg" +import ( + "spend-sparrow/internal/core" + "spend-sparrow/internal/template/svg" +) templ page(budgets []Budget) { - + @core.Breadcrumb([]string{"Home", "Budget"}, []string{"/", "/budget"})
@newItem() for _,budget:=range(budgets ) { @@ -13,64 +16,110 @@ templ page(budgets []Budget) { } templ editNew() { - -
-
+
+ @core.Breadcrumb([]string{"Home", "Budget", "New"}, []string{"/", "/budget", "/budget/new"}) +
+ -
- - - -
+
+ + + @svg.Cancel() + + + Cancel + + + +
+ +
+ +} + +templ edit(budget Budget) { +
+ @core.Breadcrumb([]string{"Home", "Budget", budget.Description}, []string{"/", "/budget", "/budget/" + budget.Id.String()}) +
+
+ + + + +
+ + + @svg.Cancel() + + + Cancel + + + +
+
+
+
} templ newItem() { - + } templ item(budget Budget) { -
+ { budget.Description } { 200 }€ -
+ } diff --git a/internal/core/breadcrumb.templ b/internal/core/breadcrumb.templ new file mode 100644 index 0000000..badd880 --- /dev/null +++ b/internal/core/breadcrumb.templ @@ -0,0 +1,13 @@ +package core + +templ Breadcrumb(elements []string, links []string) { +
+ for i, element := range(elements) { + if (i>0) { + >{ element } + } else { + { element } + } + } +
+} diff --git a/internal/core/layout.templ b/internal/core/layout.templ index 348274f..dffc9fb 100644 --- a/internal/core/layout.templ +++ b/internal/core/layout.templ @@ -1,6 +1,9 @@ package core -import "spend-sparrow/internal/template/svg" +import ( + "spend-sparrow/internal/template/svg" + "strings" +) func layoutLinkClass(isActive bool) string { common := "text-2xl p-2 text-gray-900 decoration-yellow-400 decoration-[0.25rem] hover:bg-gray-200 rounded-lg" @@ -37,7 +40,6 @@ templ Layout(slot templ.Component, user templ.Component, loggedIn bool, path str -