first commit
This commit is contained in:
237
controllers/api_cart_controller.go
Normal file
237
controllers/api_cart_controller.go
Normal file
@@ -0,0 +1,237 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
database "ares/database/config"
|
||||
"ares/database/models"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// getOrCreateCart is a helper to fetch the cart of the current user.
|
||||
func getOrCreateCart(userID uint) (models.Cart, error) {
|
||||
var cart models.Cart
|
||||
if err := database.DB.Preload("Items").Preload("Items.Product").Where("user_id = ?", userID).First(&cart).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
cart = models.Cart{UserID: userID}
|
||||
if createErr := database.DB.Create(&cart).Error; createErr != nil {
|
||||
return cart, createErr
|
||||
}
|
||||
return cart, nil
|
||||
}
|
||||
return cart, err
|
||||
}
|
||||
return cart, nil
|
||||
}
|
||||
|
||||
// GetMyCart godoc
|
||||
// @Summary Get the current user's cart
|
||||
// @Tags Cart
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Success 200 {object} models.CartDoc
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Router /api/v1/cart [get]
|
||||
func GetMyCart(c fiber.Ctx) error {
|
||||
userID, ok := c.Locals("user_id").(uint)
|
||||
if !ok || userID == 0 {
|
||||
return c.Status(http.StatusUnauthorized).JSON(fiber.Map{"error": "unauthorized"})
|
||||
}
|
||||
|
||||
cart, err := getOrCreateCart(userID)
|
||||
if err != nil {
|
||||
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": "could not load cart"})
|
||||
}
|
||||
|
||||
return c.JSON(cart)
|
||||
}
|
||||
|
||||
// AddToCartRequest represents the body for adding to a cart
|
||||
type AddToCartRequest struct {
|
||||
ProductID uint `json:"product_id" validate:"required"`
|
||||
Quantity int `json:"quantity" validate:"required,min=1"`
|
||||
}
|
||||
|
||||
// AddToCart godoc
|
||||
// @Summary Add item to cart
|
||||
// @Tags Cart
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param data body AddToCartRequest true "Cart Item Details"
|
||||
// @Success 200 {object} models.CartDoc
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /api/v1/cart/items [post]
|
||||
func AddToCart(c fiber.Ctx) error {
|
||||
userID, ok := c.Locals("user_id").(uint)
|
||||
if !ok || userID == 0 {
|
||||
return c.Status(http.StatusUnauthorized).JSON(fiber.Map{"error": "unauthorized"})
|
||||
}
|
||||
|
||||
var input AddToCartRequest
|
||||
if err := c.Bind().Body(&input); err != nil {
|
||||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": "invalid payload"})
|
||||
}
|
||||
|
||||
if err := validate.Struct(input); err != nil {
|
||||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
|
||||
// Check product exists
|
||||
var product models.Product
|
||||
if err := database.DB.First(&product, input.ProductID).Error; err != nil {
|
||||
return c.Status(http.StatusNotFound).JSON(fiber.Map{"error": "product not found"})
|
||||
}
|
||||
|
||||
cart, err := getOrCreateCart(userID)
|
||||
if err != nil {
|
||||
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": "could not load cart"})
|
||||
}
|
||||
|
||||
// Check if item already exists in cart
|
||||
var existingItem models.CartItem
|
||||
if err := database.DB.Where("cart_id = ? AND product_id = ?", cart.ID, input.ProductID).First(&existingItem).Error; err == nil {
|
||||
// Update quantity
|
||||
existingItem.Quantity += input.Quantity
|
||||
database.DB.Save(&existingItem)
|
||||
} else {
|
||||
// Create new item
|
||||
newItem := models.CartItem{
|
||||
CartID: cart.ID,
|
||||
ProductID: input.ProductID,
|
||||
Quantity: input.Quantity,
|
||||
}
|
||||
database.DB.Create(&newItem)
|
||||
}
|
||||
|
||||
// Return updated cart
|
||||
cart, _ = getOrCreateCart(userID)
|
||||
return c.JSON(cart)
|
||||
}
|
||||
|
||||
// UpdateCartItemRequest represents the body for updating a cart item quantity
|
||||
type UpdateCartItemRequest struct {
|
||||
Quantity int `json:"quantity" validate:"required,min=1"`
|
||||
}
|
||||
|
||||
// UpdateCartItem godoc
|
||||
// @Summary Update cart item quantity
|
||||
// @Tags Cart
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param item_id path int true "Cart Item ID"
|
||||
// @Param data body UpdateCartItemRequest true "Update Quantity"
|
||||
// @Success 200 {object} models.CartDoc
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /api/v1/cart/items/{item_id} [put]
|
||||
func UpdateCartItem(c fiber.Ctx) error {
|
||||
userID, ok := c.Locals("user_id").(uint)
|
||||
if !ok || userID == 0 {
|
||||
return c.Status(http.StatusUnauthorized).JSON(fiber.Map{"error": "unauthorized"})
|
||||
}
|
||||
|
||||
itemID, err := strconv.ParseUint(c.Params("item_id"), 10, 32)
|
||||
if err != nil {
|
||||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": "invalid item id"})
|
||||
}
|
||||
|
||||
var input UpdateCartItemRequest
|
||||
if err := c.Bind().Body(&input); err != nil {
|
||||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": "invalid payload"})
|
||||
}
|
||||
|
||||
if err := validate.Struct(input); err != nil {
|
||||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
|
||||
cart, err := getOrCreateCart(userID)
|
||||
if err != nil {
|
||||
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": "could not load cart"})
|
||||
}
|
||||
|
||||
var cartItem models.CartItem
|
||||
if err := database.DB.Where("id = ? AND cart_id = ?", itemID, cart.ID).First(&cartItem).Error; err != nil {
|
||||
return c.Status(http.StatusNotFound).JSON(fiber.Map{"error": "item not found in your cart"})
|
||||
}
|
||||
|
||||
cartItem.Quantity = input.Quantity
|
||||
database.DB.Save(&cartItem)
|
||||
|
||||
// Return updated cart
|
||||
cart, _ = getOrCreateCart(userID)
|
||||
return c.JSON(cart)
|
||||
}
|
||||
|
||||
// RemoveFromCart godoc
|
||||
// @Summary Remove item from cart
|
||||
// @Tags Cart
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param item_id path int true "Cart Item ID"
|
||||
// @Success 200 {object} models.CartDoc
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Router /api/v1/cart/items/{item_id} [delete]
|
||||
func RemoveFromCart(c fiber.Ctx) error {
|
||||
userID, ok := c.Locals("user_id").(uint)
|
||||
if !ok || userID == 0 {
|
||||
return c.Status(http.StatusUnauthorized).JSON(fiber.Map{"error": "unauthorized"})
|
||||
}
|
||||
|
||||
itemID, err := strconv.ParseUint(c.Params("item_id"), 10, 32)
|
||||
if err != nil {
|
||||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": "invalid item id"})
|
||||
}
|
||||
|
||||
cart, err := getOrCreateCart(userID)
|
||||
if err != nil {
|
||||
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": "could not load cart"})
|
||||
}
|
||||
|
||||
var cartItem models.CartItem
|
||||
if err := database.DB.Where("id = ? AND cart_id = ?", itemID, cart.ID).First(&cartItem).Error; err != nil {
|
||||
return c.Status(http.StatusNotFound).JSON(fiber.Map{"error": "item not found in your cart"})
|
||||
}
|
||||
|
||||
database.DB.Delete(&cartItem)
|
||||
|
||||
// Return updated cart
|
||||
cart, _ = getOrCreateCart(userID)
|
||||
return c.JSON(cart)
|
||||
}
|
||||
|
||||
// ClearCart godoc
|
||||
// @Summary Clear the entire cart
|
||||
// @Tags Cart
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Success 200 {object} models.CartDoc
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Router /api/v1/cart [delete]
|
||||
func ClearCart(c fiber.Ctx) error {
|
||||
userID, ok := c.Locals("user_id").(uint)
|
||||
if !ok || userID == 0 {
|
||||
return c.Status(http.StatusUnauthorized).JSON(fiber.Map{"error": "unauthorized"})
|
||||
}
|
||||
|
||||
cart, err := getOrCreateCart(userID)
|
||||
if err != nil {
|
||||
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": "could not load cart"})
|
||||
}
|
||||
|
||||
// Delete all items for this cart
|
||||
database.DB.Where("cart_id = ?", cart.ID).Delete(&models.CartItem{})
|
||||
|
||||
// Return updated empty cart
|
||||
cart, _ = getOrCreateCart(userID)
|
||||
return c.JSON(cart)
|
||||
}
|
||||
Reference in New Issue
Block a user