package handlers import ( "embed" "html/template" "io/fs" "log" "net/http" "regexp" "shop/internal/repository" ) //go:embed templates/* var templateFS embed.FS //go:embed static/* var staticFS embed.FS type HomeHandler struct { repo *repository.ProductRepository stats *repository.StatsRepository templates *template.Template } type homePageData struct { Title string Products interface{} Categories interface{} } func NewHomeHandler(repo *repository.ProductRepository, stats *repository.StatsRepository) (*HomeHandler, error) { funcMap := template.FuncMap{ "plain": stripHTML, } tmpl, err := template.New("").Funcs(funcMap).ParseFS(templateFS, "templates/*.html") if err != nil { return nil, err } return &HomeHandler{repo: repo, stats: stats, templates: tmpl}, nil } var tagRe = regexp.MustCompile(`<[^>]*>`) func stripHTML(s string) string { return tagRe.ReplaceAllString(s, "") } func (h *HomeHandler) Templates() *template.Template { return h.templates } func (h *HomeHandler) Static() http.Handler { sub, err := fs.Sub(staticFS, "static") if err != nil { log.Fatal(err) } return http.FileServer(http.FS(sub)) } func (h *HomeHandler) Home(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { http.NotFound(w, r) return } ctx := r.Context() if err := h.stats.IncrementHomeVisit(ctx); err != nil { log.Printf("visit counter: %v", err) } products, err := h.repo.Featured(ctx, 8) if err != nil { log.Printf("featured products: %v", err) http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } categories, err := h.repo.Categories(ctx) if err != nil { log.Printf("categories: %v", err) http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } data := homePageData{ Title: "Shop — Интернет-магазин", Products: products, Categories: categories, } w.Header().Set("Content-Type", "text/html; charset=utf-8") if err := h.templates.ExecuteTemplate(w, "home.html", data); err != nil { log.Printf("render: %v", err) } } func (h *HomeHandler) Health(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.Write([]byte(`{"status":"ok"}`)) }