small improvements

This commit is contained in:
bronku 2026-06-11 09:10:27 +02:00
parent bb32802324
commit 5f2d6f00bc
10 changed files with 117 additions and 178 deletions

6
config/config.go Normal file
View file

@ -0,0 +1,6 @@
package config
const (
DateFormat = "2006-01-02"
DateTimeFormat = "2006-01-02 15:04"
)

View file

@ -1,9 +0,0 @@
package server
import (
"net/http"
"github.com/a-h/templ"
)
type fetcher func(r *http.Request) (templ.Component, int, error)

View file

@ -8,6 +8,7 @@ import (
"github.com/a-h/templ" "github.com/a-h/templ"
"git.bronku.xyz/bronku/cake-order-tracker/config"
"git.bronku.xyz/bronku/cake-order-tracker/models" "git.bronku.xyz/bronku/cake-order-tracker/models"
"git.bronku.xyz/bronku/cake-order-tracker/server/templates" "git.bronku.xyz/bronku/cake-order-tracker/server/templates"
) )
@ -26,15 +27,15 @@ func (h *Server) orders(_ *http.Request) (templ.Component, int, error) {
y, m, _ = time.Now().Date() y, m, _ = time.Now().Date()
first, last := monthInterval(y, m) first, last := monthInterval(y, m)
orders, err := h.s.GetOrders(first, last) orders, err := h.s.GetOrders(first, last)
return templates.OrdersPage(first.Format("2006-01-02"), last.Format("2006-01-02"), orders), http.StatusOK, err return templates.OrdersPage(first.Format(config.DateFormat), last.Format(config.DateFormat), orders), http.StatusOK, err
} }
func (h *Server) ordersSearch(r *http.Request) (templ.Component, int, error) { func (h *Server) ordersSearch(r *http.Request) (templ.Component, int, error) {
from, err := time.Parse("2006-01-02", r.URL.Query().Get("from")) from, err := time.Parse(config.DateFormat, r.URL.Query().Get("from"))
if err != nil { if err != nil {
from = time.Time{} from = time.Time{}
} }
to, err := time.Parse("2006-01-02", r.URL.Query().Get("to")) to, err := time.Parse(config.DateFormat, r.URL.Query().Get("to"))
if err != nil { if err != nil {
to = time.Time{} to = time.Time{}
} }
@ -48,7 +49,7 @@ func (h *Server) cakes(_ *http.Request) (templ.Component, int, error) {
} }
func (h *Server) cake(r *http.Request) (templ.Component, int, error) { func (h *Server) cake(r *http.Request) (templ.Component, int, error) {
url := strings.Split(r.URL.String(), "/") url := strings.Split(r.URL.Path, "/")
if len(url) < 3 || url[2] == "" { if len(url) < 3 || url[2] == "" {
return templates.CakePage(models.Cake{}), http.StatusOK, nil return templates.CakePage(models.Cake{}), http.StatusOK, nil
} }
@ -73,7 +74,7 @@ func (h *Server) order(r *http.Request) (templ.Component, int, error) {
return nil, http.StatusInternalServerError, err return nil, http.StatusInternalServerError, err
} }
url := strings.Split(r.URL.String(), "/") url := strings.Split(r.URL.Path, "/")
if len(url) < 3 || url[2] == "" { if len(url) < 3 || url[2] == "" {
return templates.OrderPage(models.Order{Date: time.Now()}, catalogue), http.StatusOK, nil return templates.OrderPage(models.Order{Date: time.Now()}, catalogue), http.StatusOK, nil
} }

View file

@ -1,9 +0,0 @@
package server
import "net/http"
func (h *Server) redirect(path string, code int) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, path, code)
}
}

View file

