Files
ares/controllers/api_cart_controller.go
Beyhan Oğur 4d92991817 first commit
2026-04-26 21:30:42 +03:00

238 lines
7.0 KiB
Go

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)
}