package treasure_chest import ( "net/http" "spend-sparrow/internal/core" "spend-sparrow/internal/transaction_recurring" "spend-sparrow/internal/treasure_chest_types" "spend-sparrow/internal/utils" "github.com/a-h/templ" "github.com/google/uuid" ) type Handler interface { Handle(router *http.ServeMux) } type HandlerImpl struct { s Service transactionRecurring transaction_recurring.Service r *core.Render } func NewHandler(s Service, transactionRecurring transaction_recurring.Service, r *core.Render) Handler { return HandlerImpl{ s: s, transactionRecurring: transactionRecurring, r: r, } } func (h HandlerImpl) Handle(r *http.ServeMux) { r.Handle("GET /treasurechest", h.handleHandlerPage()) r.Handle("GET /treasurechest/{id}", h.handleHandlerItemComp()) r.Handle("POST /treasurechest/{id}", h.handleUpdateHandler()) r.Handle("DELETE /treasurechest/{id}", h.handleDeleteHandler()) } func (h HandlerImpl) handleHandlerPage() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { core.UpdateSpan(r) user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return } treasureChests, err := h.s.GetAll(r.Context(), user) if err != nil { core.HandleError(w, r, err) return } transactionsRecurring, err := h.transactionRecurring.GetAll(r.Context(), user) if err != nil { core.HandleError(w, r, err) return } monthlySums := h.calculateMonthlySums(treasureChests, transactionsRecurring) comp := TreasureChestComp(treasureChests, monthlySums) h.r.RenderLayout(r, w, comp, user) } } func (h HandlerImpl) handleHandlerItemComp() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { core.UpdateSpan(r) user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return } treasureChests, err := h.s.GetAll(r.Context(), user) if err != nil { core.HandleError(w, r, err) return } id := r.PathValue("id") if id == "new" { comp := EditTreasureChest(nil, treasureChests, nil) h.r.Render(r, w, comp) return } treasureChest, err := h.s.Get(r.Context(), user, id) if err != nil { core.HandleError(w, r, err) return } transactionsRecurring, err := h.transactionRecurring.GetAllByTreasureChest(r.Context(), user, treasureChest.Id.String()) if err != nil { core.HandleError(w, r, err) return } transactionsRec := transaction_recurring.TransactionRecurringItems(transactionsRecurring, "", "", treasureChest.Id.String()) var comp templ.Component if r.URL.Query().Get("edit") == "true" { comp = EditTreasureChest(treasureChest, treasureChests, transactionsRec) } else { monthlySums := h.calculateMonthlySums(treasureChests, transactionsRecurring) comp = TreasureChestItem(treasureChest, monthlySums) } h.r.Render(r, w, comp) } } func (h HandlerImpl) handleUpdateHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { core.UpdateSpan(r) user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return } var ( treasureChest *treasure_chest_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(r.Context(), user, parentId, name) if err != nil { core.HandleError(w, r, err) return } } else { treasureChest, err = h.s.Update(r.Context(), user, id, parentId, name) if err != nil { core.HandleError(w, r, err) return } } transactionsRecurring, err := h.transactionRecurring.GetAllByTreasureChest(r.Context(), user, treasureChest.Id.String()) if err != nil { core.HandleError(w, r, err) return } treasureChests := make([]*treasure_chest_types.TreasureChest, 1) treasureChests[0] = treasureChest monthlySums := h.calculateMonthlySums(treasureChests, transactionsRecurring) comp := TreasureChestItem(treasureChest, monthlySums) h.r.Render(r, w, comp) } } func (h HandlerImpl) handleDeleteHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { core.UpdateSpan(r) user := core.GetUser(r) if user == nil { utils.DoRedirect(w, r, "/auth/signin") return } id := r.PathValue("id") err := h.s.Delete(r.Context(), user, id) if err != nil { core.HandleError(w, r, err) return } } } func (h HandlerImpl) calculateMonthlySums( treasureChests []*treasure_chest_types.TreasureChest, transactionsRecurring []*transaction_recurring.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 }