first commit

This commit is contained in:
Beyhan Oğur
2026-04-26 21:30:42 +03:00
commit 4d92991817
1982 changed files with 284835 additions and 0 deletions

View File

@@ -0,0 +1,161 @@
package controllers
import (
database "ares/database/config"
"ares/database/models"
"errors"
"net/http"
"strconv"
"github.com/gofiber/fiber/v3"
"gorm.io/gorm"
)
// GetProducts godoc
// @Summary List products (public) with pagination
// @Tags Products
// @Produce json
// @Param page query int false "Page number"
// @Param per_page query int false "Items per page"
// @Success 200 {object} map[string]interface{}
// @Router /api/v1/products [get]
func GetProducts(c fiber.Ctx) error {
pageStr := c.Query("page", "1")
perPageStr := c.Query("per_page", "10")
page, _ := strconv.Atoi(pageStr)
perPage, _ := strconv.Atoi(perPageStr)
if page < 1 {
page = 1
}
if perPage < 1 {
perPage = 10
}
if perPage > 100 {
perPage = 100
}
offset := (page - 1) * perPage
var total int64
database.DB.Model(&models.Product{}).Count(&total)
var products []models.Product
database.DB.Preload("Categories").Preload("Tags").Limit(perPage).Offset(offset).Order("created_at desc").Find(&products)
return c.JSON(fiber.Map{
"data": products,
"meta": fiber.Map{"page": page, "per_page": perPage, "total": total},
})
}
// GetProduct godoc
// @Summary Get single product (public) by slug
// @Tags Products
// @Produce json
// @Param slug path string true "Product slug"
// @Success 200 {object} models.ProductDoc
// @Failure 404 {object} map[string]string
// @Router /api/v1/products/{slug} [get]
func GetProduct(c fiber.Ctx) error {
slug := c.Params("slug")
if slug == "" {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": "invalid slug"})
}
var product models.Product
if err := database.DB.Preload("Categories").Preload("Tags").Where("slug = ? AND deleted_at IS NULL", slug).First(&product).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return c.Status(http.StatusNotFound).JSON(fiber.Map{"error": "product not found"})
}
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": "db error"})
}
return c.JSON(product)
}
// AddProductCommentRequest represents payload
type AddProductCommentRequest struct {
ProductID uint `json:"product_id" validate:"required"`
Body string `json:"body" validate:"required,min=3"`
}
func AddProductComment(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 AddProductCommentRequest
if err := c.Bind().Body(&input); err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": "invalid payload"})
}
// Add validation if needed
if input.Body == "" {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": "body is required"})
}
var product models.Product
if err := database.DB.First(&product, input.ProductID).Error; err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": "product not found"})
}
comment := models.ProductComment{
UserID: userID,
ProductID: input.ProductID,
Body: input.Body,
}
if err := database.DB.Create(&comment).Error; err != nil {
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{"error": "could not save comment"})
}
return c.Status(http.StatusCreated).JSON(comment)
}
// GetProductComments godoc
// @Summary Get comments for a product
// @Tags Products
// @Produce json
// @Param id path int true "Product ID"
// @Success 200 {array} models.ProductCommentDoc
// @Router /api/v1/products/{id}/comments [get]
func GetProductComments(c fiber.Ctx) error {
productID, err := strconv.Atoi(c.Params("id"))
if err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": "invalid product id"})
}
var comments []models.ProductComment
database.DB.Where("product_id = ?", productID).Order("created_at desc").Find(&comments)
return c.JSON(comments)
}
// RecordProductCategoryView godoc
// @Summary Record a view for a product category
// @Tags Products
// @Produce json
// @Param id path int true "Category ID"
// @Success 201 {object} models.ProductCategoryViewDoc
// @Router /api/v1/product-categories/{id}/view [post]
func RecordProductCategoryView(c fiber.Ctx) error {
categoryID, err := strconv.Atoi(c.Params("id"))
if err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": "invalid category id"})
}
var category models.ProductCategory
if err := database.DB.First(&category, categoryID).Error; err != nil {
return c.Status(http.StatusBadRequest).JSON(fiber.Map{"error": "category not found"})
}
view := models.ProductCategoryView{
CategoryID: uint(categoryID),
IPAddress: c.IP(),
}
database.DB.Create(&view)
return c.Status(http.StatusCreated).JSON(view)
}