ERP/internal/handlers/handler.go

134 lines
3.7 KiB
Go
Raw Permalink Normal View History

2026-02-06 17:35:29 +01:00
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)
},
2026-02-08 14:20:18 +01:00
"formatDate": func(v interface{}) string {
if t, ok := v.(time.Time); ok {
return t.Format("Jan 02, 2006")
2026-02-06 17:35:29 +01:00
}
2026-02-08 14:20:18 +01:00
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 ""
2026-02-06 17:35:29 +01:00
},
"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(`<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium %s">%s</span>`, 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(`<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium %s">%s</span>`, color, t))
},
"sub": func(a, b float64) float64 {
return a - b
},
}
2026-02-08 14:20:18 +01:00
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"
}
2026-02-06 17:35:29 +01:00
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 ""
}
2026-02-08 14:20:18 +01:00
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 ""
}