365 lines
10 KiB
Go
365 lines
10 KiB
Go
package handlers
|
|
|
|
import (
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
|
|
"gauth-central/config"
|
|
"gauth-central/internal/services"
|
|
"gauth-central/pkg/utils"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type BannerHandler struct {
|
|
bannerService *services.BannerService
|
|
}
|
|
|
|
func NewBannerHandler(bannerService *services.BannerService) *BannerHandler {
|
|
return &BannerHandler{bannerService: bannerService}
|
|
}
|
|
|
|
// GetAllBanners godoc
|
|
// @Summary Get all active banners
|
|
// @Description Retrieve a list of active banners
|
|
// @Tags banners
|
|
// @Produce json
|
|
// @Success 200 {array} models.Banner
|
|
// @Failure 500 {object} map[string]string
|
|
// @Router /banners [get]
|
|
func (h *BannerHandler) GetAllBanners(c *gin.Context) {
|
|
items, err := h.bannerService.GetAllBanners(true)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, items)
|
|
}
|
|
|
|
// GetActiveBanner godoc
|
|
// @Summary Get active banner
|
|
// @Description Retrieve the newest active banner
|
|
// @Tags banners
|
|
// @Produce json
|
|
// @Success 200 {object} models.Banner
|
|
// @Failure 404 {object} map[string]string
|
|
// @Router /banners/active [get]
|
|
func (h *BannerHandler) GetActiveBanner(c *gin.Context) {
|
|
item, err := h.bannerService.GetFirstActiveBanner()
|
|
if err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, item)
|
|
}
|
|
|
|
// AdminGetAllBanners godoc
|
|
// @Summary Get all banners (Admin)
|
|
// @Description Retrieve a list of all banners including inactive ones
|
|
// @Tags admin
|
|
// @Security ApiKeyAuth
|
|
// @Produce json
|
|
// @Success 200 {array} models.Banner
|
|
// @Failure 500 {object} map[string]string
|
|
// @Router /admin/banners [get]
|
|
func (h *BannerHandler) AdminGetAllBanners(c *gin.Context) {
|
|
items, err := h.bannerService.GetAllBanners(false)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, items)
|
|
}
|
|
|
|
// AdminGetBannerByID godoc
|
|
// @Summary Get banner by ID (Admin)
|
|
// @Description Retrieve details of a specific banner
|
|
// @Tags admin
|
|
// @Security ApiKeyAuth
|
|
// @Produce json
|
|
// @Param id path string true "Banner ID"
|
|
// @Success 200 {object} models.Banner
|
|
// @Failure 404 {object} map[string]string
|
|
// @Router /admin/banners/{id} [get]
|
|
func (h *BannerHandler) AdminGetBannerByID(c *gin.Context) {
|
|
id := c.Param("id")
|
|
item, err := h.bannerService.GetBannerByID(id)
|
|
if err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, item)
|
|
}
|
|
|
|
// CreateBanner godoc
|
|
// @Summary Create a new banner (Admin)
|
|
// @Description Create a new banner entry
|
|
// @Tags admin
|
|
// @Security ApiKeyAuth
|
|
// @Accept multipart/form-data
|
|
// @Produce json
|
|
// @Param color formData string false "Text color"
|
|
// @Param title formData string false "Title"
|
|
// @Param text1 formData string false "Text 1"
|
|
// @Param text2 formData string false "Text 2"
|
|
// @Param text4 formData string false "Text 4"
|
|
// @Param text5 formData string false "Text 5"
|
|
// @Param image formData file true "Image"
|
|
// @Param image_k formData file false "Small image"
|
|
// @Param image_k_txt formData string false "Small image text"
|
|
// @Param is_active formData bool false "Is active"
|
|
// @Success 201 {object} models.Banner
|
|
// @Failure 400 {object} map[string]string
|
|
// @Router /admin/banners [post]
|
|
func (h *BannerHandler) CreateBanner(c *gin.Context) {
|
|
color := strings.TrimSpace(c.PostForm("color"))
|
|
title := strings.TrimSpace(c.PostForm("title"))
|
|
text1 := strings.TrimSpace(c.PostForm("text1"))
|
|
text2 := strings.TrimSpace(c.PostForm("text2"))
|
|
text4 := strings.TrimSpace(c.PostForm("text4"))
|
|
text5 := strings.TrimSpace(c.PostForm("text5"))
|
|
imageKTxt := strings.TrimSpace(c.PostForm("image_k_txt"))
|
|
|
|
isActive := true
|
|
isActivePtr, err := parseOptionalBool(c, "is_active")
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "is_active must be true or false"})
|
|
return
|
|
}
|
|
if isActivePtr != nil {
|
|
isActive = *isActivePtr
|
|
}
|
|
|
|
imageFile, imageErr := c.FormFile("image")
|
|
if imageErr != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "image is required"})
|
|
return
|
|
}
|
|
if imageFile.Size > 5*1024*1024 {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Image size exceeds 5MB limit"})
|
|
return
|
|
}
|
|
|
|
imageURL, err := utils.SaveOptimizedImage(imageFile, "./uploads/banner", "banner", &utils.ImageOptions{
|
|
Width: config.AppConfig.BannerImageWidth,
|
|
Height: config.AppConfig.BannerImageHeight,
|
|
Quality: float32(config.AppConfig.BannerImageQuality),
|
|
Format: config.AppConfig.BannerImageFormat,
|
|
Mode: config.AppConfig.BannerImageMode,
|
|
})
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save image: " + err.Error()})
|
|
return
|
|
}
|
|
|
|
imageKURL := ""
|
|
imageKFile, imageKErr := c.FormFile("image_k")
|
|
if imageKErr == nil {
|
|
if imageKFile.Size > 5*1024*1024 {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "image_k size exceeds 5MB limit"})
|
|
return
|
|
}
|
|
imageKURL, err = utils.SaveOptimizedImage(imageKFile, "./uploads/banner/kucuk", "banner_k", &utils.ImageOptions{
|
|
Width: config.AppConfig.BannerThumbWidth,
|
|
Height: config.AppConfig.BannerThumbHeight,
|
|
Quality: float32(config.AppConfig.BannerThumbQuality),
|
|
Format: config.AppConfig.BannerThumbFormat,
|
|
Mode: config.AppConfig.BannerThumbMode,
|
|
})
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save image_k: " + err.Error()})
|
|
return
|
|
}
|
|
}
|
|
|
|
item, err := h.bannerService.CreateBanner(
|
|
color,
|
|
title,
|
|
text1,
|
|
text2,
|
|
text4,
|
|
text5,
|
|
imageURL,
|
|
imageKURL,
|
|
imageKTxt,
|
|
isActive,
|
|
)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusCreated, item)
|
|
}
|
|
|
|
// UpdateBanner godoc
|
|
// @Summary Update a banner (Admin)
|
|
// @Description Update an existing banner entry
|
|
// @Tags admin
|
|
// @Security ApiKeyAuth
|
|
// @Accept multipart/form-data
|
|
// @Produce json
|
|
// @Param id path string true "Banner ID"
|
|
// @Param color formData string false "Text color"
|
|
// @Param title formData string false "Title"
|
|
// @Param text1 formData string false "Text 1"
|
|
// @Param text2 formData string false "Text 2"
|
|
// @Param text4 formData string false "Text 4"
|
|
// @Param text5 formData string false "Text 5"
|
|
// @Param image formData file false "Image"
|
|
// @Param image_k formData file false "Small image"
|
|
// @Param image_k_txt formData string false "Small image text"
|
|
// @Param is_active formData bool false "Is active"
|
|
// @Success 200 {object} models.Banner
|
|
// @Failure 400 {object} map[string]string
|
|
// @Failure 404 {object} map[string]string
|
|
// @Router /admin/banners/{id} [put]
|
|
func (h *BannerHandler) UpdateBanner(c *gin.Context) {
|
|
id := c.Param("id")
|
|
|
|
color, hasColor := getOptionalFormValue(c, "color")
|
|
title, hasTitle := getOptionalFormValue(c, "title")
|
|
text1, hasText1 := getOptionalFormValue(c, "text1")
|
|
text2, hasText2 := getOptionalFormValue(c, "text2")
|
|
text4, hasText4 := getOptionalFormValue(c, "text4")
|
|
text5, hasText5 := getOptionalFormValue(c, "text5")
|
|
imageKTxt, hasImageKTxt := getOptionalFormValue(c, "image_k_txt")
|
|
|
|
var colorPtr *string
|
|
var titlePtr *string
|
|
var text1Ptr *string
|
|
var text2Ptr *string
|
|
var text4Ptr *string
|
|
var text5Ptr *string
|
|
var imageKTxtPtr *string
|
|
|
|
if hasColor {
|
|
colorPtr = &color
|
|
}
|
|
if hasTitle {
|
|
titlePtr = &title
|
|
}
|
|
if hasText1 {
|
|
text1Ptr = &text1
|
|
}
|
|
if hasText2 {
|
|
text2Ptr = &text2
|
|
}
|
|
if hasText4 {
|
|
text4Ptr = &text4
|
|
}
|
|
if hasText5 {
|
|
text5Ptr = &text5
|
|
}
|
|
if hasImageKTxt {
|
|
imageKTxtPtr = &imageKTxt
|
|
}
|
|
|
|
isActivePtr, err := parseOptionalBool(c, "is_active")
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "is_active must be true or false"})
|
|
return
|
|
}
|
|
|
|
var imagePtr *string
|
|
imageFile, imageErr := c.FormFile("image")
|
|
if imageErr == nil {
|
|
if imageFile.Size > 5*1024*1024 {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Image size exceeds 5MB limit"})
|
|
return
|
|
}
|
|
item, fetchErr := h.bannerService.GetBannerByID(id)
|
|
if fetchErr != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": fetchErr.Error()})
|
|
return
|
|
}
|
|
if item.Image != "" && strings.HasPrefix(item.Image, "/uploads/") {
|
|
_ = os.Remove("." + item.Image)
|
|
}
|
|
imageURL, saveErr := utils.SaveOptimizedImage(imageFile, "./uploads/banner", id, &utils.ImageOptions{
|
|
Width: config.AppConfig.BannerImageWidth,
|
|
Height: config.AppConfig.BannerImageHeight,
|
|
Quality: float32(config.AppConfig.BannerImageQuality),
|
|
Format: config.AppConfig.BannerImageFormat,
|
|
Mode: config.AppConfig.BannerImageMode,
|
|
})
|
|
if saveErr != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save image: " + saveErr.Error()})
|
|
return
|
|
}
|
|
imagePtr = &imageURL
|
|
}
|
|
|
|
var imageKPtr *string
|
|
imageKFile, imageKErr := c.FormFile("image_k")
|
|
if imageKErr == nil {
|
|
if imageKFile.Size > 5*1024*1024 {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "image_k size exceeds 5MB limit"})
|
|
return
|
|
}
|
|
item, fetchErr := h.bannerService.GetBannerByID(id)
|
|
if fetchErr != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": fetchErr.Error()})
|
|
return
|
|
}
|
|
if item.ImageK != "" && strings.HasPrefix(item.ImageK, "/uploads/") {
|
|
_ = os.Remove("." + item.ImageK)
|
|
}
|
|
imageKURL, saveErr := utils.SaveOptimizedImage(imageKFile, "./uploads/banner/kucuk", id+"_k", &utils.ImageOptions{
|
|
Width: config.AppConfig.BannerThumbWidth,
|
|
Height: config.AppConfig.BannerThumbHeight,
|
|
Quality: float32(config.AppConfig.BannerThumbQuality),
|
|
Format: config.AppConfig.BannerThumbFormat,
|
|
Mode: config.AppConfig.BannerThumbMode,
|
|
})
|
|
if saveErr != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save image_k: " + saveErr.Error()})
|
|
return
|
|
}
|
|
imageKPtr = &imageKURL
|
|
}
|
|
|
|
item, err := h.bannerService.UpdateBanner(
|
|
id,
|
|
colorPtr,
|
|
titlePtr,
|
|
text1Ptr,
|
|
text2Ptr,
|
|
text4Ptr,
|
|
text5Ptr,
|
|
imagePtr,
|
|
imageKPtr,
|
|
imageKTxtPtr,
|
|
isActivePtr,
|
|
)
|
|
if err != nil {
|
|
status := http.StatusInternalServerError
|
|
if err.Error() == "banner not found" {
|
|
status = http.StatusNotFound
|
|
}
|
|
c.JSON(status, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, item)
|
|
}
|
|
|
|
// DeleteBanner godoc
|
|
// @Summary Delete a banner (Admin)
|
|
// @Description Delete a banner by ID
|
|
// @Tags admin
|
|
// @Security ApiKeyAuth
|
|
// @Param id path string true "Banner ID"
|
|
// @Success 200 {object} map[string]string
|
|
// @Failure 404 {object} map[string]string
|
|
// @Router /admin/banners/{id} [delete]
|
|
func (h *BannerHandler) DeleteBanner(c *gin.Context) {
|
|
id := c.Param("id")
|
|
if err := h.bannerService.DeleteBanner(id); err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"message": "Banner deleted successfully"})
|
|
}
|