package templates
import (
"fmt"
"html/template"
"io"
"os"
"path/filepath"
"time"
)
type TemplateManager struct {
templates map[string]*template.Template
}
func NewTemplateManager(templatesDir string) (*TemplateManager, error) {
tm := &TemplateManager{
templates: make(map[string]*template.Template),
}
// Define template functions
funcMap := template.FuncMap{
"formatDate": formatDate,
"truncate": truncate,
"currency": formatCurrency,
}
// Load all templates
layouts, err := filepath.Glob(filepath.Join(templatesDir, "layouts/*.html"))
if err != nil {
return nil, err
}
partials, err := filepath.Glob(filepath.Join(templatesDir, "partials/*.html"))
if err != nil {
return nil, err
}
// Load page templates
pages := []string{
"customers/index.html",
"customers/show.html",
"customers/form.html",
"customers/table.html",
"products/index.html",
"products/show.html",
"products/form.html",
"products/table.html",
"purchase-orders/index.html",
"purchase-orders/show.html",
"purchase-orders/form.html",
"purchase-orders/table.html",
"enquiries/index.html",
"enquiries/show.html",
"enquiries/form.html",
"enquiries/table.html",
"index.html",
}
for _, page := range pages {
pagePath := filepath.Join(templatesDir, page)
files := append(layouts, partials...)
files = append(files, pagePath)
// For index pages, also include the corresponding table template
if filepath.Base(page) == "index.html" {
dir := filepath.Dir(page)
tablePath := filepath.Join(templatesDir, dir, "table.html")
// Check if table file exists before adding it
if _, err := os.Stat(tablePath); err == nil {
files = append(files, tablePath)
}
}
tmpl, err := template.New(filepath.Base(page)).Funcs(funcMap).ParseFiles(files...)
if err != nil {
return nil, err
}
tm.templates[page] = tmpl
}
return tm, nil
}
func (tm *TemplateManager) Render(w io.Writer, name string, data interface{}) error {
tmpl, ok := tm.templates[name]
if !ok {
return template.New("error").Execute(w, "Template not found")
}
return tmpl.ExecuteTemplate(w, "base", data)
}
func (tm *TemplateManager) RenderPartial(w io.Writer, templateFile, templateName string, data interface{}) error {
tmpl, ok := tm.templates[templateFile]
if !ok {
return template.New("error").Execute(w, "Template not found")
}
return tmpl.ExecuteTemplate(w, templateName, data)
}
// Template helper functions
func formatDate(t interface{}) string {
switch v := t.(type) {
case time.Time:
return v.Format("2006-01-02")
case string:
if tm, err := time.Parse("2006-01-02 15:04:05", v); err == nil {
return tm.Format("2006-01-02")
}
return v
default:
return fmt.Sprintf("%v", v)
}
}
func truncate(s string, n int) string {
if len(s) <= n {
return s
}
return s[:n] + "..."
}
func formatCurrency(amount float64) string {
return fmt.Sprintf("$%.2f", amount)
}