126 lines
2.8 KiB
Go
126 lines
2.8 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"embed"
|
|
_ "embed"
|
|
"errors"
|
|
"log"
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"github.com/Bronku/iroon/models"
|
|
"github.com/Bronku/iroon/store"
|
|
"github.com/go-chi/chi/middleware"
|
|
"github.com/go-chi/chi/v5"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/clause"
|
|
)
|
|
|
|
//go:embed static/*
|
|
var static embed.FS
|
|
|
|
type contextKey string
|
|
|
|
const dbContextKey = contextKey("db")
|
|
const orderContextKey = contextKey("order")
|
|
|
|
func main() {
|
|
loadConfig()
|
|
loadTemplates()
|
|
|
|
// load database
|
|
db, err := store.LoadStore(config.Database.File)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
r := chi.NewRouter()
|
|
r.Use(middleware.RequestID)
|
|
r.Use(middleware.RealIP)
|
|
r.Use(middleware.Logger)
|
|
r.Use(middleware.Recoverer)
|
|
r.Use(middleware.Timeout(config.Server.RequestTimeout))
|
|
|
|
r.Get("/", http.RedirectHandler("/orders", http.StatusSeeOther).ServeHTTP)
|
|
|
|
// Serve static files from the "./assets" directory when accessing "/assets/*"
|
|
fileServer := http.StripPrefix("/static/", http.FileServer(http.FS(static)))
|
|
r.Handle("/static/*", fileServer)
|
|
|
|
r.Route("/orders", func(r chi.Router) {
|
|
r.Use(middleware.WithValue(dbContextKey, db))
|
|
r.Route("/{orderID}", func(r chi.Router) {
|
|
r.Use(OrderCtx)
|
|
r.Get("/", getOrder)
|
|
})
|
|
})
|
|
|
|
// start server
|
|
server := &http.Server{
|
|
Handler: r,
|
|
Addr: config.Server.Addr,
|
|
ReadHeaderTimeout: config.Server.ReadHeaderTimeout,
|
|
}
|
|
err = server.ListenAndServe()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
// can't get item from context, please include it before registering route
|
|
var errNoContextValue = errors.New("no value from context")
|
|
|
|
func OrderCtx(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
db := r.Context().Value(dbContextKey).(*gorm.DB)
|
|
if db == nil {
|
|
log.Fatal(errNoContextValue)
|
|
}
|
|
var order *models.Order
|
|
var err error
|
|
|
|
orderID, err := strconv.Atoi(chi.URLParam(r, "orderID"))
|
|
if err != nil {
|
|
w.Write([]byte("url not found"))
|
|
return
|
|
}
|
|
|
|
err = db.Preload("OrderItems.Product").Preload(clause.Associations).Find(&order, orderID).Error
|
|
if err != nil {
|
|
w.Write([]byte("item not found"))
|
|
return
|
|
}
|
|
|
|
ctx := context.WithValue(r.Context(), orderContextKey, order)
|
|
next.ServeHTTP(w, r.WithContext(ctx))
|
|
})
|
|
}
|
|
|
|
func getOrder(w http.ResponseWriter, r *http.Request) {
|
|
var db *gorm.DB
|
|
var catalogue []models.Product
|
|
var order *models.Order
|
|
var err error
|
|
|
|
db = r.Context().Value(dbContextKey).(*gorm.DB)
|
|
if db == nil {
|
|
log.Fatal(errNoContextValue)
|
|
}
|
|
|
|
err = db.Find(&catalogue).Error
|
|
if err != nil {
|
|
w.Write([]byte("no catalogue"))
|
|
return
|
|
}
|
|
|
|
order = r.Context().Value(orderContextKey).(*models.Order)
|
|
if order == nil {
|
|
log.Fatal(errNoContextValue)
|
|
}
|
|
|
|
templates["order.gohtml"].ExecuteTemplate(w, "layout", struct {
|
|
Order models.Order
|
|
Catalogue []models.Product
|
|
}{*order, catalogue})
|
|
}
|