budgit/internal/ui/layouts/space.templ
2026-01-18 22:02:55 +00:00

137 lines
4 KiB
Text

package layouts
import (
"git.juancwu.dev/juancwu/budgit/internal/ctxkeys"
"git.juancwu.dev/juancwu/budgit/internal/model"
"git.juancwu.dev/juancwu/budgit/internal/ui/blocks"
"git.juancwu.dev/juancwu/budgit/internal/ui/components/breadcrumb"
"git.juancwu.dev/juancwu/budgit/internal/ui/components/icon"
"git.juancwu.dev/juancwu/budgit/internal/ui/components/sidebar"
)
templ Space(title string, space *model.Space) {
{{ cfg := ctxkeys.Config(ctx) }}
@Base(SEOProps{
Title: title,
Description: "Space Dashboard",
Path: ctxkeys.URLPath(ctx),
}) {
@sidebar.Layout() {
@sidebar.Sidebar() {
@sidebar.Header() {
@sidebar.Menu() {
@sidebar.MenuItem() {
@sidebar.MenuButton(sidebar.MenuButtonProps{
Size: sidebar.MenuButtonSizeLg,
Href: "/app/dashboard",
}) {
@icon.LayoutDashboard()
<div class="flex flex-col">
<span class="text-sm font-bold">{ cfg.AppName }</span>
<span class="text-xs text-muted-foreground">Back to Dashboard</span>
</div>
}
}
}
}
@sidebar.Content() {
@sidebar.Group() {
@sidebar.GroupLabel() {
{ space.Name }
}
@sidebar.Menu() {
@sidebar.MenuItem() {
@sidebar.MenuButton(sidebar.MenuButtonProps{
Href: "/app/spaces/" + space.ID,
IsActive: ctxkeys.URLPath(ctx) == "/app/spaces/"+space.ID,
Tooltip: "Space Dashboard",
}) {
@icon.House(icon.Props{Class: "size-4"})
<span>Overview</span>
}
}
@sidebar.MenuItem() {
@sidebar.MenuButton(sidebar.MenuButtonProps{
Href: "/app/spaces/" + space.ID + "/expenses",
IsActive: ctxkeys.URLPath(ctx) == "/app/spaces/"+space.ID+"/expenses",
Tooltip: "Expenses",
}) {
@icon.DollarSign(icon.Props{Class: "size-4"})
<span>Expenses</span>
}
}
@sidebar.MenuItem() {
@sidebar.MenuButton(sidebar.MenuButtonProps{
Href: "/app/spaces/" + space.ID + "/lists",
IsActive: ctxkeys.URLPath(ctx) == "/app/spaces/"+space.ID+"/lists",
Tooltip: "Shopping Lists",
}) {
@icon.ShoppingCart(icon.Props{Class: "size-4"})
<span>Shopping Lists</span>
}
}
@sidebar.MenuItem() {
@sidebar.MenuButton(sidebar.MenuButtonProps{
Href: "/app/spaces/" + space.ID + "/tags",
IsActive: ctxkeys.URLPath(ctx) == "/app/spaces/"+space.ID+"/tags",
Tooltip: "Tags",
}) {
@icon.Tag(icon.Props{Class: "size-4"})
<span>Tags</span>
}
}
}
}
}
@sidebar.Footer() {
// Re-using the same dropdown from app layout
{{ user := ctxkeys.User(ctx) }}
{{ profile := ctxkeys.Profile(ctx) }}
if user != nil && profile != nil {
@AppSidebarDropdown(user, profile)
}
}
}
@sidebar.Inset() {
<div hx-sse={ "connect:/app/spaces/" + space.ID + "/stream" } class="flex flex-col h-full">
// Top Navigation Bar
<header class="sticky top-0 z-10 border-b bg-background">
<div class="flex h-14 items-center px-6">
<div class="flex items-center gap-4">
@sidebar.Trigger()
@breadcrumb.Breadcrumb() {
@breadcrumb.List() {
@breadcrumb.Item() {
@breadcrumb.Link(breadcrumb.LinkProps{Href: "/app/dashboard"}) {
Dashboard
}
}
@breadcrumb.Separator()
@breadcrumb.Item() {
@breadcrumb.Link(breadcrumb.LinkProps{Href: "/app/spaces/" + space.ID}) {
{ space.Name }
}
}
@breadcrumb.Separator()
@breadcrumb.Item() {
@breadcrumb.Page() {
{ title }
}
}
}
}
</div>
<div class="ml-auto flex items-center gap-4">
@blocks.ThemeSwitcher()
</div>
</div>
</header>
// App Content
<main class="flex-1 p-6">
{ children... }
</main>
</div>
}
}
}
}