package handlers import ( "database/sql" "fmt" "html/template" "net/http" "path/filepath" "time" "github.com/gorilla/sessions" ) type Handler struct { DB *sql.DB Store *sessions.CookieStore } // Template helper functions var funcMap = template.FuncMap{ "formatMoney": func(amount float64) string { return fmt.Sprintf("$%.2f", amount) }, "formatDate": func(v interface{}) string { if t, ok := v.(time.Time); ok { return t.Format("Jan 02, 2006") } if date, ok := v.(string); ok { t, err := time.Parse("2006-01-02", date) if err != nil { return date } return t.Format("Jan 02, 2006") } return "" }, "formatDateTime": func(v interface{}) string { if t, ok := v.(time.Time); ok { return t.Format("Jan 02, 2006 15:04") } return "" }, "statusBadge": func(status string) template.HTML { colors := map[string]string{ "draft": "bg-gray-100 text-gray-800", "confirmed": "bg-blue-100 text-blue-800", "fulfilled": "bg-green-100 text-green-800", "cancelled": "bg-red-100 text-red-800", "pending": "bg-yellow-100 text-yellow-800", "paid": "bg-green-100 text-green-800", "overdue": "bg-red-100 text-red-800", } color, ok := colors[status] if !ok { color = "bg-gray-100 text-gray-800" } return template.HTML(fmt.Sprintf(`%s`, color, status)) }, "capitalize": func(s string) string { if len(s) == 0 { return s } return string(s[0]-32) + s[1:] }, "accountTypeBadge": func(t string) template.HTML { colors := map[string]string{ "asset": "bg-blue-100 text-blue-800", "liability": "bg-red-100 text-red-800", "equity": "bg-purple-100 text-purple-800", "revenue": "bg-green-100 text-green-800", "expense": "bg-orange-100 text-orange-800", } color, ok := colors[t] if !ok { color = "bg-gray-100 text-gray-800" } return template.HTML(fmt.Sprintf(`%s`, color, t)) }, "sub": func(a, b float64) float64 { return a - b }, } func (h *Handler) render(w http.ResponseWriter, r *http.Request, templates []string, data interface{}) { if d, ok := data.(map[string]interface{}); ok { d["Username"] = h.getUsername(r) d["IsAdmin"] = h.getRole(r) == "admin" } paths := make([]string, len(templates)) for i, t := range templates { paths[i] = filepath.Join("templates", t) } tmpl, err := template.New("").Funcs(funcMap).ParseFiles(paths...) if err != nil { http.Error(w, fmt.Sprintf("Template error: %v", err), http.StatusInternalServerError) return } if err := tmpl.ExecuteTemplate(w, "layout", data); err != nil { http.Error(w, fmt.Sprintf("Render error: %v", err), http.StatusInternalServerError) } } func (h *Handler) renderPartial(w http.ResponseWriter, templateFile string, templateName string, data interface{}) { path := filepath.Join("templates", templateFile) tmpl, err := template.New("").Funcs(funcMap).ParseFiles(path) if err != nil { http.Error(w, fmt.Sprintf("Template error: %v", err), http.StatusInternalServerError) return } if err := tmpl.ExecuteTemplate(w, templateName, data); err != nil { http.Error(w, fmt.Sprintf("Render error: %v", err), http.StatusInternalServerError) } } func (h *Handler) getUsername(r *http.Request) string { session, _ := h.Store.Get(r, "erp-session") if username, ok := session.Values["username"].(string); ok { return username } return "" } func (h *Handler) getRole(r *http.Request) string { session, _ := h.Store.Get(r, "erp-session") if role, ok := session.Values["role"].(string); ok { return role } return "" }