From 081499ca595e393f566fb1b592871e9479750d90 Mon Sep 17 00:00:00 2001 From: juancwu Date: Thu, 15 Jan 2026 01:06:55 +0000 Subject: [PATCH] improve dashboard page --- internal/handler/dashboard.go | 35 +++++++++++++++-- internal/routes/routes.go | 2 +- internal/ui/layouts/app.templ | 49 ++++-------------------- internal/ui/layouts/space.templ | 4 +- internal/ui/pages/app_dashboard.templ | 54 +++++++++++++++++++++++---- 5 files changed, 89 insertions(+), 55 deletions(-) diff --git a/internal/handler/dashboard.go b/internal/handler/dashboard.go index 1a920d3..e3f29ce 100644 --- a/internal/handler/dashboard.go +++ b/internal/handler/dashboard.go @@ -1,18 +1,45 @@ package handler import ( + "log/slog" "net/http" + "git.juancwu.dev/juancwu/budgit/internal/ctxkeys" + "git.juancwu.dev/juancwu/budgit/internal/service" "git.juancwu.dev/juancwu/budgit/internal/ui" "git.juancwu.dev/juancwu/budgit/internal/ui/pages" ) -type dashboardHandler struct{} +type dashboardHandler struct { + spaceService *service.SpaceService + expenseService *service.ExpenseService +} -func NewDashboardHandler() *dashboardHandler { - return &dashboardHandler{} +func NewDashboardHandler(ss *service.SpaceService, es *service.ExpenseService) *dashboardHandler { + return &dashboardHandler{ + spaceService: ss, + expenseService: es, + } } func (h *dashboardHandler) DashboardPage(w http.ResponseWriter, r *http.Request) { - ui.Render(w, r, pages.Dashboard()) + user := ctxkeys.User(r.Context()) + spaces, err := h.spaceService.GetSpacesForUser(user.ID) + if err != nil { + slog.Error("failed to get spaces for user", "error", err, "user_id", user.ID) + http.Error(w, "Internal Server Error", http.StatusInternalServerError) + return + } + + var totalBalance int + for _, space := range spaces { + balance, err := h.expenseService.GetBalanceForSpace(space.ID) + if err != nil { + slog.Error("failed to get balance for space", "error", err, "space_id", space.ID) + continue + } + totalBalance += balance + } + + ui.Render(w, r, pages.Dashboard(spaces, totalBalance)) } diff --git a/internal/routes/routes.go b/internal/routes/routes.go index 00a3cb2..35d115c 100644 --- a/internal/routes/routes.go +++ b/internal/routes/routes.go @@ -13,7 +13,7 @@ import ( func SetupRoutes(a *app.App) http.Handler { auth := handler.NewAuthHandler(a.AuthService, a.InviteService) home := handler.NewHomeHandler() - dashboard := handler.NewDashboardHandler() + dashboard := handler.NewDashboardHandler(a.SpaceService, a.ExpenseService) space := handler.NewSpaceHandler(a.SpaceService, a.TagService, a.ShoppingListService, a.ExpenseService, a.InviteService, a.EventBus) mux := http.NewServeMux() diff --git a/internal/ui/layouts/app.templ b/internal/ui/layouts/app.templ index 1586b0b..48f55a4 100644 --- a/internal/ui/layouts/app.templ +++ b/internal/ui/layouts/app.templ @@ -32,7 +32,6 @@ templ App(title string) { @icon.LayoutDashboard()
{ cfg.AppName } - Workspace
} } @@ -54,34 +53,11 @@ templ App(title string) { Dashboard } } - @sidebar.MenuItem() { - @sidebar.MenuButton(sidebar.MenuButtonProps{ - Href: "/app/goals", - IsActive: ctxkeys.URLPath(ctx) == "/app/goals", - Tooltip: "Goals", - }) { - @icon.FolderOpen(icon.Props{Class: "size-4"}) - Goals - } - } } } } @sidebar.Footer() { @sidebar.Menu() { - @sidebar.MenuItem() { - @sidebar.MenuButton(sidebar.MenuButtonProps{ - Href: "/docs", - Size: sidebar.MenuButtonSizeSm, - Attributes: templ.Attributes{ - "target": "_blank", - "rel": "noopener noreferrer", - }, - }) { - @icon.BookOpen(icon.Props{Class: "size-4"}) - Documentation - } - } @sidebar.MenuItem() { @sidebar.MenuButton(sidebar.MenuButtonProps{ Href: "mailto:" + cfg.SupportEmail, @@ -170,23 +146,14 @@ templ AppSidebarDropdown(user *model.User, profile *model.Profile) { } @dropdown.Separator() - @dropdown.Item(dropdown.ItemProps{ - Href: "/app/settings", - }) { - - @icon.Settings(icon.Props{Size: 16, Class: "mr-2"}) - Settings - - } - @dropdown.Item(dropdown.ItemProps{ - Href: "/app/billing", - }) { - - @icon.CreditCard(icon.Props{Size: 16, Class: "mr-2"}) - Billing - - } - @dropdown.Separator() + + + + + + + +
@csrf.Token() @dropdown.Item(dropdown.ItemProps{ diff --git a/internal/ui/layouts/space.templ b/internal/ui/layouts/space.templ index 832725a..d0410ee 100644 --- a/internal/ui/layouts/space.templ +++ b/internal/ui/layouts/space.templ @@ -28,7 +28,7 @@ templ Space(title string, space *model.Space) { @icon.LayoutDashboard()
{ cfg.AppName } - Back to Home + Back to Dashboard
} } @@ -103,7 +103,7 @@ templ Space(title string, space *model.Space) { @breadcrumb.List() { @breadcrumb.Item() { @breadcrumb.Link(breadcrumb.LinkProps{Href: "/app/dashboard"}) { - Home + Dashboard } } @breadcrumb.Separator() diff --git a/internal/ui/pages/app_dashboard.templ b/internal/ui/pages/app_dashboard.templ index e69cc54..8ac0743 100644 --- a/internal/ui/pages/app_dashboard.templ +++ b/internal/ui/pages/app_dashboard.templ @@ -1,15 +1,55 @@ package pages -import "git.juancwu.dev/juancwu/budgit/internal/ui/layouts" +import ( + "fmt" + "git.juancwu.dev/juancwu/budgit/internal/model" + "git.juancwu.dev/juancwu/budgit/internal/ui/layouts" + "git.juancwu.dev/juancwu/budgit/internal/ui/components/card" +) -templ Dashboard() { +templ Dashboard(spaces []*model.Space, totalBalance int) { @layouts.App("Dashboard") {
-
-

Dashboard

-

- Welcome to your dashboard -

+
+
+

Dashboard

+

+ Welcome back! Here's an overview of your spaces. +

+
+
+

Total Balance

+

+ { fmt.Sprintf("$%.2f", float64(totalBalance)/100.0) } +

+
+
+ +
+ for _, space := range spaces { + + @card.Card(card.Props{ Class: "h-full transition-colors group-hover:border-primary" }) { + @card.Header() { + @card.Title() { { space.Name } } + @card.Description() { + Manage expenses and shopping lists in this space. + } + } + @card.Content() { + // You could add some summary stats here later + } + } + + } + + // Option to create a new space + @card.Card(card.Props{ Class: "h-full border-dashed" }) { + @card.Content(card.ContentProps{ Class: "h-full flex flex-col items-center justify-center py-12" }) { +

Need another space?

+ // TODO: Add a button or link to create a new space + Create Space (Coming Soon) + } + }
}