@ -1,7 +1,6 @@
package server package server
import ( import (
"fmt"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
@ -9,6 +8,7 @@ import (
"github.com/a-h/templ" "github.com/a-h/templ"
"git.bronku.xyz/bronku/cake-order-tracker/config"
"git.bronku.xyz/bronku/cake-order-tracker/models" "git.bronku.xyz/bronku/cake-order-tracker/models"
"git.bronku.xyz/bronku/cake-order-tracker/server/templates" "git.bronku.xyz/bronku/cake-order-tracker/server/templates"
) )
@ -30,7 +30,6 @@ func (h *Server) postCake(r *http.Request) (templ.Component, int, error) {
return nil, http.StatusBadRequest, err return nil, http.StatusBadRequest, err
} }
n.ID, err = h.s.SaveCake(n) n.ID, err = h.s.SaveCake(n)
fmt.Println(err)
return templates.Confirmation("Potwierdzone", n.ID), http.StatusAccepted, err return templates.Confirmation("Potwierdzone", n.ID), http.StatusAccepted, err
} }
@ -41,7 +40,6 @@ func (h *Server) postOrder(r *http.Request) (templ.Component, int, error) {
} }
err = r.ParseForm() err = r.ParseForm()
fmt.Println(r.PostForm)
if err != nil { if err != nil {
return nil, http.StatusBadRequest, err return nil, http.StatusBadRequest, err
} }
@ -55,14 +53,14 @@ func (h *Server) postOrder(r *http.Request) (templ.Component, int, error) {
if err != nil { if err != nil {
return nil, http.StatusBadRequest, err return nil, http.StatusBadRequest, err
} }
n.Date, err = time.Parse("2006-01-02", r.FormValue("date")) n.Date, err = time.Parse(config.DateFormat, r.FormValue("date"))
if err != nil { if err != nil {
return nil, http.StatusBadRequest, err return nil, http.StatusBadRequest, err
} }
n.Cakes = make([]models.Cake, 0) n.Cakes = make([]models.Cake, 0)
for _, e := range cakes { for _, e := range cakes {
e.Amount, err = strconv.Atoi(r.FormValue(fmt.Sprintf("cake[%d]", e.ID))) e.Amount, err = strconv.Atoi(r.FormValue("cake[" + strconv.Itoa(e.ID) + "]"))
if err != nil { if err != nil {
continue continue
} }
@ -77,6 +75,5 @@ func (h *Server) postOrder(r *http.Request) (templ.Component, int, error) {
n.Status = strings.TrimSpace(r.FormValue("status")) n.Status = strings.TrimSpace(r.FormValue("status"))
n.ID, err = h.s.SaveOrder(n) n.ID, err = h.s.SaveOrder(n)
fmt.Println(n)
return templates.Confirmation("Potwierdzone", n.ID), http.StatusAccepted, err return templates.Confirmation("Potwierdzone", n.ID), http.StatusAccepted, err
} }

View file

@ -4,52 +4,44 @@ import (
"embed" "embed"
"net/http" "net/http"
"github.com/a-h/templ"
"git.bronku.xyz/bronku/cake-order-tracker/store" "git.bronku.xyz/bronku/cake-order-tracker/store"
) )
type Server struct { type fetcher func(r *http.Request) (templ.Component, int, error)
s *store.Store
routes map[string]route
http.Handler
}
type route struct { type Server struct {
function fetcher s *store.Store
http.Handler
} }
//go:embed static/* //go:embed static/*
var static embed.FS var static embed.FS
func (h *Server) loadHandler() { func redirect(path string, code int) http.HandlerFunc {
mux := http.NewServeMux() return func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, path, code)
for i, e := range h.routes {
mux.HandleFunc(i, h.render(e.function))
} }
mux.HandleFunc("GET /", h.redirect("/orders", http.StatusSeeOther))
fs := http.FileServerFS(static)
mux.Handle("GET /static/", fs)
h.Handler = mux
} }
func New(store *store.Store) *Server { func New(store *store.Store) *Server {
var server Server var server Server
server.routes = map[string]route{
"GET /order/": {server.order},
"GET /orders": {server.orders},
"GET /orders/search/": {server.ordersSearch},
"GET /cake/": {server.cake},
"GET /cakes": {server.cakes},
"POST /order/": {server.postOrder},
"POST /cake/": {server.postCake},
}
server.s = store server.s = store
server.loadHandler()
mux := http.NewServeMux()
mux.HandleFunc("GET /", redirect("/orders", http.StatusSeeOther))
mux.HandleFunc("GET /order/", server.render(server.order))
mux.HandleFunc("GET /orders", server.render(server.orders))
mux.HandleFunc("GET /orders/search/", server.render(server.ordersSearch))
mux.HandleFunc("GET /cake/", server.render(server.cake))
mux.HandleFunc("GET /cakes", server.render(server.cakes))
mux.HandleFunc("POST /order/", server.render(server.postOrder))
mux.HandleFunc("POST /cake/", server.render(server.postCake))
fs := http.FileServerFS(static)
mux.Handle("GET /static/", fs)
server.Handler = mux
return &server return &server
} }

View file

