diff --git a/.gitignore b/.gitignore index 00c246b..f0aa2fd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ .env -/client/node_modules -/src/public/js \ No newline at end of file +/client/node_modules \ No newline at end of file diff --git a/src/controllers/cart/add-to-cart.go b/src/controllers/cart/add-to-cart.go index 0310e5b..014f4de 100644 --- a/src/controllers/cart/add-to-cart.go +++ b/src/controllers/cart/add-to-cart.go @@ -1,6 +1,7 @@ package cart import ( + "fmt" "strconv" "github.com/gofiber/fiber/v2" @@ -12,20 +13,37 @@ func AddToCart(c *fiber.Ctx) error { var newItem models.CartItem if err := c.BodyParser(&newItem); err != nil { - return c.Redirect("/error") + fmt.Println(err) + return c.JSON(fiber.Map{ + "message": "Invalid request body", + "success": false, + "data": nil, + }) } productId, err := strconv.ParseInt(c.Params("ID"), 10, 64) if err != nil { - return c.Redirect("/error") + return c.JSON(fiber.Map{ + "message": "Invalid query parameter", + "success": false, + "data": nil, + }) } newItem.ID = int(productId) if err := cart.AddToCartAndUpdateSession(c, newItem); err != nil { - return c.Redirect("/error") + return c.JSON(fiber.Map{ + "message": "Item has not been added to cart", + "success": false, + "data": nil, + }) } - return c.Redirect(string(c.Context().Referer())) + return c.JSON(fiber.Map{ + "message": "Item has been added to cart", + "success": true, + "data": nil, + }) } diff --git a/src/models/cart.go b/src/models/cart.go index dc3baf9..471b0e9 100644 --- a/src/models/cart.go +++ b/src/models/cart.go @@ -2,5 +2,5 @@ package models type CartItem struct { ID int - Quantity int + Quantity int `json:"quantity"` } diff --git a/src/public/js/add-to-cart.js b/src/public/js/add-to-cart.js new file mode 100644 index 0000000..34b4e2f --- /dev/null +++ b/src/public/js/add-to-cart.js @@ -0,0 +1,92 @@ +/* + primary, + success, + warning, + danger +*/ + +/* + element: string; + className: string, + attributes: { + key: string; + value: string; + }[]; +*/ +const createElement = (options) => { + if (!options.element) return null; + + const element = document.createElement(options.element); + + if (options.className) { + element.className = options.className; + } + + if (options.attributes && options.attributes.length > 0) { + options.attributes.forEach((attribute) => { + element.setAttribute(attribute.key, attribute.value); + }); + } + + if (options.text) { + element.textContent = options.text; + } + + return element; +}; + +const appendAlert = (text, severity) => { + if (!text) return; + + const alertContainer = document.getElementById('alert-container'); + + Array.from(alertContainer.children).forEach((child) => { + alertContainer.removeChild(child); + }); + + const alertElement = createElement({ + element: 'div', + className: 'uk-alert-' + severity, + attributes: [{ key: 'uk-alert', value: '' }], + }); + + alertElement.appendChild( + createElement({ + element: 'a', + className: 'uk-alert-close', + attributes: [{ key: 'uk-close', value: '' }], + }) + ); + + alertElement.appendChild(createElement({ text, element: 'p' })); + + alertContainer.appendChild(alertElement); +}; + +const addToCart = async (productId) => { + const addToCartButton = document.getElementById('add-to-cart'); + + addToCartButton.setAttribute('disabled', true); + + try { + const quantityInput = document.querySelector('[name=quantity]'); + + const quantity = parseInt(quantityInput.value); + + const res = await fetch('/add-to-cart/' + productId, { + method: 'POST', + body: JSON.stringify({ quantity }), + headers: { + 'Content-Type': 'application/json', + }, + }); + + const data = await res.json(); + + appendAlert(data.message, data.success ? 'success' : 'danger'); + } catch (err) { + return; + } + + addToCartButton.removeAttribute('disabled'); +}; diff --git a/src/views/pages/view-product.html b/src/views/pages/view-product.html index 97d25ce..67664b3 100644 --- a/src/views/pages/view-product.html +++ b/src/views/pages/view-product.html @@ -27,11 +27,18 @@

{{ .Product.Amount }} SEK

+ +
+ +