2026-03-12 20:51:38 -07:00

104 lines
2.4 KiB
Go

package handlers
import (
"encoding/json"
"html/template"
"io/fs"
"log"
"net/http"
"strconv"
"sync"
"setec-manager/internal/config"
"setec-manager/internal/db"
"setec-manager/internal/hosting"
"setec-manager/web"
"github.com/go-chi/chi/v5"
)
type Handler struct {
Config *config.Config
DB *db.DB
HostingConfigs *hosting.ProviderConfigStore
tmpl *template.Template
once sync.Once
}
func New(cfg *config.Config, database *db.DB, hostingConfigs *hosting.ProviderConfigStore) *Handler {
return &Handler{
Config: cfg,
DB: database,
HostingConfigs: hostingConfigs,
}
}
func (h *Handler) getTemplates() *template.Template {
h.once.Do(func() {
funcMap := template.FuncMap{
"eq": func(a, b interface{}) bool { return a == b },
"ne": func(a, b interface{}) bool { return a != b },
"default": func(val, def interface{}) interface{} {
if val == nil || val == "" || val == 0 || val == false {
return def
}
return val
},
}
var err error
h.tmpl, err = template.New("").Funcs(funcMap).ParseFS(web.TemplateFS, "templates/*.html")
if err != nil {
log.Fatalf("Failed to parse templates: %v", err)
}
// Also parse from the static FS to make sure it's available
_ = fs.WalkDir(web.StaticFS, ".", func(path string, d fs.DirEntry, err error) error {
return nil
})
})
return h.tmpl
}
type pageData struct {
Title string
Data interface{}
Config *config.Config
}
func (h *Handler) render(w http.ResponseWriter, name string, data interface{}) {
pd := pageData{
Data: data,
Config: h.Config,
}
t := h.getTemplates().Lookup(name)
if t == nil {
http.Error(w, "Template not found: "+name, http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
if err := t.Execute(w, pd); err != nil {
log.Printf("[template] %s: %v", name, err)
}
}
func writeJSON(w http.ResponseWriter, status int, v interface{}) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
json.NewEncoder(w).Encode(v)
}
func writeError(w http.ResponseWriter, status int, msg string) {
writeJSON(w, status, map[string]string{"error": msg})
}
func paramInt(r *http.Request, name string) (int64, error) {
return strconv.ParseInt(chi.URLParam(r, name), 10, 64)
}
func paramStr(r *http.Request, name string) string {
return chi.URLParam(r, name)
}