@ -2,94 +2,56 @@ package store
import ( import (
"errors" "errors"
"fmt" "log"
"git.bronku.xyz/bronku/cake-order-tracker/models" "git.bronku.xyz/bronku/cake-order-tracker/models"
) )
func (s *Store) cakeCount() int {
out := 0
rows, err := s.db.Query("select count(*) from cake;")
if err != nil {
return out
}
defer rows.Close()
_ = rows.Next()
_ = rows.Scan(&out)
return out
}
func (s *Store) loadCakes() ([]models.Cake, error) {
out := make([]models.Cake, 0, s.cakeCount())
rows, err := s.db.Query("select id, name, price from cake order by id;")
if err != nil {
return out, err
}
defer rows.Close()
for rows.Next() {
var cake models.Cake
err = rows.Scan(&cake.ID, &cake.Name, &cake.Price)
if err != nil {
continue
}
out = append(out, cake)
}
return out, nil
}
func (s *Store) searchCakes(id int) (int, error) {
for i, e := range s.cakes {
if e.ID != id {
continue
}
return i, nil
}
return 0, errors.New("cake not found")
}
func (s *Store) GetCake(id int) (models.Cake, error) { func (s *Store) GetCake(id int) (models.Cake, error) {
if id <= 0 { if id <= 0 {
return models.Cake{}, errors.New("invalid cake id") return models.Cake{}, errors.New("invalid cake id")
} }
i, err := s.searchCakes(id) row := s.db.QueryRow("select id, name, price from cake where id = ?;", id)
var out models.Cake
err := row.Scan(&out.ID, &out.Name, &out.Price)
if err != nil { if err != nil {
return models.Cake{}, err return models.Cake{}, errors.New("cake not found")
} }
return s.cakes[i], err return out, nil
} }
func (s *Store) GetCakes() ([]models.Cake, error) { func (s *Store) GetCakes() ([]models.Cake, error) {
result := make([]models.Cake, len(s.cakes)) rows, err := s.db.Query("select id, name, price from cake order by id;")
copy(result, s.cakes)
return result, nil
}
func (s *Store) updateCake(newCake models.Cake) error {
query := "update cake set name = ? , price = ? where id = ?"
_, err := s.db.Exec(query, newCake.Name, newCake.Price, newCake.ID)
if err != nil { if err != nil {
return err return nil, err
} }
defer rows.Close()
i, err := s.searchCakes(newCake.ID) var out []models.Cake
if err != nil { for rows.Next() {
return err var cake models.Cake
if err := rows.Scan(&cake.ID, &cake.Name, &cake.Price); err != nil {
return nil, err
}
out = append(out, cake)
} }
s.cakes[i] = newCake return out, rows.Err()
return nil
} }
func (s *Store) SaveCake(newCake models.Cake) (int, error) { func (s *Store) SaveCake(newCake models.Cake) (int, error) {
if newCake.ID != 0 { if newCake.ID != 0 {
return newCake.ID, s.updateCake(newCake) q := "update cake set name = ?, price = ? where id = ?;"
_, err := s.db.Exec(q, newCake.Name, newCake.Price, newCake.ID)
if err != nil {
return 0, err
}
log.Printf("UPDATE cake id=%d name=%q price=%d", newCake.ID, newCake.Name, newCake.Price)
return newCake.ID, nil
} }
fmt.Println("adding a new cake", newCake)
query := "insert into cake(name, price) values (?, ? );" q := "insert into cake(name, price) values (?, ?);"
result, err := s.db.Exec(query, newCake.Name, newCake.Price) result, err := s.db.Exec(q, newCake.Name, newCake.Price)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -99,7 +61,6 @@ func (s *Store) SaveCake(newCake models.Cake) (int, error) {
return 0, err return 0, err
} }
newCake.ID = int(id) newCake.ID = int(id)
log.Printf("INSERT cake id=%d name=%q price=%d", newCake.ID, newCake.Name, newCake.Price)
s.cakes = append(s.cakes, newCake)
return newCake.ID, nil return newCake.ID, nil
} }

View file

