134 lines
3.7 KiB
Go
134 lines
3.7 KiB
Go
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(`<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
|
|
},
|
|
}
|
|
|
|
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 ""
|
|
}
|