Files
atahango/api/handlers/banner_handler.go
Beyhan Oğur bbbf76b184 first commit
2026-04-26 21:35:24 +03:00

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