feat(layout): #49 update layout by navigation
All checks were successful
Build Docker Image / Build-Docker-Image (push) Successful in 5m0s
Build and Push Docker Image / Build-And-Push-Docker-Image (push) Successful in 5m0s

This commit was merged in pull request #57.
This commit is contained in:
2025-05-06 22:10:49 +02:00
parent 605c64ef92
commit b8f13dfc93
6 changed files with 80 additions and 51 deletions

2
dev.sh
View File

@@ -1,5 +1,5 @@
templ generate --watch --proxy="http://localhost:8080" --cmd="go run ." & templ generate --watch --proxy="http://localhost:8080" --cmd="go run ." &
npm run watch & npm run watch
read -n1 -s read -n1 -s
kill $(jobs -p) kill $(jobs -p)

View File

@@ -38,7 +38,7 @@ func (render *Render) RenderLayout(r *http.Request, w http.ResponseWriter, slot
func (render *Render) RenderLayoutWithStatus(r *http.Request, w http.ResponseWriter, slot templ.Component, user *types.User, status int) { func (render *Render) RenderLayoutWithStatus(r *http.Request, w http.ResponseWriter, slot templ.Component, user *types.User, status int) {
userComp := render.getUserComp(user) userComp := render.getUserComp(user)
layout := template.Layout(slot, userComp) layout := template.Layout(slot, userComp, user != nil, r.URL.Path)
render.RenderWithStatus(r, w, layout, status) render.RenderWithStatus(r, w, layout, status)
} }

View File

@@ -27,10 +27,10 @@ func NewIndex(service service.Auth, render *Render) Index {
} }
func (handler IndexImpl) Handle(router *http.ServeMux) { func (handler IndexImpl) Handle(router *http.ServeMux) {
router.Handle("/", handler.handleIndexAnd404()) router.Handle("/", handler.handleRootAnd404())
} }
func (handler IndexImpl) handleIndexAnd404() http.HandlerFunc { func (handler IndexImpl) handleRootAnd404() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
user := middleware.GetUser(r) user := middleware.GetUser(r)
@@ -41,7 +41,11 @@ func (handler IndexImpl) handleIndexAnd404() http.HandlerFunc {
comp = template.NotFound() comp = template.NotFound()
status = http.StatusNotFound status = http.StatusNotFound
} else { } else {
comp = template.Index() if user != nil {
comp = template.Dashboard()
} else {
comp = template.Index()
}
status = http.StatusOK status = http.StatusOK
} }

View File

@@ -4,8 +4,8 @@
"description": "Your (almost) independent tech stack to host on a VPC.", "description": "Your (almost) independent tech stack to host on a VPC.",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"build": "mkdir -p static/js && cp -f node_modules/htmx.org/dist/htmx.min.js static/js/htmx.min.js && tailwindcss -i input.css -o static/css/tailwind.css --minify", "build": "cp -f node_modules/htmx.org/dist/htmx.min.js static/js/htmx.min.js && tailwindcss -i input.css -o static/css/tailwind.css --minify",
"watch": "mkdir -p static/js && cp -f node_modules/htmx.org/dist/htmx.min.js static/js/htmx.min.js && tailwindcss -i input.css -o static/css/tailwind.css --watch" "watch": "cp -f node_modules/htmx.org/dist/htmx.min.js static/js/htmx.min.js && tailwindcss -i input.css -o static/css/tailwind.css --watch"
}, },
"keywords": [], "keywords": [],
"author": "", "author": "",

9
template/dashboard.templ Normal file
View File

@@ -0,0 +1,9 @@
package template
templ Dashboard() {
<div class="">
<h1 class="text-8xl">
Dashboard
</h1>
</div>
}

View File

@@ -1,52 +1,68 @@
package template package template
templ Layout(slot templ.Component, user templ.Component) { func layoutLinkClass(isActive bool) string {
<!DOCTYPE html> if isActive {
<html lang="en"> return "text-xl hover:bg-gray-100 p-1 duration-100 rounded-xl transition-colors text-gray-900"
}
return "text-xl hover:bg-gray-100 hover:text-gray-900 p-1 duration-200 rounded-xl transition-colors text-gray-400"
}
<head> templ Layout(slot templ.Component, user templ.Component, loggedIn bool, path string) {
<meta charset="utf-8" /> <!DOCTYPE html>
<title>SpendSparrow</title> <html lang="en">
<link rel="icon" href="/static/favicon.svg" /> <head>
<link rel="stylesheet" href="/static/css/tailwind.css" /> <meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1" /> <title>SpendSparrow</title>
<meta name="htmx-config" content='{ <link rel="icon" href="/static/favicon.svg"/>
<link rel="stylesheet" href="/static/css/tailwind.css"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta
name="htmx-config"
content='{
"includeIndicatorStyles": false, "includeIndicatorStyles": false,
"selfRequestsOnly": true, "selfRequestsOnly": true,
"allowScriptTags": false "allowScriptTags": false
}' /> }'
<script src="/static/js/htmx.min.js"></script> />
<script src="/static/js/toast.js"></script> <script src="/static/js/htmx.min.js"></script>
</head> <script src="/static/js/toast.js"></script>
</head>
<body hx-headers='{"csrf-token": "CSRF_TOKEN"}'> <body hx-headers='{"csrf-token": "CSRF_TOKEN"}'>
<div class="h-screen flex flex-col"> <div class="h-screen flex flex-col">
// Header // Header
<div class="sticky top-0"> <div class="sticky top-0">
<div class="flex bg-white justify-end items-center gap-2 py-1 px-2 h-12 md:gap-10 md:px-10 md:py-2"> <nav class="flex bg-white items-center gap-2 py-1 px-2 h-12 md:gap-10 md:px-10 md:py-2">
<a href="/" class="flex-1 flex gap-2"> <a href="/" class="flex gap-2 mr-20">
<img class="w-6" src="/static/favicon.svg" alt="SpendSparrow logo" /> <img class="w-6" src="/static/favicon.svg" alt="SpendSparrow logo"/>
<span class="text-4xl font-bold font-pirata">SpendSparrow</span> <span class="text-4xl font-bold font-pirata">SpendSparrow</span>
</a> </a>
@user if loggedIn {
<a class={ layoutLinkClass(path == "/") } href="/">Dashboard</a>
<a class={ layoutLinkClass(path == "/transaction") } href="/transaction">Transaction</a>
<a class={ layoutLinkClass(path == "/account") } href="/account">Account</a>
}
<div class="ml-auto">
@user
</div>
</nav>
<div class="h-12 inset-0 bg-linear-0 from-transparent to-white"></div>
</div>
// Content
<div class="flex-1">
if slot != nil {
@slot
}
</div>
// Footer
</div> </div>
<div class="h-12 inset-0 bg-linear-0 from-transparent to-white"></div> <div id="toasts" class="fixed bottom-4 right-4 ml-4 max-w-96 flex flex-col gap-2 z-50">
</div> <div
// Content id="toast"
<div class="flex-1"> class="transition-all duration-300 opacity-0 px-4 py-2 text-lg hidden text-bold rounded bg-amber-900 text-white"
if slot != nil { >
@slot M
} </div>
</div> </div>
// Footer </body>
</div> </html>
<div id="toasts" class="fixed bottom-4 right-4 ml-4 max-w-96 flex flex-col gap-2 z-50">
<div id="toast"
class="transition-all duration-300 opacity-0 px-4 py-2 text-lg hidden text-bold rounded bg-amber-900 text-white">
M
</div>
</div>
</body>
</html>
} }