diff --git a/.gitignore b/.gitignore index ea4d9e0..be55ec9 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,9 @@ go.work go.work.sum +# Generated templ code +*_templ.go + # env file .env .idea diff --git a/go.mod b/go.mod index 050d73f..5ae13f9 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,26 @@ module git.bronku.xyz/bronku/cake-order-tracker -go 1.23.5 +go 1.25.0 require github.com/mattn/go-sqlite3 v1.14.24 + +require github.com/a-h/templ v0.3.1020 + +require ( + github.com/a-h/parse v0.0.0-20250122154542-74294addb73e // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cli/browser v1.3.0 // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/natefinch/atomic v1.0.1 // indirect + golang.org/x/mod v0.26.0 // indirect + golang.org/x/net v0.51.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.41.0 // indirect + golang.org/x/tools v0.35.0 // indirect +) + +tool github.com/a-h/templ/cmd/templ diff --git a/go.sum b/go.sum index 9dcdc9b..e32de87 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,45 @@ +github.com/a-h/parse v0.0.0-20250122154542-74294addb73e h1:HjVbSQHy+dnlS6C3XajZ69NYAb5jbGNfHanvm1+iYlo= +github.com/a-h/parse v0.0.0-20250122154542-74294addb73e/go.mod h1:3mnrkvGpurZ4ZrTDbYU84xhwXW2TjTKShSwjRi2ihfQ= +github.com/a-h/templ v0.3.1020 h1:ypAT/L5ySWEnZ6Zft/5yfoWXYYkhFNvEFOeeqecg4tw= +github.com/a-h/templ v0.3.1020/go.mod h1:A2DlK61v+K+NRoGnhmYbNYVmtYHcFO5/AisMvBdDxTM= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cli/browser v1.3.0 h1:LejqCrpWr+1pRqmEPDGnTZOjsMe7sehifLynZJuqJpo= +github.com/cli/browser v1.3.0/go.mod h1:HH8s+fOAxjhQoBUAsKuPCbqUuxZDhQ2/aD+SzsEfBTk= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM= github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/natefinch/atomic v1.0.1 h1:ZPYKxkqQOx3KZ+RsbnP/YsgvxWQPGxjC0oBt2AhwV0A= +github.com/natefinch/atomic v1.0.1/go.mod h1:N/D/ELrljoqDyT3rZrsUmtsuzvHkeB/wWjHV22AZRbM= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= +golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= +golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= +golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= +golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index ec5a151..a422b1f 100644 --- a/main.go +++ b/main.go @@ -1,5 +1,7 @@ package main +//go:generate go tool templ generate + import ( "log" "net/http" @@ -12,9 +14,9 @@ import ( func main() { s := store.OpenStore("./foo.db") defer s.Close() - h := server.New(s) - defer h.Close() + var h http.Handler = server.New(s) + h = logging.Middleware(h) log.Println("starting server") - log.Fatal(http.ListenAndServe(":8080", logging.Middleware(h))) + log.Fatal(http.ListenAndServe(":8080", h)) } diff --git a/server/fetcher.go b/server/fetcher.go index e30bd1a..f52b0aa 100644 --- a/server/fetcher.go +++ b/server/fetcher.go @@ -1,5 +1,9 @@ package server -import "net/http" +import ( + "net/http" -type fetcher func(r *http.Request) (any, int, error) + "github.com/a-h/templ" +) + +type fetcher func(r *http.Request) (templ.Component, int, error) diff --git a/server/get.go b/server/get.go index ff3d3f3..ef9196c 100644 --- a/server/get.go +++ b/server/get.go @@ -1,13 +1,15 @@ package server import ( - "fmt" "net/http" "strconv" "strings" "time" + "github.com/a-h/templ" + "git.bronku.xyz/bronku/cake-order-tracker/models" + "git.bronku.xyz/bronku/cake-order-tracker/server/templates" ) func monthInterval(y int, m time.Month) (firstDay, lastDay time.Time) { @@ -16,24 +18,18 @@ func monthInterval(y int, m time.Month) (firstDay, lastDay time.Time) { return firstDay, lastDay } -func (h *Server) orders(_ *http.Request) (any, int, error) { +func (h *Server) orders(_ *http.Request) (templ.Component, int, error) { var ( y int m time.Month ) y, m, _ = time.Now().Date() first, last := monthInterval(y, m) - fmt.Println(first, last) orders, err := h.s.GetOrders(first, last) - data := struct { - First string - Last string - Orders []models.Order - }{first.Format("2006-01-02"), last.Format("2006-01-02"), orders} - return data, http.StatusOK, err + return templates.OrdersPage(first.Format("2006-01-02"), last.Format("2006-01-02"), orders), http.StatusOK, err } -func (h *Server) ordersSearch(r *http.Request) (any, 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")) if err != nil { from = time.Time{} @@ -42,20 +38,19 @@ func (h *Server) ordersSearch(r *http.Request) (any, int, error) { if err != nil { to = time.Time{} } - fmt.Println(from, to) data, err := h.s.GetOrders(from, to) - return data, http.StatusOK, err + return templates.OrdersTable(data), http.StatusOK, err } -func (h *Server) cakes(_ *http.Request) (any, int, error) { +func (h *Server) cakes(_ *http.Request) (templ.Component, int, error) { data, err := h.s.GetCakes() - return data, http.StatusOK, err + return templates.CakesPage(data), http.StatusOK, err } -func (h *Server) cake(r *http.Request) (any, int, error) { +func (h *Server) cake(r *http.Request) (templ.Component, int, error) { url := strings.Split(r.URL.String(), "/") if len(url) < 3 || url[2] == "" { - return models.Cake{}, http.StatusOK, nil + return templates.CakePage(models.Cake{}), http.StatusOK, nil } id, err := strconv.Atoi(url[2]) @@ -68,26 +63,19 @@ func (h *Server) cake(r *http.Request) (any, int, error) { return nil, http.StatusNotFound, err } - return data, http.StatusOK, nil + return templates.CakePage(data), http.StatusOK, nil } -func (h *Server) order(r *http.Request) (any, int, error) { - type formData struct { - Order models.Order - Catalogue []models.Cake - } +func (h *Server) order(r *http.Request) (templ.Component, int, error) { var err error - var data formData - - data.Catalogue, err = h.s.GetCakes() + catalogue, err := h.s.GetCakes() if err != nil { return nil, http.StatusInternalServerError, err } url := strings.Split(r.URL.String(), "/") if len(url) < 3 || url[2] == "" { - data.Order.Date = time.Now() - return data, http.StatusOK, nil + return templates.OrderPage(models.Order{Date: time.Now()}, catalogue), http.StatusOK, nil } id, err := strconv.Atoi(url[2]) @@ -95,10 +83,10 @@ func (h *Server) order(r *http.Request) (any, int, error) { return nil, http.StatusBadRequest, err } - data.Order, err = h.s.GetOrder(id) + order, err := h.s.GetOrder(id) if err != nil { return nil, http.StatusNotFound, err } - return data, http.StatusOK, nil + return templates.OrderPage(order, catalogue), http.StatusOK, nil } diff --git a/server/post.go b/server/post.go index 3bcc116..8e08547 100644 --- a/server/post.go +++ b/server/post.go @@ -7,10 +7,13 @@ import ( "strings" "time" + "github.com/a-h/templ" + "git.bronku.xyz/bronku/cake-order-tracker/models" + "git.bronku.xyz/bronku/cake-order-tracker/server/templates" ) -func (h *Server) postCake(r *http.Request) (any, int, error) { +func (h *Server) postCake(r *http.Request) (templ.Component, int, error) { err := r.ParseForm() if err != nil { return nil, http.StatusInternalServerError, err @@ -28,10 +31,10 @@ func (h *Server) postCake(r *http.Request) (any, int, error) { } n.ID, err = h.s.SaveCake(n) fmt.Println(err) - return n, http.StatusAccepted, err + return templates.Confirmation("Potwierdzone", n.ID), http.StatusAccepted, err } -func (h *Server) postOrder(r *http.Request) (any, int, error) { +func (h *Server) postOrder(r *http.Request) (templ.Component, int, error) { cakes, err := h.s.GetCakes() if err != nil { return nil, http.StatusInternalServerError, err @@ -75,5 +78,5 @@ func (h *Server) postOrder(r *http.Request) (any, int, error) { n.ID, err = h.s.SaveOrder(n) fmt.Println(n) - return n, http.StatusAccepted, err + return templates.Confirmation("Potwierdzone", n.ID), http.StatusAccepted, err } diff --git a/server/server.go b/server/server.go index 9b594dd..6b3ee3f 100644 --- a/server/server.go +++ b/server/server.go @@ -2,27 +2,19 @@ package server import ( "embed" - "html/template" "net/http" "git.bronku.xyz/bronku/cake-order-tracker/store" ) type Server struct { - tmpl map[string]*template.Template s *store.Store routes map[string]route http.Handler } type route struct { - function fetcher - template string - templateEntry string -} - -func (h *Server) Close() { - h.Close() + function fetcher } //go:embed static/* @@ -32,7 +24,7 @@ func (h *Server) loadHandler() { mux := http.NewServeMux() for i, e := range h.routes { - mux.HandleFunc(i, h.render(e.function, e.template, e.templateEntry)) + mux.HandleFunc(i, h.render(e.function)) } mux.HandleFunc("GET /", h.redirect("/orders", http.StatusSeeOther)) @@ -47,16 +39,15 @@ func New(store *store.Store) *Server { var server Server server.routes = map[string]route{ - "GET /order/": {server.order, "order", "layout"}, - "GET /orders": {server.orders, "orders", "layout"}, - "GET /orders/search/": {server.ordersSearch, "orders", "orders-table"}, - "GET /cake/": {server.cake, "cake", "layout"}, - "GET /cakes": {server.cakes, "cakes", "layout"}, - "POST /order/": {server.postOrder, "confirmation", "layout"}, - "POST /cake/": {server.postCake, "confirmation", "layout"}, + "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.loadTemplates() server.s = store server.loadHandler() diff --git a/server/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2 b/server/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2 new file mode 100644 index 0000000..d750914 Binary files /dev/null and b/server/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2 differ diff --git a/server/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2 b/server/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2 new file mode 100644 index 0000000..d15208d Binary files /dev/null and b/server/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2 differ diff --git a/server/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2 b/server/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2 new file mode 100644 index 0000000..024f077 Binary files /dev/null and b/server/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2 differ diff --git a/server/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2 b/server/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2 new file mode 100644 index 0000000..479d010 Binary files /dev/null and b/server/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2 differ diff --git a/server/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2 b/server/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2 new file mode 100644 index 0000000..de83a9c Binary files /dev/null and b/server/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2 differ diff --git a/server/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2 b/server/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2 new file mode 100644 index 0000000..6e7141f Binary files /dev/null and b/server/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2 differ diff --git a/server/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2 b/server/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2 new file mode 100644 index 0000000..a40c469 Binary files /dev/null and b/server/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2 differ diff --git a/server/static/fonts/inter.css b/server/static/fonts/inter.css new file mode 100644 index 0000000..62697ea --- /dev/null +++ b/server/static/fonts/inter.css @@ -0,0 +1,315 @@ +/* cyrillic-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2JL7SUc.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa0ZL7SUc.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2ZL7SUc.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1pL7SUc.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa2pL7SUc.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa25L7SUc.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url(/static/fonts/UcC73FwrK3iLTeHuS_nVMrMxCp50SjIa1ZL7.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} diff --git a/server/static/fonts/kJESBvYX7BgnkSrUwT8OhrdQw4oELdPIeeII9v6oDMzBwG-RpA6RzaxHMO1W.woff2 b/server/static/fonts/kJESBvYX7BgnkSrUwT8OhrdQw4oELdPIeeII9v6oDMzBwG-RpA6RzaxHMO1W.woff2 new file mode 100644 index 0000000..2d22eb4 Binary files /dev/null and b/server/static/fonts/kJESBvYX7BgnkSrUwT8OhrdQw4oELdPIeeII9v6oDMzBwG-RpA6RzaxHMO1W.woff2 differ diff --git a/server/static/fonts/material.css b/server/static/fonts/material.css new file mode 100644 index 0000000..a38a17a --- /dev/null +++ b/server/static/fonts/material.css @@ -0,0 +1,24 @@ +/* fallback */ +@font-face { + font-family: 'Material Symbols Outlined'; + font-style: normal; + font-weight: 100 700; + font-display: swap; + src: url(/static/fonts/kJESBvYX7BgnkSrUwT8OhrdQw4oELdPIeeII9v6oDMzBwG-RpA6RzaxHMO1W.woff2) format('woff2'); +} + +.material-symbols-outlined { + font-family: 'Material Symbols Outlined'; + font-weight: normal; + font-style: normal; + font-size: 24px; + line-height: 1; + letter-spacing: normal; + text-transform: none; + display: inline-block; + white-space: nowrap; + word-wrap: normal; + direction: ltr; + -webkit-font-feature-settings: 'liga'; + -webkit-font-smoothing: antialiased; +} diff --git a/server/template.go b/server/template.go index adff311..e31b080 100644 --- a/server/template.go +++ b/server/template.go @@ -1,47 +1,23 @@ package server import ( - "embed" - "html/template" - "log" "net/http" "git.bronku.xyz/bronku/cake-order-tracker/logging" ) -//go:embed templates/* -var templates embed.FS - -func (h *Server) loadTemplates() { - h.tmpl = make(map[string]*template.Template) - funcs := template.FuncMap{ - "add": func(a, b int) int { return a + b }, - "mult": func(a, b int) int { return a * b }, - } - for _, page := range h.routes { - tmpl, err := template.New("").Funcs(funcs).ParseFS(templates, - "templates/layout/*.gohtml", - "templates/"+page.template+".gohtml", - ) - if err != nil { - log.Fatal(err) - } - h.tmpl[page.template] = tmpl - } -} - -func (h *Server) render(fetch fetcher, templateFile string, templateEntry string) http.HandlerFunc { +func (h *Server) render(fetch fetcher) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - data, code, err := fetch(r) + component, code, err := fetch(r) if err != nil { logging.ErrorPage(err, code).ServeHTTP(w, r) return } - err = h.tmpl[templateFile].ExecuteTemplate(w, templateEntry, data) + w.Header().Set("content-type", "text/html") + err = component.Render(r.Context(), w) if err != nil { logging.ErrorPage(err, http.StatusInternalServerError).ServeHTTP(w, r) return } - w.Header().Set("content-type", "text/html") } } diff --git a/server/templates/cake.gohtml b/server/templates/cake.gohtml deleted file mode 100644 index 81bb0e4..0000000 --- a/server/templates/cake.gohtml +++ /dev/null @@ -1,33 +0,0 @@ -{{define "title"}} -Ciasto {{if .ID}}#{{.ID}}{{else}}nowe{{end}} -{{end}} -{{define "main"}} -
-
-
-

