From f39b6205d1da634463bbadab33a2558c81665a26 Mon Sep 17 00:00:00 2001 From: kalipso Date: Thu, 10 Apr 2025 12:54:03 +0200 Subject: [PATCH] add basic print controller + view --- controllers/printController.go | 75 ++++++++++++++++++ controllers/shopItemController.go | 123 ++++++++++++++---------------- main.go | 3 + static/output.css | 5 ++ views/orderpreview.html | 93 ++++++++++++++++++++++ views/printvariant.html | 72 +++++++++++++++++ 6 files changed, 307 insertions(+), 64 deletions(-) create mode 100644 controllers/printController.go create mode 100644 views/orderpreview.html create mode 100644 views/printvariant.html diff --git a/controllers/printController.go b/controllers/printController.go new file mode 100644 index 0000000..a1c5d37 --- /dev/null +++ b/controllers/printController.go @@ -0,0 +1,75 @@ +package controllers + +import ( + "fmt" + "net/http" + + "example.com/gin/test/models" + "example.com/gin/test/repositories" + "github.com/gin-gonic/gin" +) + +type PrintController interface { + PrintVariantView(*gin.Context) + PrintVariantHandler(*gin.Context) +} + +type printController struct{} + +func NewPrintController() PrintController { + return &printController{} +} + +func (rc *printController) PrintVariantView(c *gin.Context) { + variant, err := repositories.ShopItems.GetVariantById(c.Param("id")) + + if err != nil { + c.HTML(http.StatusBadRequest, "error.html", gin.H{"data": gin.H{"error": err}}) + } + + shopItem, err := repositories.ShopItems.GetById(fmt.Sprintf("%v", variant.ShopItemID)) + + if err != nil { + c.HTML(http.StatusBadRequest, "error.html", gin.H{"data": gin.H{"error": err}}) + } + + type ShopItemVariantPair struct { + ShopItem models.ShopItem + ItemVariant models.ItemVariant + } + + data := CreateSessionData(c, gin.H{ + "itemVariants": []ShopItemVariantPair{ + {ShopItem: shopItem, ItemVariant: variant}, + }, + }) + + fmt.Println(data) + + c.HTML(http.StatusOK, "printvariant.html", data) +} + +func (rc *printController) PrintVariantHandler(c *gin.Context) { + err := repositories.ShopItems.DeleteById(c.Param("id")) + + if err != nil { + data := CreateSessionData(c, gin.H{ + "error": err, + "success": "", + }) + + c.HTML(http.StatusOK, "deleteitem.html", data) + } + + shopItems, _ := repositories.ShopItems.GetAll() + fmt.Println(len(shopItems)) + + data := CreateSessionData(c, gin.H{ + "title": "shopItem Page", + "shopItems": shopItems, + }) + + fmt.Println(data) + + c.HTML(http.StatusOK, "index.html", data) +} diff --git a/controllers/shopItemController.go b/controllers/shopItemController.go index 0f5535b..8db096f 100644 --- a/controllers/shopItemController.go +++ b/controllers/shopItemController.go @@ -3,9 +3,9 @@ package controllers import ( "fmt" "net/http" - "strconv" - "path/filepath" "os/exec" + "path/filepath" + "strconv" "github.com/gin-gonic/gin" @@ -16,7 +16,7 @@ import ( type CRUDController interface { Create(*gin.Context) - GetAll(*gin.Context) + GetAll(*gin.Context) GetById(*gin.Context) Update(*gin.Context) Delete(*gin.Context) @@ -38,7 +38,7 @@ type ShopItemController interface { AddTagHandler(*gin.Context) } -type shopItemController struct {} +type shopItemController struct{} func NewShopItemController() ShopItemController { return &shopItemController{} @@ -80,9 +80,9 @@ func (rc *shopItemController) NewShopItemFromForm(ctx *gin.Context) (models.Shop if err == nil { dstImage = filepath.Join("static/uploads", image.Filename) - if err := ctx.SaveUploadedFile(image, dstImage); err != nil { + if err := ctx.SaveUploadedFile(image, dstImage); err != nil { return models.ShopItem{}, fmt.Errorf("Could not save image") - } + } } dstPdf := "" @@ -90,13 +90,13 @@ func (rc *shopItemController) NewShopItemFromForm(ctx *gin.Context) (models.Shop if err == nil { dstPdf = filepath.Join("static/uploads", pdf.Filename) - if err := ctx.SaveUploadedFile(pdf, dstPdf); err != nil { + if err := ctx.SaveUploadedFile(pdf, dstPdf); err != nil { return models.ShopItem{}, fmt.Errorf("Could not save PDF") - } + } if dstImage == defaultImagePath { dstImage = dstPdf + ".preview.png" - cmd := exec.Command("pdftoppm", "-png", "-singlefile", dstPdf, dstPdf + ".preview") + cmd := exec.Command("pdftoppm", "-png", "-singlefile", dstPdf, dstPdf+".preview") _, err := cmd.Output() if err != nil { @@ -125,29 +125,29 @@ func (rc *shopItemController) NewShopItemFromForm(ctx *gin.Context) (models.Shop for idx := range variantNames { if variantValues[idx] == "" || variantNames[idx] == "" { continue - } + } price, err := strconv.ParseFloat(variantValues[idx], 64) - if err != nil { + if err != nil { return models.ShopItem{}, fmt.Errorf("Could not variant parse price") - } + } - variants = append(variants, models.ItemVariant{ - Name: variantNames[idx], + variants = append(variants, models.ItemVariant{ + Name: variantNames[idx], Price: price, }) } shopItem := models.ShopItem{ - Name: name, - Abstract: abstract, + Name: name, + Abstract: abstract, Description: description, - Category: category, - IsPublic: true, - BasePrice: rc.GetBasePrice(variants), - Image: dstImage, - Pdf: dstPdf, - Variants: variants, + Category: category, + IsPublic: true, + BasePrice: rc.GetBasePrice(variants), + Image: dstImage, + Pdf: dstPdf, + Variants: variants, } for _, tagId := range tagIds { @@ -198,7 +198,6 @@ func (rc *shopItemController) Create(c *gin.Context) { ReplyOK(c, "shopItem was created") } - func (rc *shopItemController) Update(c *gin.Context) { shopItemId, err := strconv.Atoi(c.Param("id")) @@ -225,7 +224,7 @@ func (rc *shopItemController) Update(c *gin.Context) { ReplyOK(c, "shopItem was updated") } -//TODO: delete associated cartitems +// TODO: delete associated cartitems func (rc *shopItemController) Delete(c *gin.Context) { err := repositories.ShopItems.DeleteById(c.Param("id")) @@ -241,19 +240,19 @@ func (rc *shopItemController) ShopItemView(c *gin.Context) { shopItem, err := repositories.ShopItems.GetById(c.Param("id")) if err != nil { - c.HTML(http.StatusBadRequest, "shopitem.html", gin.H{ "data": gin.H{ "error": err } }) + c.HTML(http.StatusBadRequest, "shopitem.html", gin.H{"data": gin.H{"error": err}}) } //TODO: get tags by item tags, err := repositories.Tags.GetAll() if err != nil { - c.HTML(http.StatusBadRequest, "shopitem.html", gin.H{ "data": gin.H{ "error": err } }) + c.HTML(http.StatusBadRequest, "shopitem.html", gin.H{"data": gin.H{"error": err}}) } data := CreateSessionData(c, gin.H{ "shopItem": shopItem, - "tags": tags, + "tags": tags, }) if err != nil { @@ -267,25 +266,24 @@ func (rc *shopItemController) AddItemView(c *gin.Context) { tags, err := repositories.Tags.GetAll() if err != nil { - c.HTML(http.StatusBadRequest, "additem.html", gin.H{ "error": err }) + c.HTML(http.StatusBadRequest, "additem.html", gin.H{"error": err}) } data := CreateSessionData(c, gin.H{ - "error": "", + "error": "", "success": "", - "tags": tags, + "tags": tags, }) c.HTML(http.StatusOK, "additem.html", data) } - func (rc *shopItemController) AddItemHandler(c *gin.Context) { errorHandler := func(err error, tags []models.Tag) { data := CreateSessionData(c, gin.H{ - "error": err, + "error": err, "success": "", - "tags": tags, + "tags": tags, }) c.HTML(http.StatusOK, "additem.html", data) @@ -310,48 +308,46 @@ func (rc *shopItemController) AddItemHandler(c *gin.Context) { } data := CreateSessionData(c, gin.H{ - "error": "", + "error": "", "success": fmt.Sprintf("Item '%s' Registered", shopItem.Name), - "tags": tags, + "tags": tags, }) c.HTML(http.StatusOK, "additem.html", data) } - func (rc *shopItemController) EditItemView(c *gin.Context) { shopItem, err := repositories.ShopItems.GetById(c.Param("id")) tags, err := repositories.Tags.GetAll() if err != nil { - c.HTML(http.StatusBadRequest, "edititem.html", gin.H{ "error": err }) + c.HTML(http.StatusBadRequest, "edititem.html", gin.H{"error": err}) } - + fmt.Println(shopItem) data := CreateSessionData(c, gin.H{ - "error": "", - "success": "", + "error": "", + "success": "", "shopItem": shopItem, - "tags": tags, + "tags": tags, }) c.HTML(http.StatusOK, "edititem.html", data) } - func (rc *shopItemController) EditItemHandler(c *gin.Context) { shopItem, err := rc.NewShopItemFromForm(c) if err != nil { - c.HTML(http.StatusBadRequest, "edititem.html", gin.H{ "error": err }) + c.HTML(http.StatusBadRequest, "edititem.html", gin.H{"error": err}) return } newShopItem, err := repositories.ShopItems.GetById(c.Param("id")) if err != nil { - c.HTML(http.StatusBadRequest, "edititem.html", gin.H{ "error": err }) + c.HTML(http.StatusBadRequest, "edititem.html", gin.H{"error": err}) return } @@ -365,16 +361,16 @@ func (rc *shopItemController) EditItemHandler(c *gin.Context) { tags, err := repositories.Tags.GetAll() if err != nil { - c.HTML(http.StatusBadRequest, "edititem.html", gin.H{ "error": err }) + c.HTML(http.StatusBadRequest, "edititem.html", gin.H{"error": err}) return } _, err = repositories.ShopItems.Update(newShopItem) if err != nil { data := CreateSessionData(c, gin.H{ - "error": err, + "error": err, "success": "", - "tags": tags, + "tags": tags, }) c.HTML(http.StatusOK, "edititem.html", data) @@ -382,9 +378,9 @@ func (rc *shopItemController) EditItemHandler(c *gin.Context) { } data := CreateSessionData(c, gin.H{ - "error": "", + "error": "", "success": fmt.Sprintf("Item '%s' Updated", newShopItem.Name), - "tags": tags, + "tags": tags, }) c.HTML(http.StatusOK, "edititem.html", data) @@ -395,28 +391,27 @@ func (rc *shopItemController) DeleteItemView(c *gin.Context) { tags, err := repositories.Tags.GetAll() if err != nil { - c.HTML(http.StatusBadRequest, "deleteitem.html", gin.H{ "error": err }) + c.HTML(http.StatusBadRequest, "deleteitem.html", gin.H{"error": err}) } - + fmt.Println(shopItem) data := CreateSessionData(c, gin.H{ - "error": "", - "success": "", + "error": "", + "success": "", "shopItem": shopItem, - "tags": tags, + "tags": tags, }) c.HTML(http.StatusOK, "deleteitem.html", data) } - func (rc *shopItemController) DeleteItemHandler(c *gin.Context) { err := repositories.ShopItems.DeleteById(c.Param("id")) if err != nil { data := CreateSessionData(c, gin.H{ - "error": err, + "error": err, "success": "", }) @@ -427,7 +422,7 @@ func (rc *shopItemController) DeleteItemHandler(c *gin.Context) { fmt.Println(len(shopItems)) data := CreateSessionData(c, gin.H{ - "title": "shopItem Page", + "title": "shopItem Page", "shopItems": shopItems, }) @@ -444,17 +439,17 @@ func (rc *shopItemController) TagHandler(ctx *gin.Context) { if err != nil { fmt.Println(err) - ctx.HTML(http.StatusBadRequest, "tagview.html", gin.H{ "error": err }) + ctx.HTML(http.StatusBadRequest, "tagview.html", gin.H{"error": err}) return } - + if action == "update" { tag.Name = name tag, err = repositories.Tags.Update(tag) if err != nil { fmt.Println(err) - ctx.HTML(http.StatusBadRequest, "tagview.html", gin.H{ "error": err }) + ctx.HTML(http.StatusBadRequest, "tagview.html", gin.H{"error": err}) return } } @@ -471,14 +466,14 @@ func (rc *shopItemController) AddTagHandler(c *gin.Context) { if err != nil { fmt.Println(err) - c.HTML(http.StatusBadRequest, "tagview.html", gin.H{ "error": err }) + c.HTML(http.StatusBadRequest, "tagview.html", gin.H{"error": err}) return } _, err = repositories.Tags.Create(tag) if err != nil { data := CreateSessionData(c, gin.H{ - "error": err, + "error": err, "success": "", }) @@ -493,7 +488,7 @@ func (rc *shopItemController) TagView(c *gin.Context) { tags, err := repositories.Tags.GetAll() if err != nil { - c.HTML(http.StatusBadRequest, "tagview.html", gin.H{ "data": gin.H{ "error": err } }) + c.HTML(http.StatusBadRequest, "tagview.html", gin.H{"data": gin.H{"error": err}}) } data := CreateSessionData(c, gin.H{ @@ -544,7 +539,7 @@ func (rc *shopItemController) GetAllTags(c *gin.Context) { } func ReplyError(ctx *gin.Context, err error) { - ctx.JSON(http.StatusBadRequest, gin.H{ "error": err.Error() }) + ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) } func ReplyOK(ctx *gin.Context, message any) { diff --git a/main.go b/main.go index 499314b..7403758 100644 --- a/main.go +++ b/main.go @@ -18,6 +18,7 @@ var ( shopItemController controllers.ShopItemController = controllers.NewShopItemController() userController controllers.UserController = controllers.UserController{} cartItemController controllers.CartItemController = controllers.NewCartItemController() + printController controllers.PrintController = controllers.NewPrintController() authValidator middlewares.AuthValidator = middlewares.AuthValidator{} ) @@ -81,6 +82,8 @@ func main() { viewRoutes.POST("/shopitems/:id/edit", authValidator.RequireAuth, shopItemController.EditItemHandler) viewRoutes.GET("/shopitems/:id/delete", authValidator.RequireAuth, shopItemController.DeleteItemView) viewRoutes.POST("/shopitems/:id/delete", authValidator.RequireAuth, shopItemController.DeleteItemHandler) + viewRoutes.GET("/variant/:id/print", authValidator.RequireAuth, printController.PrintVariantView) + viewRoutes.POST("/variant/:id/print", authValidator.RequireAuth, printController.PrintVariantHandler) viewRoutes.GET("/tags", authValidator.RequireAuth, shopItemController.TagView) viewRoutes.POST("/tags/:id", authValidator.RequireAuth, shopItemController.TagHandler) viewRoutes.POST("/tags", authValidator.RequireAuth, shopItemController.AddTagHandler) diff --git a/static/output.css b/static/output.css index 87db094..34b6e1c 100644 --- a/static/output.css +++ b/static/output.css @@ -1301,6 +1301,11 @@ video { color: rgb(255 255 255 / var(--tw-text-opacity, 1)); } +.text-red-900 { + --tw-text-opacity: 1; + color: rgb(127 29 29 / var(--tw-text-opacity, 1)); +} + .underline { text-decoration-line: underline; } diff --git a/views/orderpreview.html b/views/orderpreview.html new file mode 100644 index 0000000..4ea2093 --- /dev/null +++ b/views/orderpreview.html @@ -0,0 +1,93 @@ +{{ template "header.html" . }} + +
+
+ +
+

Order summary

+ +
+

Delivery information

+ +
+
+

Shipping: {{ .data.shipping.Name }}

+ {{ if .data.askAddress }} +

First Name: {{ .data.order.FirstName }}

+

Last Name: {{ .data.order.LastName }}

+

Address: {{ .data.order.Address }}

+

Postal Code: {{ .data.order.PostalCode }}

+

City: {{ .data.order.City }}

+

Country: {{ .data.order.Country }}

+ {{ end }} +

Email: {{ .data.order.Email }}

+

Comment: {{ .data.order.Comment }}

+
+
+ + Edit +
+ +
+
+ + + {{ range .data.order.CartItems }} + + + + + + {{ end }} + + +
+ + x{{ .Quantity }}{{ .ItemVariant.Price }}€
+
+ +
+

Order summary

+ +
+
+
+
Original price
+
{{ .data.priceProducts }}€
+
+ +
+
Shipping
+
{{ .data.shipping.Price }}€
+
+ +
+ +
+
Total
+
{{ .data.priceTotal }}€
+
+
+ +
+ + +
+ +
+ + + +
+
+
+
+
+
+ +{{ template "footer.html" . }} diff --git a/views/printvariant.html b/views/printvariant.html new file mode 100644 index 0000000..5dff735 --- /dev/null +++ b/views/printvariant.html @@ -0,0 +1,72 @@ +{{ template "header.html" . }} + +
+
+
+
+

+ Welcome to the Zineshop Printservice.
+ Pressing Print will automatically print the given Zines for you. + All you have to do is set an Amount for each Zine you want to print.

+ CoverPage: If selected, the Printer will take Paper from the BypassTray for the first page. For + example you can put colored paper there to have a nice looking front page, and the rest will be normal paper. + Makue sure you put paper in that tray when selecting this option.

+ + Print Order: The Zines will be printed from top to bottom as seen in this list. + + +

+ +
+ + + {{ range .data.itemVariants }} + + + + + + + + {{ end }} + + +
+ + + + + Amount: + +
+ +
+ +
+
+
+ +
+

If CoverPage + selected, make sure you put paper in the BypassTray

+ + +
+
+
+
+
+ +
+ +{{ template "footer.html" . }}