package handler import ( "net/http" "spend-sparrow/internal/handler/middleware" "spend-sparrow/internal/service" tr "spend-sparrow/internal/template/transaction_recurring" t "spend-sparrow/internal/template/treasurechest" "spend-sparrow/internal/types" "spend-sparrow/internal/utils" "github.com/a-h/templ" "github.com/google/uuid" ) type TreasureChest interface { Handle(router *http.ServeMux) } type TreasureChestImpl struct { s service.TreasureChest transactionRecurring service.TransactionRecurring r *Render } func NewTreasureChest(s service.TreasureChest, transactionRecurring service.TransactionRecurring, r *Render) TreasureChest { return TreasureChestImpl{ s: s, transactionRecurring: transactionRecurring, r: r, } } func (h TreasureChestImpl) Handle(r *http.ServeMux) { r.Handle("GET /treasurechest", h.handleTreasureChestPage()) r.Handle("GET /treasurechest/{id}", h.handleTreasureChestItemComp()) r.Handle("POST /treasurechest/{id}", h.handleUpdateTreasureChest()) r.Handle("DELETE /treasurechest/{id}", h.handleDeleteTreasureChest()) } func (h TreasureChestImpl) handleTreasureChestPage() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { user := middleware.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return } treasureChests, err := h.s.GetAll(user) if err != nil { handleError(w, r, err) return } transactionsRecurring, err := h.transactionRecurring.GetAll(user) if err != nil { handleError(w, r, err) return } monthlySums := h.calculateMonthlySums(treasureChests, transactionsRecurring) comp := t.TreasureChest(treasureChests, monthlySums) h.r.RenderLayout(r, w, comp, user) } } func (h TreasureChestImpl) handleTreasureChestItemComp() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { user := middleware.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return } treasureChests, err := h.s.GetAll(user) if err != nil { handleError(w, r, err) return } id := r.PathValue("id") if id == "new" { comp := t.EditTreasureChest(nil, treasureChests, nil) h.r.Render(r, w, comp) return } treasureChest, err := h.s.Get(user, id) if err != nil { handleError(w, r, err) return } transactionsRecurring, err := h.transactionRecurring.GetAllByTreasureChest(user, treasureChest.Id.String()) if err != nil { handleError(w, r, err) return } transactionsRec := tr.TransactionRecurringItems(transactionsRecurring, "", "", treasureChest.Id.String()) var comp templ.Component if r.URL.Query().Get("edit") == "true" { comp = t.EditTreasureChest(treasureChest, treasureChests, transactionsRec) } else { monthlySums := h.calculateMonthlySums(treasureChests, transactionsRecurring) comp = t.TreasureChestItem(treasureChest, monthlySums) } h.r.Render(r, w, comp) } } func (h TreasureChestImpl) handleUpdateTreasureChest() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { user := middleware.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return } var ( treasureChest *types.TreasureChest err error ) id := r.PathValue("id") parentId := r.FormValue("parent-id") name := r.FormValue("name") if id == "new" { treasureChest, err = h.s.Add(user, parentId, name) if err != nil { handleError(w, r, err) return } } else { treasureChest, err = h.s.Update(user, id, parentId, name) if err != nil { handleError(w, r, err) return } } transactionsRecurring, err := h.transactionRecurring.GetAllByTreasureChest(user, treasureChest.Id.String()) if err != nil { handleError(w, r, err) return } treasureChests := make([]*types.TreasureChest, 1) treasureChests[0] = treasureChest monthlySums := h.calculateMonthlySums(treasureChests, transactionsRecurring) comp := t.TreasureChestItem(treasureChest, monthlySums) h.r.Render(r, w, comp) } } func (h TreasureChestImpl) handleDeleteTreasureChest() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { user := middleware.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return } id := r.PathValue("id") err := h.s.Delete(user, id) if err != nil { handleError(w, r, err) return } } } func (h TreasureChestImpl) calculateMonthlySums( treasureChests []*types.TreasureChest, transactionsRecurring []*types.TransactionRecurring, ) map[uuid.UUID]int64 { monthlySums := make(map[uuid.UUID]int64) for _, tc := range treasureChests { monthlySums[tc.Id] = 0 } for _, t := range transactionsRecurring { if t.TreasureChestId != nil && t.Value > 0 && t.IntervalMonths > 0 { monthlySums[*t.TreasureChestId] += t.Value / t.IntervalMonths } } return monthlySums }