@ -3,46 +3,52 @@ package store
import ( import (
"database/sql" "database/sql"
"errors" "errors"
"fmt" "log"
"time" "time"
"git.bronku.xyz/bronku/cake-order-tracker/config"
"git.bronku.xyz/bronku/cake-order-tracker/models" "git.bronku.xyz/bronku/cake-order-tracker/models"
) )
// #todo update labels in templates func (s *Store) scanOrderRow(row *sql.Rows) (models.Order, error) {
func (s *Store) parseOrderRow(row *sql.Rows) (models.Order, error) {
var out models.Order var out models.Order
var orderDate, deliveryDate string var orderDate, deliveryDate string
err := row.Scan(&out.ID, &out.Name, &out.Surname, &out.Phone, &out.Location, &orderDate, &deliveryDate, &out.Status, &out.Paid) err := row.Scan(&out.ID, &out.Name, &out.Surname, &out.Phone, &out.Location, &orderDate, &deliveryDate, &out.Status, &out.Paid)
if err != nil { if err != nil {
return out, err return out, err
} }
out.Accepted, _ = time.Parse("2006-01-02 15:04", orderDate) out.Accepted, err = time.Parse(config.DateTimeFormat, orderDate)
out.Date, _ = time.Parse("2006-01-02 15:04", deliveryDate)
out.Cakes = make([]models.Cake, 0)
rows, err := s.db.Query("select cake, amount from ordered_cake where customer_order = ?;", out.ID)
if err != nil { if err != nil {
return out, err return out, err
} }
out.Date, err = time.Parse(config.DateTimeFormat, deliveryDate)
if err != nil {
return out, err
}
return out, nil
}
func (s *Store) loadOrderCakes(orderID int) ([]models.Cake, error) {
var cakes []models.Cake
rows, err := s.db.Query("select cake, amount from ordered_cake where customer_order = ?;", orderID)
if err != nil {
return cakes, err
}
defer rows.Close() defer rows.Close()
for rows.Next() { for rows.Next() {
var newCake models.Cake var c models.Cake
err = rows.Scan(&newCake.ID, &newCake.Amount) if err := rows.Scan(&c.ID, &c.Amount); err != nil {
if err != nil { return cakes, err
return out, err
} }
cakeData, err := s.GetCake(newCake.ID) cakeData, err := s.GetCake(c.ID)
if err != nil { if err != nil {
continue continue
} }
newCake.Name = cakeData.Name c.Name = cakeData.Name
newCake.Price = cakeData.Price c.Price = cakeData.Price
out.Cakes = append(out.Cakes, newCake) cakes = append(cakes, c)
} }
return cakes, rows.Err()
return out, nil
} }
func (s *Store) getOrdersFromQuery(query string, args ...any) ([]models.Order, error) { func (s *Store) getOrdersFromQuery(query string, args ...any) ([]models.Order, error) {
@ -54,9 +60,12 @@ func (s *Store) getOrdersFromQuery(query string, args ...any) ([]models.Order, e
defer rows.Close() defer rows.Close()
for rows.Next() { for rows.Next() {
order, err := s.parseOrderRow(rows) order, err := s.scanOrderRow(rows)
if err != nil {
continue
}
order.Cakes, err = s.loadOrderCakes(order.ID)
if err != nil { if err != nil {
fmt.Println(err)
continue continue
} }
out = append(out, order) out = append(out, order)
@ -78,8 +87,8 @@ func (s *Store) GetOrder(id int) (models.Order, error) {
} }
func (s *Store) GetOrders(from, to time.Time) ([]models.Order, error) { func (s *Store) GetOrders(from, to time.Time) ([]models.Order, error) {
start := from.Format("2006-01-02") + " 00:00" start := from.Format(config.DateFormat) + " 00:00"
end := to.Format("2006-01-02") + " 99:99" end := to.Format(config.DateFormat) + " 99:99"
if to.IsZero() { if to.IsZero() {
end = "9999-99-99 99:99" end = "9999-99-99 99:99"
} }
@ -88,15 +97,15 @@ func (s *Store) GetOrders(from, to time.Time) ([]models.Order, error) {
} }
func (s *Store) UpdateOrderContents(tx *sql.Tx, newOrder models.Order) error { func (s *Store) UpdateOrderContents(tx *sql.Tx, newOrder models.Order) error {
query := "delete from ordered_cake where customer_order = ?;" q := "delete from ordered_cake where customer_order = ?;"
_, err := tx.Exec(query, newOrder.ID) _, err := tx.Exec(q, newOrder.ID)
if err != nil { if err != nil {
return err return err
} }
query = "insert into ordered_cake(customer_order, cake, amount) values (?,?,?);" q = "insert into ordered_cake(customer_order, cake, amount) values (?,?,?);"
for _, e := range newOrder.Cakes { for _, e := range newOrder.Cakes {
_, err := tx.Exec(query, newOrder.ID, e.ID, e.Amount) _, err := tx.Exec(q, newOrder.ID, e.ID, e.Amount)
if err != nil { if err != nil {
return err return err
} }
@ -109,17 +118,17 @@ func (s *Store) UpdateOrder(newOrder models.Order) error {
if err != nil { if err != nil {
return err return err
} }
query := "update customer_order set name = ?, surname = ?, phone = ?, location = ?, order_date = ?, delivery_date = ?, status = ?, paid = ? where id = ?;" q := "update customer_order set name = ?, surname = ?, phone = ?, location = ?, order_date = ?, delivery_date = ?, status = ?, paid = ? where id = ?;"
accepted := newOrder.Accepted.Format("2006-01-02 15:04") accepted := newOrder.Accepted.Format(config.DateTimeFormat)
date := newOrder.Date.Format("2006-01-02 15:04") date := newOrder.Date.Format(config.DateTimeFormat)
tx, err := s.db.Begin() tx, err := s.db.Begin()
if err != nil { if err != nil {
return err return err
} }
_, err = tx.Exec(query, newOrder.Name, newOrder.Surname, newOrder.Phone, newOrder.Location, accepted, date, newOrder.Status, newOrder.Paid, newOrder.ID) _, err = tx.Exec(q, newOrder.Name, newOrder.Surname, newOrder.Phone, newOrder.Location, accepted, date, newOrder.Status, newOrder.Paid, newOrder.ID)
if err != nil { if err != nil {
_ = tx.Rollback() _ = tx.Rollback()
return err return err
@ -132,6 +141,7 @@ func (s *Store) UpdateOrder(newOrder models.Order) error {
} }
err = tx.Commit() err = tx.Commit()
log.Printf("UPDATE order id=%d name=%q status=%q", newOrder.ID, newOrder.Name, newOrder.Status)
return nil return nil
} }
@ -139,16 +149,16 @@ func (s *Store) SaveOrder(newOrder models.Order) (int, error) {
if newOrder.ID != 0 { if newOrder.ID != 0 {
return newOrder.ID, s.UpdateOrder(newOrder) return newOrder.ID, s.UpdateOrder(newOrder)
} }
query := "insert into customer_order(name, surname, phone, location, order_date, delivery_date, status, paid) values (?, ?, ?, ?, ?, ?, ?, ?);" q := "insert into customer_order(name, surname, phone, location, order_date, delivery_date, status, paid) values (?, ?, ?, ?, ?, ?, ?, ?);"
tx, err := s.db.Begin() tx, err := s.db.Begin()
if err != nil { if err != nil {
return 0, err return 0, err
} }
accepted := newOrder.Accepted.Format("2006-01-02 15:04") accepted := newOrder.Accepted.Format(config.DateTimeFormat)
date := newOrder.Date.Format("2006-01-02 15:04") date := newOrder.Date.Format(config.DateTimeFormat)
result, err := tx.Exec(query, newOrder.Name, newOrder.Surname, newOrder.Phone, newOrder.Location, accepted, date, newOrder.Status, newOrder.Paid) result, err := tx.Exec(q, newOrder.Name, newOrder.Surname, newOrder.Phone, newOrder.Location, accepted, date, newOrder.Status, newOrder.Paid)
if err != nil { if err != nil {
_ = tx.Rollback() _ = tx.Rollback()
return 0, err return 0, err
@ -157,16 +167,17 @@ func (s *Store) SaveOrder(newOrder models.Order) (int, error) {
id, err := result.LastInsertId() id, err := result.LastInsertId()
if err != nil { if err != nil {
_ = tx.Rollback() _ = tx.Rollback()
return newOrder.ID, err return 0, err
} }
newOrder.ID = int(id) newOrder.ID = int(id)
err = s.UpdateOrderContents(tx, newOrder) err = s.UpdateOrderContents(tx, newOrder)
if err != nil { if err != nil {
_ = tx.Rollback() _ = tx.Rollback()
return newOrder.ID, err return 0, err
} }
err = tx.Commit() err = tx.Commit()
log.Printf("INSERT order id=%d name=%q status=%q", newOrder.ID, newOrder.Name, newOrder.Status)
return newOrder.ID, err return newOrder.ID, err
} }

View file

@ -4,13 +4,11 @@ import (
"database/sql" "database/sql"
"log" "log"
"git.bronku.xyz/bronku/cake-order-tracker/models"
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
) )
type Store struct { type Store struct {
db *sql.DB db *sql.DB
cakes []models.Cake
} }
func OpenStore(filename string) *Store { func OpenStore(filename string) *Store {
@ -23,11 +21,6 @@ func OpenStore(filename string) *Store {
} }
out.loadMigrations() out.loadMigrations()
out.cakes, err = out.loadCakes()
log.Println(out.cakes)
if err != nil {
log.Fatal(err)
}
return &out return &out
} }

View file

@ -1,6 +1,7 @@
package store package store
import ( import (
"slices"
"testing" "testing"
"time" "time"
@ -284,10 +285,5 @@ mainLoop:
} }
} }
} }
for _, e := range matched { return !slices.Contains(matched, false)
if e == false {
return false
}
}
return true
} }