package handler import ( "fmt" "log/slog" "net/http" "spend-sparrow/internal/handler/middleware" "spend-sparrow/internal/service" "spend-sparrow/internal/template" "spend-sparrow/internal/template/dashboard" "spend-sparrow/internal/types" "spend-sparrow/internal/utils" "time" "github.com/a-h/templ" ) type Index interface { Handle(router *http.ServeMux) } type IndexImpl struct { r *Render d *service.Dashboard c service.Clock } func NewIndex(r *Render, d *service.Dashboard, c service.Clock) Index { return IndexImpl{ r: r, d: d, c: c, } } func (handler IndexImpl) Handle(router *http.ServeMux) { router.Handle("/", handler.handleRootAnd404()) router.Handle("/empty", handler.handleEmpty()) } func (handler IndexImpl) handleRootAnd404() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { updateSpan(r) user := middleware.GetUser(r) htmx := utils.IsHtmx(r) var comp templ.Component var status int if r.URL.Path != "/" { comp = template.NotFound() status = http.StatusNotFound } else { if user != nil { var err error comp, err = handler.dashboard(user, htmx, r) if err != nil { slog.ErrorContext(r.Context(), "Failed to get dashboard summary", "err", err) } } else { comp = template.Index() } status = http.StatusOK } if htmx { handler.r.RenderWithStatus(r, w, comp, status) } else { handler.r.RenderLayoutWithStatus(r, w, comp, user, status) } } } func (handler IndexImpl) dashboard(user *types.User, htmx bool, r *http.Request) (templ.Component, error) { var month time.Time var err error monthStr := r.URL.Query().Get("month") if monthStr != "" { month, err = time.Parse("2006-01-02", monthStr) if err != nil { return nil, fmt.Errorf("could not parse timestamp: %w", service.ErrBadRequest) } } else { month = handler.c.Now() } summary, err := handler.d.Summary(r.Context(), user, month) if err != nil { return nil, err } if htmx { return dashboard.DashboardData(summary), nil } else { return dashboard.Dashboard(summary), nil } } func (handler IndexImpl) handleEmpty() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { updateSpan(r) // Return nothing } }