179 lines
4.5 KiB
Go

package components
import (
"fmt"
"maps"
"dk/internal/auth"
"dk/internal/csrf"
"dk/internal/database"
"dk/internal/middleware"
"dk/internal/router"
"dk/internal/template"
"dk/internal/users"
)
// GenerateTopNav generates the top navigation HTML based on authentication status
func GenerateTopNav(ctx router.Ctx) string {
if middleware.IsAuthenticated(ctx) {
csrfField := csrf.HiddenField(ctx, auth.Manager)
return fmt.Sprintf(`<form action="/logout" method="post" class="logout">
%s
<button class="img-button" type="submit"><img src="/assets/images/button_logout.gif" alt="Log Out" title="Log Out"></button>
</form>
<a href="/help"><img src="/assets/images/button_help.gif" alt="Help" title="Help"></a>`, csrfField)
} else {
return `<a href="/login"><img src="/assets/images/button_login.gif" alt="Log In" title="Log In"></a>
<a href="/register"><img src="/assets/images/button_register.gif" alt="Register" title="Register"></a>
<a href="/help"><img src="/assets/images/button_help.gif" alt="Help" title="Help"></a>`
}
}
// GenerateLeftSide generates the left sidebar content for authenticated users
func GenerateLeftSide(ctx router.Ctx) string {
if !middleware.IsAuthenticated(ctx) {
return ""
}
// Load and render the leftside template with user data
leftSideTmpl, err := template.Cache.Load("leftside.html")
if err != nil {
return "" // Silently fail - sidebar is optional
}
// Get the current user from session
currentUser := middleware.GetCurrentUser(ctx)
if currentUser == nil {
return ""
}
// Get the full user object from database
db := database.GetDB()
if db == nil {
return ""
}
user, err := users.Find(db, currentUser.ID)
if err != nil {
return ""
}
// Pass the user object directly to the template
leftSideData := map[string]any{
"user": user,
}
return leftSideTmpl.RenderNamed(leftSideData)
}
// GenerateRightSide generates the right sidebar content for authenticated users
func GenerateRightSide(ctx router.Ctx) string {
if !middleware.IsAuthenticated(ctx) {
return ""
}
// Load and render the rightside template with user data
rightSideTmpl, err := template.Cache.Load("rightside.html")
if err != nil {
return "" // Silently fail - sidebar is optional
}
// Get the current user from session
currentUser := middleware.GetCurrentUser(ctx)
if currentUser == nil {
return ""
}
// Get the full user object from database
db := database.GetDB()
if db == nil {
return ""
}
user, err := users.Find(db, currentUser.ID)
if err != nil {
return ""
}
// Pass the user object directly to the template
rightSideData := map[string]any{
"user": user,
}
return rightSideTmpl.RenderNamed(rightSideData)
}
// PageData holds common page template data
type PageData struct {
Title string
Content string
TopNav string
LeftSide string
RightSide string
TotalTime string
NumQueries string
Version string
Build string
}
// RenderPage renders a page using the layout template with common data and additional custom data
func RenderPage(ctx router.Ctx, pageData PageData, additionalData map[string]any) error {
if template.Cache == nil || auth.Manager == nil {
return fmt.Errorf("singleton template.Cache or auth.Manager not initialized")
}
layoutTmpl, err := template.Cache.Load("layout.html")
if err != nil {
return fmt.Errorf("failed to load layout template: %w", err)
}
// Build the base template data with common fields
data := map[string]any{
"title": pageData.Title,
"content": pageData.Content,
"topnav": GenerateTopNav(ctx),
"leftside": pageData.LeftSide,
"rightside": pageData.RightSide,
"totaltime": middleware.GetRequestTime(ctx),
"numqueries": pageData.NumQueries,
"version": pageData.Version,
"build": pageData.Build,
}
// Merge in additional data (overwrites common data if keys conflict)
maps.Copy(data, additionalData)
// Set defaults for empty fields
if data["leftside"] == "" {
data["leftside"] = GenerateLeftSide(ctx)
}
if data["rightside"] == "" {
data["rightside"] = GenerateRightSide(ctx)
}
if data["numqueries"] == "" {
data["numqueries"] = "0"
}
if data["version"] == "" {
data["version"] = "1.0.0"
}
if data["build"] == "" {
data["build"] = "dev"
}
layoutTmpl.WriteTo(ctx, data)
return nil
}
// NewPageData creates a new PageData with sensible defaults
func NewPageData(title, content string) PageData {
return PageData{
Title: title,
Content: content,
LeftSide: "",
RightSide: "",
NumQueries: "0",
Version: "1.0.0",
Build: "dev",
}
}