2025-08-26 14:13:09 -06:00
|
|
|
package utils
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bytes"
|
|
|
|
|
"html/template"
|
2025-08-27 17:54:45 -06:00
|
|
|
"log"
|
2025-08-26 14:13:09 -06:00
|
|
|
"net/http"
|
2025-08-27 17:54:45 -06:00
|
|
|
"os"
|
2025-08-26 14:13:09 -06:00
|
|
|
"path/filepath"
|
2025-09-01 17:32:00 -06:00
|
|
|
"strings"
|
2025-08-27 17:54:45 -06:00
|
|
|
|
|
|
|
|
"github.com/joho/godotenv"
|
2025-08-26 14:13:09 -06:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Helper functions for templates
|
|
|
|
|
var templateFuncs = template.FuncMap{
|
|
|
|
|
"add": func(a, b int) int {
|
|
|
|
|
return a + b
|
|
|
|
|
},
|
|
|
|
|
"sub": func(a, b int) int {
|
|
|
|
|
return a - b
|
|
|
|
|
},
|
|
|
|
|
"eq": func(a, b interface{}) bool {
|
|
|
|
|
return a == b
|
|
|
|
|
},
|
|
|
|
|
"pageRange": func(currentPage, totalPages int) []int {
|
|
|
|
|
// Generate page numbers to show (max 7 pages)
|
|
|
|
|
start := currentPage - 3
|
|
|
|
|
end := currentPage + 3
|
|
|
|
|
|
|
|
|
|
if start < 1 {
|
|
|
|
|
end += 1 - start
|
|
|
|
|
start = 1
|
|
|
|
|
}
|
|
|
|
|
if end > totalPages {
|
|
|
|
|
start -= end - totalPages
|
|
|
|
|
end = totalPages
|
|
|
|
|
}
|
|
|
|
|
if start < 1 {
|
|
|
|
|
start = 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var pages []int
|
|
|
|
|
for i := start; i <= end; i++ {
|
|
|
|
|
pages = append(pages, i)
|
|
|
|
|
}
|
|
|
|
|
return pages
|
|
|
|
|
},
|
2025-09-01 17:32:00 -06:00
|
|
|
"formatColumnName": func(name string) string {
|
|
|
|
|
// Replace underscores with spaces and title case each word
|
|
|
|
|
formatted := strings.ReplaceAll(name, "_", " ")
|
|
|
|
|
words := strings.Fields(formatted)
|
|
|
|
|
for i, word := range words {
|
|
|
|
|
if len(word) > 0 {
|
|
|
|
|
words[i] = strings.ToUpper(string(word[0])) + strings.ToLower(word[1:])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return strings.Join(words, " ")
|
|
|
|
|
},
|
2025-08-26 14:13:09 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Render(w http.ResponseWriter, tmpl string, data interface{}) {
|
2025-08-27 17:54:45 -06:00
|
|
|
// Load .env file
|
|
|
|
|
err := godotenv.Load() // or specify path: godotenv.Load("/path/to/.env")
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalf("Error loading .env file: %v", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get individual components from environment variables
|
|
|
|
|
TemplatesURL := os.Getenv("TEMPLATES_URL")
|
|
|
|
|
|
2025-08-26 14:13:09 -06:00
|
|
|
// Paths for layout + page templates
|
2025-08-27 17:54:45 -06:00
|
|
|
layout := filepath.Join(TemplatesURL, "layout.html")
|
|
|
|
|
page := filepath.Join(TemplatesURL, tmpl)
|
2025-08-26 14:13:09 -06:00
|
|
|
|
|
|
|
|
// Parse files with helper functions
|
|
|
|
|
tmpls, err := template.New("").Funcs(templateFuncs).ParseFiles(layout, page)
|
|
|
|
|
if err != nil {
|
|
|
|
|
http.Error(w, "Template parsing error: "+err.Error(), http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Render to buffer first (catch errors before writing response)
|
|
|
|
|
var buf bytes.Buffer
|
|
|
|
|
err = tmpls.ExecuteTemplate(&buf, "layout", data)
|
|
|
|
|
if err != nil {
|
|
|
|
|
http.Error(w, "Template execution error: "+err.Error(), http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Write final HTML to response
|
|
|
|
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
|
|
|
buf.WriteTo(w)
|
|
|
|
|
}
|