- cake - {{if .ID}}Edytuj ciasto #{{.ID}}{{else}}Nowe ciasto{{end}} -

-
-
- -
- - -
-
- - -
-
- Anuluj - -
-
-
-
-{{end}} diff --git a/server/templates/cake.templ b/server/templates/cake.templ new file mode 100644 index 0000000..83b6c46 --- /dev/null +++ b/server/templates/cake.templ @@ -0,0 +1,46 @@ +package templates + +import ( + "strconv" + + "git.bronku.xyz/bronku/cake-order-tracker/models" +) + +templ CakePage(cake models.Cake) { + @Layout(cakeTitle(cake), CakeForm(cake)) +} + +templ CakeForm(cake models.Cake) { +
+
+
+

+ cake + if cake.ID != 0 { + Edytuj ciasto #{ strconv.Itoa(cake.ID) } + } else { + Nowe ciasto + } +

+
+
+ +
+ + +
+
+ + +
+
+ Anuluj + +
+
+
+
+} diff --git a/server/templates/cakes.gohtml b/server/templates/cakes.gohtml deleted file mode 100644 index 04ac8f4..0000000 --- a/server/templates/cakes.gohtml +++ /dev/null @@ -1,61 +0,0 @@ -{{define "title"}} -Katalog -{{end}} -{{define "main"}} -
-
-

- inventory_2 - Zarządzanie katalogiem -

- - add - Nowe ciasto - -
-
- - - - - - - - - - - - {{range .}} - - - - - - - - {{end}} - -
NazwaSKUCena bazowa
-
- cake -
-
{{.Name}}#{{.ID}}{{.Price}} PLN - - edit - -
-
- -
-{{end}} diff --git a/server/templates/cakes.templ b/server/templates/cakes.templ new file mode 100644 index 0000000..d931304 --- /dev/null +++ b/server/templates/cakes.templ @@ -0,0 +1,70 @@ +package templates + +import ( + "strconv" + + "git.bronku.xyz/bronku/cake-order-tracker/models" +) + +templ CakesPage(cakes []models.Cake) { + @Layout("Katalog", CakesMain(cakes)) +} + +templ CakesMain(cakes []models.Cake) { +
+
+

+ inventory_2 + Zarządzanie katalogiem +

+ + add + Nowe ciasto + +
+
+ + + + + + + + + + + + for _, c := range cakes { + + + + + + + + } + +
NazwaSKUCena bazowa
+
+ cake +
+
{ c.Name }#{ strconv.Itoa(c.ID) }{ strconv.Itoa(c.Price) } PLN + + edit + +
+
+ +
+} diff --git a/server/templates/confirmation.gohtml b/server/templates/confirmation.gohtml deleted file mode 100644 index 9ed0444..0000000 --- a/server/templates/confirmation.gohtml +++ /dev/null @@ -1,13 +0,0 @@ -{{define "title"}} -Potwierdzone -{{end}} -{{define "main"}} -
- check_circle -

{{.ID}} — zapisano

- - arrow_back - Powrót do zamówień - -
-{{end}} diff --git a/server/templates/confirmation.templ b/server/templates/confirmation.templ new file mode 100644 index 0000000..2307ef0 --- /dev/null +++ b/server/templates/confirmation.templ @@ -0,0 +1,18 @@ +package templates + +import "strconv" + +templ Confirmation(title string, id int) { + @Layout(title, ConfirmationBody(id)) +} + +templ ConfirmationBody(id int) { +
+ check_circle +

{ strconv.Itoa(id) } — zapisano

+ + arrow_back + Powrót do zamówień + +
+} diff --git a/server/templates/helpers.go b/server/templates/helpers.go new file mode 100644 index 0000000..74f6c87 --- /dev/null +++ b/server/templates/helpers.go @@ -0,0 +1,84 @@ +package templates + +import ( + "fmt" + "strconv" + "strings" + + "git.bronku.xyz/bronku/cake-order-tracker/models" +) + +func cakeTitle(cake models.Cake) string { + if cake.ID != 0 { + return "Ciasto #" + strconv.Itoa(cake.ID) + } + return "Ciasto nowe" +} + +func orderTitle(order models.Order) string { + if order.ID != 0 { + return "Edytuj zamówienie #" + strconv.Itoa(order.ID) + } + return "Nowe zamówienie" +} + +func orderSubtotal(order models.Order) int { + sub := 0 + for _, c := range order.Cakes { + sub += c.Price * c.Amount + } + return sub +} + +func countPending(orders []models.Order) int { + n := 0 + for _, o := range orders { + if o.Status != "done" { + n++ + } + } + return n +} + +func countDone(orders []models.Order) int { + n := 0 + for _, o := range orders { + if o.Status == "done" { + n++ + } + } + return n +} + +func estimateRevenue(orders []models.Order) int { + total := 0 + for _, o := range orders { + for _, c := range o.Cakes { + total += c.Price * c.Amount + } + } + return total +} + +func cakeItemsDesc(cakes []models.Cake) string { + desc := "" + for i, c := range cakes { + if i > 0 { + desc += ", " + } + desc += c.Name + " (x" + strconv.Itoa(c.Amount) + ")" + } + return desc +} + +func orderScript(order models.Order) string { + var b strings.Builder + b.WriteString("") + return b.String() +} diff --git a/server/templates/layout.templ b/server/templates/layout.templ new file mode 100644 index 0000000..2af9aca --- /dev/null +++ b/server/templates/layout.templ @@ -0,0 +1,43 @@ +package templates + +templ Layout(title string, main templ.Component) { + + + + + + { title } — Zamówienia ciast + + + + + + + + +
+
+
+

{ title }

+
+
+
+ @main +
+
+ + + +} diff --git a/server/templates/layout/layout.gohtml b/server/templates/layout/layout.gohtml deleted file mode 100644 index 44949c3..0000000 --- a/server/templates/layout/layout.gohtml +++ /dev/null @@ -1,43 +0,0 @@ -{{define "layout"}} - - - - - - {{template "title" .}} — Zamówienia ciast - - - - - - - - - - -
-
-
-

{{template "title" .}}

-
-
-
- {{template "main" .}} -
-
- - - -{{end}} diff --git a/server/templates/layout/nav.gohtml b/server/templates/layout/nav.gohtml deleted file mode 100644 index 2749d3f..0000000 --- a/server/templates/layout/nav.gohtml +++ /dev/null @@ -1,16 +0,0 @@ -{{define "nav"}} - - add - Nowe zamówienie - - -{{end}} diff --git a/server/templates/nav.templ b/server/templates/nav.templ new file mode 100644 index 0000000..aee619b --- /dev/null +++ b/server/templates/nav.templ @@ -0,0 +1,18 @@ +package templates + +templ Nav() { + + add + Nowe zamówienie + + +} diff --git a/server/templates/order.gohtml b/server/templates/order.gohtml deleted file mode 100644 index 75ed842..0000000 --- a/server/templates/order.gohtml +++ /dev/null @@ -1,151 +0,0 @@ -{{define "title"}} - {{if .Order.ID}} - Edytuj zamówienie #{{.Order.ID}} - {{else}} - Nowe zamówienie - {{end}} -{{end}} -{{define "main"}} -
- {{$catalogue := .Catalogue}} - {{with .Order}} - -
-
-
-

- person_add - Dane klienta -

-
-
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
-
-
-
-
-

- inventory_2 - Katalog produktów -

- -
-
-
- {{range $catalogue}} -
-
-
- cake -
-
-
{{.Name}}
-
{{.Price}} PLN
-
-
-
- - 0 - -
-
- {{end}} -
-
-
-
- - {{end}} -
- -{{end}} diff --git a/server/templates/order.templ b/server/templates/order.templ new file mode 100644 index 0000000..a12eb2e --- /dev/null +++ b/server/templates/order.templ @@ -0,0 +1,144 @@ +package templates + +import ( + "strconv" + + "git.bronku.xyz/bronku/cake-order-tracker/models" +) + +templ OrderPage(order models.Order, catalogue []models.Cake) { + @Layout(orderTitle(order), OrderForm(order, catalogue)) +} + +templ OrderForm(order models.Order, catalogue []models.Cake) { +
+ +
+
+
+

+ person_add + Dane klienta +

+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+
+

+ inventory_2 + Katalog produktów +

+ +
+
+
+ for _, c := range catalogue { +
+
+
+ cake +
+
+
{ c.Name }
+
{ strconv.Itoa(c.Price) } PLN
+
+
+
+ + 0 + +
+
+ } +
+
+
+
+ +
+ @templ.Raw(orderScript(order)) +} diff --git a/server/templates/orders.gohtml b/server/templates/orders.gohtml deleted file mode 100644 index e837b70..0000000 --- a/server/templates/orders.gohtml +++ /dev/null @@ -1,126 +0,0 @@ -{{define "title"}} -Panel główny -{{end}} -{{define "main"}} -
-
- - receipt_long - Zamówienia dzisiaj - - {{len .Orders}} - - arrow_upward - Wszystkie aktywne - -
-
- - cake - Do realizacji - - - {{$pending := 0}} - {{range .Orders}}{{if ne .Status "done"}}{{$pending = add $pending 1}}{{end}}{{end}} - {{$pending}} - - - priority_high - Oczekujące - -
-
- - check_circle - Gotowe do odbioru - - - {{$done := 0}} - {{range .Orders}}{{if eq .Status "done"}}{{$done = add $done 1}}{{end}}{{end}} - {{$done}} - - Zrealizowane -
-
- - payments - Przychód (szac.) - - - {{$total := 0}} - {{range .Orders}}{{range .Cakes}}{{$total = add $total (mult .Price .Amount)}}{{end}}{{end}} - {{$total}} PLN - - - trending_up - W bieżącym miesiącu - -
-
- -
-
-

- list_alt - Aktywne zamówienia -

-
-
-
- - -
-
- - -
-
-
-
-
- {{template "orders-table" .Orders}} -
-
-{{end}} -{{define "orders-table"}} - - - - - - - - - - - - - - {{range .}} - - - - - - - - - - {{end}} - -
ID zamówieniaKlientData odbioruPozycjeSumaStatus
#{{.ID}}{{.Surname}} {{.Name}}
{{.Phone}}
{{.Date.Format "2006-01-02 15:04"}} - - {{range $i, $c := .Cakes}}{{if $i}}, {{end}}{{.Name}} (x{{.Amount}}){{end}} - - {{.Total}} PLN - - {{if eq .Status "accepted"}}Przyjęte - {{else if eq .Status "done"}}Gotowe - {{else}}Oczekujące{{end}} - - - - edit - -
-{{end}} diff --git a/server/templates/orders.templ b/server/templates/orders.templ new file mode 100644 index 0000000..e76186f --- /dev/null +++ b/server/templates/orders.templ @@ -0,0 +1,133 @@ +package templates + +import ( + "strconv" + + "git.bronku.xyz/bronku/cake-order-tracker/models" +) + +templ OrdersPage(first, last string, orders []models.Order) { + @Layout("Panel główny", OrdersMain(first, last, orders)) +} + +templ OrdersMain(first, last string, orders []models.Order) { +
+
+ + receipt_long + Zamówienia dzisiaj + + { len(orders) } + + arrow_upward + Wszystkie aktywne + +
+
+ + cake + Do realizacji + + { strconv.Itoa(countPending(orders)) } + + priority_high + Oczekujące + +
+
+ + check_circle + Gotowe do odbioru + + { strconv.Itoa(countDone(orders)) } + Zrealizowane +
+
+ + payments + Przychód (szac.) + + { strconv.Itoa(estimateRevenue(orders)) } PLN + + trending_up + W bieżącym miesiącu + +
+
+ +
+
+

+ list_alt + Aktywne zamówienia +

+
+
+
+ + +
+
+ + +
+
+
+
+
+ @OrdersTable(orders) +
+
+} + +templ OrdersTable(orders []models.Order) { + + + + + + + + + + + + + + for _, o := range orders { + + + + + + + + + + } + +
ID zamówieniaKlientData odbioruPozycjeSumaStatus
#{ strconv.Itoa(o.ID) }{ o.Surname } { o.Name }
{ o.Phone }
{ o.Date.Format("2006-01-02 15:04") } + + for i, c := range o.Cakes { + if i > 0 { + { ", " } + } + { c.Name } (x{ strconv.Itoa(c.Amount) }) + } + + { strconv.Itoa(o.Total()) } PLN + + if o.Status == "accepted" { + Przyjęte + } else if o.Status == "done" { + Gotowe + } else { + Oczekujące + } + + + + edit + +
+}