feat: add feature banner domain
This commit is contained in:
parent
e748c6f492
commit
8616d725a4
|
@ -28,4 +28,5 @@ go.work.sum
|
||||||
|
|
||||||
# Ignore avatar images
|
# Ignore avatar images
|
||||||
/public/uploads/avatars/
|
/public/uploads/avatars/
|
||||||
/public/uploads/articles/
|
/public/uploads/articles/
|
||||||
|
/public/uploads/banners/
|
|
@ -44,6 +44,7 @@ func ConnectDatabase() {
|
||||||
&model.UserPin{},
|
&model.UserPin{},
|
||||||
&model.Address{},
|
&model.Address{},
|
||||||
&model.Article{},
|
&model.Article{},
|
||||||
|
&model.Banner{},
|
||||||
// ==main feature==
|
// ==main feature==
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package dto
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
type ResponseBannerDTO struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
BannerName string `json:"bannername"`
|
||||||
|
BannerImage string `json:"bannerimage"`
|
||||||
|
CreatedAt string `json:"createdAt"`
|
||||||
|
UpdatedAt string `json:"updatedAt"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RequestBannerDTO struct {
|
||||||
|
BannerName string `json:"bannername"`
|
||||||
|
BannerImage string `json:"bannerimage"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RequestBannerDTO) ValidateBannerInput() (map[string][]string, bool) {
|
||||||
|
errors := make(map[string][]string)
|
||||||
|
|
||||||
|
if strings.TrimSpace(r.BannerName) == "" {
|
||||||
|
errors["bannername"] = append(errors["bannername"], "nama banner harus diisi")
|
||||||
|
}
|
||||||
|
if len(errors) > 0 {
|
||||||
|
return errors, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, true
|
||||||
|
}
|
|
@ -41,7 +41,7 @@ func (h *ArticleHandler) CreateArticle(c *fiber.Ctx) error {
|
||||||
return utils.GenericResponse(c, fiber.StatusInternalServerError, err.Error())
|
return utils.GenericResponse(c, fiber.StatusInternalServerError, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return utils.SuccessResponse(c, articleResponse, "Article created successfully")
|
return utils.CreateResponse(c, articleResponse, "Article created successfully")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ArticleHandler) GetAllArticles(c *fiber.Ctx) error {
|
func (h *ArticleHandler) GetAllArticles(c *fiber.Ctx) error {
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"github.com/pahmiudahgede/senggoldong/dto"
|
||||||
|
"github.com/pahmiudahgede/senggoldong/internal/services"
|
||||||
|
"github.com/pahmiudahgede/senggoldong/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BannerHandler struct {
|
||||||
|
BannerService services.BannerService
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBannerHandler(bannerService services.BannerService) *BannerHandler {
|
||||||
|
return &BannerHandler{BannerService: bannerService}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *BannerHandler) CreateBanner(c *fiber.Ctx) error {
|
||||||
|
var request dto.RequestBannerDTO
|
||||||
|
|
||||||
|
if err := c.BodyParser(&request); err != nil {
|
||||||
|
return utils.ValidationErrorResponse(c, map[string][]string{"body": {"Invalid body"}})
|
||||||
|
}
|
||||||
|
|
||||||
|
errors, valid := request.ValidateBannerInput()
|
||||||
|
if !valid {
|
||||||
|
return utils.ValidationErrorResponse(c, errors)
|
||||||
|
}
|
||||||
|
|
||||||
|
bannerImage, err := c.FormFile("bannerimage")
|
||||||
|
if err != nil {
|
||||||
|
return utils.GenericResponse(c, fiber.StatusBadRequest, "Banner image is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
bannerResponse, err := h.BannerService.CreateBanner(request, bannerImage)
|
||||||
|
if err != nil {
|
||||||
|
return utils.GenericResponse(c, fiber.StatusInternalServerError, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return utils.CreateResponse(c, bannerResponse, "Banner created successfully")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *BannerHandler) GetAllBanners(c *fiber.Ctx) error {
|
||||||
|
banners, err := h.BannerService.GetAllBanners()
|
||||||
|
if err != nil {
|
||||||
|
return utils.GenericResponse(c, fiber.StatusInternalServerError, "Failed to fetch banners")
|
||||||
|
}
|
||||||
|
|
||||||
|
return utils.NonPaginatedResponse(c, banners, len(banners), "Banners fetched successfully")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *BannerHandler) GetBannerByID(c *fiber.Ctx) error {
|
||||||
|
id := c.Params("banner_id")
|
||||||
|
if id == "" {
|
||||||
|
return utils.GenericResponse(c, fiber.StatusBadRequest, "Banner ID is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
banner, err := h.BannerService.GetBannerByID(id)
|
||||||
|
if err != nil {
|
||||||
|
return utils.GenericResponse(c, fiber.StatusInternalServerError, "Failed to fetch banner")
|
||||||
|
}
|
||||||
|
|
||||||
|
return utils.SuccessResponse(c, banner, "Banner fetched successfully")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *BannerHandler) UpdateBanner(c *fiber.Ctx) error {
|
||||||
|
id := c.Params("banner_id")
|
||||||
|
if id == "" {
|
||||||
|
return utils.GenericResponse(c, fiber.StatusBadRequest, "Banner ID is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
var request dto.RequestBannerDTO
|
||||||
|
|
||||||
|
if err := c.BodyParser(&request); err != nil {
|
||||||
|
return utils.ValidationErrorResponse(c, map[string][]string{"body": {"Invalid body"}})
|
||||||
|
}
|
||||||
|
|
||||||
|
errors, valid := request.ValidateBannerInput()
|
||||||
|
if !valid {
|
||||||
|
return utils.ValidationErrorResponse(c, errors)
|
||||||
|
}
|
||||||
|
|
||||||
|
bannerImage, err := c.FormFile("bannerimage")
|
||||||
|
if err != nil && err.Error() != "no such file" {
|
||||||
|
return utils.GenericResponse(c, fiber.StatusBadRequest, "Banner image is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
bannerResponse, err := h.BannerService.UpdateBanner(id, request, bannerImage)
|
||||||
|
if err != nil {
|
||||||
|
return utils.GenericResponse(c, fiber.StatusInternalServerError, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return utils.SuccessResponse(c, bannerResponse, "Banner updated successfully")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *BannerHandler) DeleteBanner(c *fiber.Ctx) error {
|
||||||
|
id := c.Params("banner_id")
|
||||||
|
if id == "" {
|
||||||
|
return utils.GenericResponse(c, fiber.StatusBadRequest, "Banner ID is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
err := h.BannerService.DeleteBanner(id)
|
||||||
|
if err != nil {
|
||||||
|
return utils.GenericResponse(c, fiber.StatusInternalServerError, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return utils.GenericResponse(c, fiber.StatusOK, "Banner deleted successfully")
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
package repositories
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/pahmiudahgede/senggoldong/model"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BannerRepository interface {
|
||||||
|
CreateBanner(banner *model.Banner) error
|
||||||
|
FindBannerByID(id string) (*model.Banner, error)
|
||||||
|
FindAllBanners() ([]model.Banner, error)
|
||||||
|
UpdateBanner(id string, banner *model.Banner) error
|
||||||
|
DeleteBanner(id string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type bannerRepository struct {
|
||||||
|
DB *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBannerRepository(db *gorm.DB) BannerRepository {
|
||||||
|
return &bannerRepository{DB: db}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *bannerRepository) CreateBanner(banner *model.Banner) error {
|
||||||
|
if err := r.DB.Create(banner).Error; err != nil {
|
||||||
|
return fmt.Errorf("failed to create banner: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *bannerRepository) FindBannerByID(id string) (*model.Banner, error) {
|
||||||
|
var banner model.Banner
|
||||||
|
err := r.DB.Where("id = ?", id).First(&banner).Error
|
||||||
|
if err != nil {
|
||||||
|
if err == gorm.ErrRecordNotFound {
|
||||||
|
return nil, fmt.Errorf("banner with ID %s not found", id)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("failed to fetch banner by ID: %v", err)
|
||||||
|
}
|
||||||
|
return &banner, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *bannerRepository) FindAllBanners() ([]model.Banner, error) {
|
||||||
|
var banners []model.Banner
|
||||||
|
err := r.DB.Find(&banners).Error
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to fetch banners: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return banners, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *bannerRepository) UpdateBanner(id string, banner *model.Banner) error {
|
||||||
|
err := r.DB.Model(&model.Banner{}).Where("id = ?", id).Updates(banner).Error
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to update banner: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *bannerRepository) DeleteBanner(id string) error {
|
||||||
|
result := r.DB.Delete(&model.Banner{}, "id = ?", id)
|
||||||
|
if result.Error != nil {
|
||||||
|
return fmt.Errorf("failed to delete banner: %v", result.Error)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,347 @@
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"mime/multipart"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/pahmiudahgede/senggoldong/dto"
|
||||||
|
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||||
|
"github.com/pahmiudahgede/senggoldong/model"
|
||||||
|
"github.com/pahmiudahgede/senggoldong/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BannerService interface {
|
||||||
|
CreateBanner(request dto.RequestBannerDTO, bannerImage *multipart.FileHeader) (*dto.ResponseBannerDTO, error)
|
||||||
|
GetAllBanners() ([]dto.ResponseBannerDTO, error)
|
||||||
|
GetBannerByID(id string) (*dto.ResponseBannerDTO, error)
|
||||||
|
UpdateBanner(id string, request dto.RequestBannerDTO, bannerImage *multipart.FileHeader) (*dto.ResponseBannerDTO, error)
|
||||||
|
DeleteBanner(id string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type bannerService struct {
|
||||||
|
BannerRepo repositories.BannerRepository
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBannerService(bannerRepo repositories.BannerRepository) BannerService {
|
||||||
|
return &bannerService{BannerRepo: bannerRepo}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *bannerService) saveBannerImage(bannerImage *multipart.FileHeader) (string, error) {
|
||||||
|
bannerImageDir := "./public/uploads/banners"
|
||||||
|
if _, err := os.Stat(bannerImageDir); os.IsNotExist(err) {
|
||||||
|
if err := os.MkdirAll(bannerImageDir, os.ModePerm); err != nil {
|
||||||
|
return "", fmt.Errorf("failed to create directory for banner image: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allowedExtensions := map[string]bool{".jpg": true, ".jpeg": true, ".png": true}
|
||||||
|
extension := filepath.Ext(bannerImage.Filename)
|
||||||
|
if !allowedExtensions[extension] {
|
||||||
|
return "", fmt.Errorf("invalid file type, only .jpg, .jpeg, and .png are allowed")
|
||||||
|
}
|
||||||
|
|
||||||
|
bannerImageFileName := fmt.Sprintf("%s_banner%s", uuid.New().String(), extension)
|
||||||
|
bannerImagePath := filepath.Join(bannerImageDir, bannerImageFileName)
|
||||||
|
|
||||||
|
src, err := bannerImage.Open()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to open uploaded file: %v", err)
|
||||||
|
}
|
||||||
|
defer src.Close()
|
||||||
|
|
||||||
|
dst, err := os.Create(bannerImagePath)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to create banner image file: %v", err)
|
||||||
|
}
|
||||||
|
defer dst.Close()
|
||||||
|
|
||||||
|
if _, err := dst.ReadFrom(src); err != nil {
|
||||||
|
return "", fmt.Errorf("failed to save banner image: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return bannerImagePath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *bannerService) CreateBanner(request dto.RequestBannerDTO, bannerImage *multipart.FileHeader) (*dto.ResponseBannerDTO, error) {
|
||||||
|
|
||||||
|
errors, valid := request.ValidateBannerInput()
|
||||||
|
if !valid {
|
||||||
|
return nil, fmt.Errorf("validation error: %v", errors)
|
||||||
|
}
|
||||||
|
|
||||||
|
bannerImagePath, err := s.saveBannerImage(bannerImage)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to save banner image: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
banner := model.Banner{
|
||||||
|
BannerName: request.BannerName,
|
||||||
|
BannerImage: bannerImagePath,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.BannerRepo.CreateBanner(&banner); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create banner: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
createdAt, _ := utils.FormatDateToIndonesianFormat(banner.CreatedAt)
|
||||||
|
updatedAt, _ := utils.FormatDateToIndonesianFormat(banner.UpdatedAt)
|
||||||
|
|
||||||
|
bannerResponseDTO := &dto.ResponseBannerDTO{
|
||||||
|
ID: banner.ID,
|
||||||
|
BannerName: banner.BannerName,
|
||||||
|
BannerImage: banner.BannerImage,
|
||||||
|
CreatedAt: createdAt,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
|
}
|
||||||
|
|
||||||
|
articlesCacheKey := "banners:all"
|
||||||
|
err = utils.DeleteData(articlesCacheKey)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error deleting cache for all banners: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheKey := fmt.Sprintf("banner:%s", banner.ID)
|
||||||
|
cacheData := map[string]interface{}{
|
||||||
|
"data": bannerResponseDTO,
|
||||||
|
}
|
||||||
|
if err := utils.SetJSONData(cacheKey, cacheData, time.Hour*24); err != nil {
|
||||||
|
fmt.Printf("Error caching banner: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
banners, err := s.BannerRepo.FindAllBanners()
|
||||||
|
if err == nil {
|
||||||
|
var bannersDTO []dto.ResponseBannerDTO
|
||||||
|
for _, b := range banners {
|
||||||
|
createdAt, _ := utils.FormatDateToIndonesianFormat(b.CreatedAt)
|
||||||
|
updatedAt, _ := utils.FormatDateToIndonesianFormat(b.UpdatedAt)
|
||||||
|
|
||||||
|
bannersDTO = append(bannersDTO, dto.ResponseBannerDTO{
|
||||||
|
ID: b.ID,
|
||||||
|
BannerName: b.BannerName,
|
||||||
|
BannerImage: b.BannerImage,
|
||||||
|
CreatedAt: createdAt,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheData = map[string]interface{}{
|
||||||
|
"data": bannersDTO,
|
||||||
|
}
|
||||||
|
if err := utils.SetJSONData(articlesCacheKey, cacheData, time.Hour*24); err != nil {
|
||||||
|
fmt.Printf("Error caching updated banners to Redis: %v\n", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Error fetching all banners: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return bannerResponseDTO, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *bannerService) GetAllBanners() ([]dto.ResponseBannerDTO, error) {
|
||||||
|
var banners []dto.ResponseBannerDTO
|
||||||
|
|
||||||
|
cacheKey := "banners:all"
|
||||||
|
cachedData, err := utils.GetJSONData(cacheKey)
|
||||||
|
if err == nil && cachedData != nil {
|
||||||
|
|
||||||
|
if data, ok := cachedData["data"].([]interface{}); ok {
|
||||||
|
for _, item := range data {
|
||||||
|
if bannerData, ok := item.(map[string]interface{}); ok {
|
||||||
|
banners = append(banners, dto.ResponseBannerDTO{
|
||||||
|
ID: bannerData["id"].(string),
|
||||||
|
BannerName: bannerData["bannername"].(string),
|
||||||
|
BannerImage: bannerData["bannerimage"].(string),
|
||||||
|
CreatedAt: bannerData["createdAt"].(string),
|
||||||
|
UpdatedAt: bannerData["updatedAt"].(string),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return banners, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
records, err := s.BannerRepo.FindAllBanners()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to fetch banners: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, record := range records {
|
||||||
|
createdAt, _ := utils.FormatDateToIndonesianFormat(record.CreatedAt)
|
||||||
|
updatedAt, _ := utils.FormatDateToIndonesianFormat(record.UpdatedAt)
|
||||||
|
|
||||||
|
banners = append(banners, dto.ResponseBannerDTO{
|
||||||
|
ID: record.ID,
|
||||||
|
BannerName: record.BannerName,
|
||||||
|
BannerImage: record.BannerImage,
|
||||||
|
CreatedAt: createdAt,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheData := map[string]interface{}{
|
||||||
|
"data": banners,
|
||||||
|
}
|
||||||
|
if err := utils.SetJSONData(cacheKey, cacheData, time.Hour*24); err != nil {
|
||||||
|
fmt.Printf("Error caching banners: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return banners, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *bannerService) GetBannerByID(id string) (*dto.ResponseBannerDTO, error) {
|
||||||
|
|
||||||
|
cacheKey := fmt.Sprintf("banner:%s", id)
|
||||||
|
cachedData, err := utils.GetJSONData(cacheKey)
|
||||||
|
if err == nil && cachedData != nil {
|
||||||
|
if data, ok := cachedData["data"].(map[string]interface{}); ok {
|
||||||
|
return &dto.ResponseBannerDTO{
|
||||||
|
ID: data["id"].(string),
|
||||||
|
BannerName: data["bannername"].(string),
|
||||||
|
BannerImage: data["bannerimage"].(string),
|
||||||
|
CreatedAt: data["createdAt"].(string),
|
||||||
|
UpdatedAt: data["updatedAt"].(string),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
banner, err := s.BannerRepo.FindBannerByID(id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to fetch banner by ID: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
createdAt, _ := utils.FormatDateToIndonesianFormat(banner.CreatedAt)
|
||||||
|
updatedAt, _ := utils.FormatDateToIndonesianFormat(banner.UpdatedAt)
|
||||||
|
|
||||||
|
bannerResponseDTO := &dto.ResponseBannerDTO{
|
||||||
|
ID: banner.ID,
|
||||||
|
BannerName: banner.BannerName,
|
||||||
|
BannerImage: banner.BannerImage,
|
||||||
|
CreatedAt: createdAt,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheData := map[string]interface{}{
|
||||||
|
"data": bannerResponseDTO,
|
||||||
|
}
|
||||||
|
if err := utils.SetJSONData(cacheKey, cacheData, time.Hour*24); err != nil {
|
||||||
|
fmt.Printf("Error caching banner: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return bannerResponseDTO, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *bannerService) UpdateBanner(id string, request dto.RequestBannerDTO, bannerImage *multipart.FileHeader) (*dto.ResponseBannerDTO, error) {
|
||||||
|
// Cari banner yang ingin diupdate
|
||||||
|
banner, err := s.BannerRepo.FindBannerByID(id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("banner not found: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update data banner
|
||||||
|
banner.BannerName = request.BannerName
|
||||||
|
if bannerImage != nil {
|
||||||
|
// Hapus file lama jika ada gambar baru yang diupload
|
||||||
|
bannerImagePath, err := s.saveBannerImage(bannerImage)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to save banner image: %v", err)
|
||||||
|
}
|
||||||
|
banner.BannerImage = bannerImagePath
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simpan perubahan ke database
|
||||||
|
if err := s.BannerRepo.UpdateBanner(id, banner); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to update banner: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format tanggal
|
||||||
|
createdAt, _ := utils.FormatDateToIndonesianFormat(banner.CreatedAt)
|
||||||
|
updatedAt, _ := utils.FormatDateToIndonesianFormat(banner.UpdatedAt)
|
||||||
|
|
||||||
|
// Membuat Response DTO
|
||||||
|
bannerResponseDTO := &dto.ResponseBannerDTO{
|
||||||
|
ID: banner.ID,
|
||||||
|
BannerName: banner.BannerName,
|
||||||
|
BannerImage: banner.BannerImage,
|
||||||
|
CreatedAt: createdAt,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Menghapus cache untuk banner yang lama
|
||||||
|
cacheKey := fmt.Sprintf("banner:%s", id)
|
||||||
|
err = utils.DeleteData(cacheKey)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error deleting cache for banner: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache banner yang terbaru
|
||||||
|
cacheData := map[string]interface{}{
|
||||||
|
"data": bannerResponseDTO,
|
||||||
|
}
|
||||||
|
if err := utils.SetJSONData(cacheKey, cacheData, time.Hour*24); err != nil {
|
||||||
|
fmt.Printf("Error caching updated banner: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Menghapus dan memperbarui cache untuk seluruh banner
|
||||||
|
articlesCacheKey := "banners:all"
|
||||||
|
err = utils.DeleteData(articlesCacheKey)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error deleting cache for all banners: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache seluruh daftar banner yang terbaru
|
||||||
|
banners, err := s.BannerRepo.FindAllBanners()
|
||||||
|
if err == nil {
|
||||||
|
var bannersDTO []dto.ResponseBannerDTO
|
||||||
|
for _, b := range banners {
|
||||||
|
createdAt, _ := utils.FormatDateToIndonesianFormat(b.CreatedAt)
|
||||||
|
updatedAt, _ := utils.FormatDateToIndonesianFormat(b.UpdatedAt)
|
||||||
|
|
||||||
|
bannersDTO = append(bannersDTO, dto.ResponseBannerDTO{
|
||||||
|
ID: b.ID,
|
||||||
|
BannerName: b.BannerName,
|
||||||
|
BannerImage: b.BannerImage,
|
||||||
|
CreatedAt: createdAt,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheData = map[string]interface{}{
|
||||||
|
"data": bannersDTO,
|
||||||
|
}
|
||||||
|
if err := utils.SetJSONData(articlesCacheKey, cacheData, time.Hour*24); err != nil {
|
||||||
|
fmt.Printf("Error caching updated banners to Redis: %v\n", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Error fetching all banners: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return bannerResponseDTO, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteBanner - Menghapus banner dan memperbarui cache
|
||||||
|
func (s *bannerService) DeleteBanner(id string) error {
|
||||||
|
// Hapus banner dari database
|
||||||
|
if err := s.BannerRepo.DeleteBanner(id); err != nil {
|
||||||
|
return fmt.Errorf("failed to delete banner: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Menghapus cache untuk banner yang dihapus
|
||||||
|
cacheKey := fmt.Sprintf("banner:%s", id)
|
||||||
|
err := utils.DeleteData(cacheKey)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error deleting cache for banner: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Menghapus cache untuk seluruh banner
|
||||||
|
articlesCacheKey := "banners:all"
|
||||||
|
err = utils.DeleteData(articlesCacheKey)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error deleting cache for all banners: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package model
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type Banner struct {
|
||||||
|
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
|
||||||
|
BannerName string `gorm:"not null" json:"bannername"`
|
||||||
|
BannerImage string `gorm:"not null" json:"bannerimage"`
|
||||||
|
CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"`
|
||||||
|
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"`
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package presentation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"github.com/pahmiudahgede/senggoldong/config"
|
||||||
|
"github.com/pahmiudahgede/senggoldong/internal/handler"
|
||||||
|
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||||
|
"github.com/pahmiudahgede/senggoldong/internal/services"
|
||||||
|
"github.com/pahmiudahgede/senggoldong/middleware"
|
||||||
|
"github.com/pahmiudahgede/senggoldong/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BannerRouter(api fiber.Router) {
|
||||||
|
bannerRepo := repositories.NewBannerRepository(config.DB)
|
||||||
|
bannerService := services.NewBannerService(bannerRepo)
|
||||||
|
BannerHandler := handler.NewBannerHandler(bannerService)
|
||||||
|
|
||||||
|
bannerAPI := api.Group("/banner-rijik")
|
||||||
|
|
||||||
|
bannerAPI.Post("/create-banner", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator), BannerHandler.CreateBanner)
|
||||||
|
bannerAPI.Get("/getall-banner", BannerHandler.GetAllBanners)
|
||||||
|
bannerAPI.Get("/get-banner/:banner_id", BannerHandler.GetBannerByID)
|
||||||
|
bannerAPI.Put("/update-banner/:banner_id", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator), BannerHandler.UpdateBanner)
|
||||||
|
bannerAPI.Delete("/delete-banner/:banner_id", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator), BannerHandler.DeleteBanner)
|
||||||
|
}
|
|
@ -17,4 +17,5 @@ func SetupRoutes(app *fiber.App) {
|
||||||
presentation.WilayahRouter(api)
|
presentation.WilayahRouter(api)
|
||||||
presentation.AddressRouter(api)
|
presentation.AddressRouter(api)
|
||||||
presentation.ArticleRouter(api)
|
presentation.ArticleRouter(api)
|
||||||
|
presentation.BannerRouter(api)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue