package controllers import ( "net/http" "strconv" "fotbal-club/internal/models" "github.com/gin-gonic/gin" "gorm.io/gorm" ) // EshopAdminController handles admin management of eshop products and variants. type EshopAdminController struct { DB *gorm.DB } func NewEshopAdminController(db *gorm.DB) *EshopAdminController { return &EshopAdminController{DB: db} } // AdminListProducts returns all products for admin management. func (ctl *EshopAdminController) AdminListProducts(c *gin.Context) { var products []models.EshopProduct q := ctl.DB.Preload("Category").Preload("Variants").Order("created_at DESC, id DESC") if err := q.Find(&products).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load products"}) return } c.JSON(http.StatusOK, gin.H{"data": products}) } // AdminGetProduct returns a single product by ID. func (ctl *EshopAdminController) AdminGetProduct(c *gin.Context) { id := c.Param("id") var product models.EshopProduct if err := ctl.DB.Preload("Category").Preload("Variants").First(&product, id).Error; err != nil { if err == gorm.ErrRecordNotFound { c.JSON(http.StatusNotFound, gin.H{"error": "Product not found"}) return } c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load product"}) return } c.JSON(http.StatusOK, product) } // AdminCreateProduct creates a new product. func (ctl *EshopAdminController) AdminCreateProduct(c *gin.Context) { var input models.EshopProduct if err := c.ShouldBindJSON(&input); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if input.Currency == "" { input.Currency = "CZK" } if err := ctl.DB.Create(&input).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create product"}) return } c.JSON(http.StatusCreated, input) } // AdminUpdateProduct updates an existing product. func (ctl *EshopAdminController) AdminUpdateProduct(c *gin.Context) { id := c.Param("id") var existing models.EshopProduct if err := ctl.DB.First(&existing, id).Error; err != nil { if err == gorm.ErrRecordNotFound { c.JSON(http.StatusNotFound, gin.H{"error": "Product not found"}) return } c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load product"}) return } var input models.EshopProduct if err := c.ShouldBindJSON(&input); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } existing.Name = input.Name existing.Slug = input.Slug existing.ShortDescription = input.ShortDescription existing.DescriptionHTML = input.DescriptionHTML existing.PriceCents = input.PriceCents existing.Currency = input.Currency existing.VATRate = input.VATRate existing.Active = input.Active existing.StockMode = input.StockMode existing.DefaultImageURL = input.DefaultImageURL existing.GalleryJSON = input.GalleryJSON existing.Tags = input.Tags existing.MetadataJSON = input.MetadataJSON existing.CategoryID = input.CategoryID if existing.Currency == "" { existing.Currency = "CZK" } if err := ctl.DB.Save(&existing).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update product"}) return } c.JSON(http.StatusOK, existing) } // AdminDeleteProduct soft-deletes a product. func (ctl *EshopAdminController) AdminDeleteProduct(c *gin.Context) { id := c.Param("id") if err := ctl.DB.Delete(&models.EshopProduct{}, id).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete product"}) return } c.Status(http.StatusNoContent) } // ---- Variants ---- // AdminListVariants lists variants for a product. func (ctl *EshopAdminController) AdminListVariants(c *gin.Context) { productIDStr := c.Param("id") productID, err := strconv.ParseUint(productIDStr, 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid product id"}) return } var variants []models.EshopProductVariant if err := ctl.DB.Where("product_id = ?", uint(productID)).Find(&variants).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load variants"}) return } c.JSON(http.StatusOK, gin.H{"data": variants}) } // AdminCreateVariant creates a variant for a product. func (ctl *EshopAdminController) AdminCreateVariant(c *gin.Context) { productIDStr := c.Param("id") productID, err := strconv.ParseUint(productIDStr, 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid product id"}) return } var input models.EshopProductVariant if err := c.ShouldBindJSON(&input); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } input.ProductID = uint(productID) if err := ctl.DB.Create(&input).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create variant"}) return } c.JSON(http.StatusCreated, input) } // AdminUpdateVariant updates a variant. func (ctl *EshopAdminController) AdminUpdateVariant(c *gin.Context) { variantID := c.Param("id") var existing models.EshopProductVariant if err := ctl.DB.First(&existing, variantID).Error; err != nil { if err == gorm.ErrRecordNotFound { c.JSON(http.StatusNotFound, gin.H{"error": "Variant not found"}) return } c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load variant"}) return } var input models.EshopProductVariant if err := c.ShouldBindJSON(&input); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } existing.SKU = input.SKU existing.Name = input.Name existing.AttributesJSON = input.AttributesJSON existing.StockQty = input.StockQty existing.Barcode = input.Barcode existing.ImageURL = input.ImageURL if err := ctl.DB.Save(&existing).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update variant"}) return } c.JSON(http.StatusOK, existing) } // AdminDeleteVariant deletes a variant. func (ctl *EshopAdminController) AdminDeleteVariant(c *gin.Context) { variantID := c.Param("id") if err := ctl.DB.Delete(&models.EshopProductVariant{}, variantID).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete variant"}) return } c.Status(http.StatusNoContent) }