feat: add feature how to and how about
This commit is contained in:
parent
9f1a4eb8fa
commit
30d082f4e9
|
@ -60,6 +60,8 @@ func ConnectDatabase() {
|
|||
&model.Article{},
|
||||
&model.Banner{},
|
||||
&model.InitialCoint{},
|
||||
&model.About{},
|
||||
&model.AboutDetail{},
|
||||
|
||||
// =>Trash Model<=
|
||||
&model.TrashCategory{},
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
package dto
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
type RequestAboutDTO struct {
|
||||
Title string `json:"title"`
|
||||
CoverImage string `json:"cover_image"`
|
||||
// AboutDetail []RequestAboutDetailDTO `json:"about_detail"`
|
||||
}
|
||||
|
||||
func (r *RequestAboutDTO) ValidateAbout() (map[string][]string, bool) {
|
||||
errors := make(map[string][]string)
|
||||
|
||||
if strings.TrimSpace(r.Title) == "" {
|
||||
errors["title"] = append(errors["title"], "Title is required")
|
||||
}
|
||||
|
||||
if len(errors) > 0 {
|
||||
return errors, false
|
||||
}
|
||||
|
||||
return nil, true
|
||||
}
|
||||
|
||||
type ResponseAboutDTO struct {
|
||||
ID string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
CoverImage string `json:"cover_image"`
|
||||
AboutDetail *[]ResponseAboutDetailDTO `json:"about_detail"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
}
|
||||
|
||||
type RequestAboutDetailDTO struct {
|
||||
AboutId string `json:"about_id"`
|
||||
ImageDetail string `json:"image_detail"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
func (r *RequestAboutDetailDTO) ValidateAboutDetail() (map[string][]string, bool) {
|
||||
errors := make(map[string][]string)
|
||||
|
||||
if strings.TrimSpace(r.AboutId) == "" {
|
||||
errors["about_id"] = append(errors["about_id"], "About ID is required")
|
||||
}
|
||||
|
||||
if strings.TrimSpace(r.ImageDetail) == "" {
|
||||
errors["image_detail"] = append(errors["image_detail"], "Image detail is required")
|
||||
}
|
||||
|
||||
if strings.TrimSpace(r.Description) == "" {
|
||||
errors["description"] = append(errors["description"], "Description is required")
|
||||
}
|
||||
|
||||
if len(errors) > 0 {
|
||||
return errors, false
|
||||
}
|
||||
|
||||
return nil, true
|
||||
}
|
||||
|
||||
type ResponseAboutDetailDTO struct {
|
||||
ID string `json:"id"`
|
||||
AboutID string `json:"about_id"`
|
||||
ImageDetail string `json:"image_detail"`
|
||||
Description string `json:"description"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"rijig/dto"
|
||||
"rijig/internal/services"
|
||||
"rijig/utils"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
type AboutHandler struct {
|
||||
AboutService services.AboutService
|
||||
}
|
||||
|
||||
func NewAboutHandler(aboutService services.AboutService) *AboutHandler {
|
||||
return &AboutHandler{
|
||||
AboutService: aboutService,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *AboutHandler) CreateAbout(c *fiber.Ctx) error {
|
||||
var request dto.RequestAboutDTO
|
||||
if err := c.BodyParser(&request); err != nil {
|
||||
log.Printf("Error parsing request body: %v", err)
|
||||
return utils.ErrorResponse(c, "Invalid input data")
|
||||
}
|
||||
|
||||
aboutCoverImage, err := c.FormFile("cover_image")
|
||||
if err != nil {
|
||||
log.Printf("Error retrieving cover image about from request: %v", err)
|
||||
return utils.ErrorResponse(c, "cover_iamge is required")
|
||||
}
|
||||
|
||||
response, err := h.AboutService.CreateAbout(request, aboutCoverImage)
|
||||
if err != nil {
|
||||
log.Printf("Error creating About: %v", err)
|
||||
return utils.ErrorResponse(c, fmt.Sprintf("Failed to create About: %v", err))
|
||||
}
|
||||
|
||||
return utils.SuccessResponse(c, response, "Successfully created About")
|
||||
}
|
||||
|
||||
func (h *AboutHandler) UpdateAbout(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
var request dto.RequestAboutDTO
|
||||
if err := c.BodyParser(&request); err != nil {
|
||||
log.Printf("Error parsing request body: %v", err)
|
||||
return utils.ErrorResponse(c, "Invalid input data")
|
||||
}
|
||||
|
||||
aboutCoverImage, err := c.FormFile("cover_image")
|
||||
if err != nil {
|
||||
log.Printf("Error retrieving cover image about from request: %v", err)
|
||||
return utils.ErrorResponse(c, "cover_iamge is required")
|
||||
}
|
||||
|
||||
response, err := h.AboutService.UpdateAbout(id, request, aboutCoverImage)
|
||||
if err != nil {
|
||||
log.Printf("Error updating About: %v", err)
|
||||
return utils.ErrorResponse(c, fmt.Sprintf("Failed to update About: %v", err))
|
||||
}
|
||||
|
||||
return utils.SuccessResponse(c, response, "Successfully updated About")
|
||||
}
|
||||
|
||||
func (h *AboutHandler) GetAllAbout(c *fiber.Ctx) error {
|
||||
|
||||
response, err := h.AboutService.GetAllAbout()
|
||||
if err != nil {
|
||||
log.Printf("Error fetching all About: %v", err)
|
||||
return utils.ErrorResponse(c, "Failed to fetch About list")
|
||||
}
|
||||
|
||||
return utils.PaginatedResponse(c, response, 1, len(response), len(response), "Successfully fetched About list")
|
||||
}
|
||||
|
||||
func (h *AboutHandler) GetAboutByID(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
response, err := h.AboutService.GetAboutByID(id)
|
||||
if err != nil {
|
||||
log.Printf("Error fetching About by ID: %v", err)
|
||||
return utils.ErrorResponse(c, fmt.Sprintf("Failed to fetch About by ID: %v", err))
|
||||
}
|
||||
|
||||
return utils.SuccessResponse(c, response, "Successfully fetched About")
|
||||
}
|
||||
|
||||
func (h *AboutHandler) GetAboutDetailById(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
response, err := h.AboutService.GetAboutDetailById(id)
|
||||
if err != nil {
|
||||
log.Printf("Error fetching About detail by ID: %v", err)
|
||||
return utils.ErrorResponse(c, fmt.Sprintf("Failed to fetch About by ID: %v", err))
|
||||
}
|
||||
|
||||
return utils.SuccessResponse(c, response, "Successfully fetched About")
|
||||
}
|
||||
|
||||
func (h *AboutHandler) DeleteAbout(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
if err := h.AboutService.DeleteAbout(id); err != nil {
|
||||
log.Printf("Error deleting About: %v", err)
|
||||
return utils.ErrorResponse(c, fmt.Sprintf("Failed to delete About: %v", err))
|
||||
}
|
||||
|
||||
return utils.GenericResponse(c, fiber.StatusOK, "Successfully deleted About")
|
||||
}
|
||||
|
||||
func (h *AboutHandler) CreateAboutDetail(c *fiber.Ctx) error {
|
||||
var request dto.RequestAboutDetailDTO
|
||||
if err := c.BodyParser(&request); err != nil {
|
||||
log.Printf("Error parsing request body: %v", err)
|
||||
return utils.ErrorResponse(c, "Invalid input data")
|
||||
}
|
||||
|
||||
aboutDetailImage, err := c.FormFile("image_detail")
|
||||
if err != nil {
|
||||
log.Printf("Error retrieving image detail from request: %v", err)
|
||||
return utils.ErrorResponse(c, "image_detail is required")
|
||||
}
|
||||
|
||||
response, err := h.AboutService.CreateAboutDetail(request, aboutDetailImage)
|
||||
if err != nil {
|
||||
log.Printf("Error creating AboutDetail: %v", err)
|
||||
return utils.ErrorResponse(c, fmt.Sprintf("Failed to create AboutDetail: %v", err))
|
||||
}
|
||||
|
||||
return utils.SuccessResponse(c, response, "Successfully created AboutDetail")
|
||||
}
|
||||
|
||||
func (h *AboutHandler) UpdateAboutDetail(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
var request dto.RequestAboutDetailDTO
|
||||
if err := c.BodyParser(&request); err != nil {
|
||||
log.Printf("Error parsing request body: %v", err)
|
||||
return utils.ErrorResponse(c, "Invalid input data")
|
||||
}
|
||||
|
||||
aboutDetailImage, err := c.FormFile("image_detail")
|
||||
if err != nil {
|
||||
log.Printf("Error retrieving image detail from request: %v", err)
|
||||
return utils.ErrorResponse(c, "image_detail is required")
|
||||
}
|
||||
|
||||
response, err := h.AboutService.UpdateAboutDetail(id, request, aboutDetailImage)
|
||||
if err != nil {
|
||||
log.Printf("Error updating AboutDetail: %v", err)
|
||||
return utils.ErrorResponse(c, fmt.Sprintf("Failed to update AboutDetail: %v", err))
|
||||
}
|
||||
|
||||
return utils.SuccessResponse(c, response, "Successfully updated AboutDetail")
|
||||
}
|
||||
|
||||
func (h *AboutHandler) DeleteAboutDetail(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
if err := h.AboutService.DeleteAboutDetail(id); err != nil {
|
||||
log.Printf("Error deleting AboutDetail: %v", err)
|
||||
return utils.ErrorResponse(c, fmt.Sprintf("Failed to delete AboutDetail: %v", err))
|
||||
}
|
||||
|
||||
return utils.GenericResponse(c, fiber.StatusOK, "Successfully deleted AboutDetail")
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package repositories
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"rijig/model"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type AboutRepository interface {
|
||||
CreateAbout(about *model.About) error
|
||||
CreateAboutDetail(aboutDetail *model.AboutDetail) error
|
||||
GetAllAbout() ([]model.About, error)
|
||||
GetAboutByID(id string) (*model.About, error)
|
||||
GetAboutDetailByID(id string) (*model.AboutDetail, error)
|
||||
UpdateAbout(id string, about *model.About) (*model.About, error)
|
||||
UpdateAboutDetail(id string, aboutDetail *model.AboutDetail) (*model.AboutDetail, error)
|
||||
DeleteAbout(id string) error
|
||||
DeleteAboutDetail(id string) error
|
||||
}
|
||||
|
||||
type aboutRepository struct {
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
func NewAboutRepository(db *gorm.DB) AboutRepository {
|
||||
return &aboutRepository{DB: db}
|
||||
}
|
||||
|
||||
func (r *aboutRepository) CreateAbout(about *model.About) error {
|
||||
if err := r.DB.Create(&about).Error; err != nil {
|
||||
return fmt.Errorf("failed to create About: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *aboutRepository) CreateAboutDetail(aboutDetail *model.AboutDetail) error {
|
||||
if err := r.DB.Create(&aboutDetail).Error; err != nil {
|
||||
return fmt.Errorf("failed to create AboutDetail: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *aboutRepository) GetAllAbout() ([]model.About, error) {
|
||||
var abouts []model.About
|
||||
if err := r.DB.Find(&abouts).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch all About records: %v", err)
|
||||
}
|
||||
return abouts, nil
|
||||
}
|
||||
|
||||
func (r *aboutRepository) GetAboutByID(id string) (*model.About, error) {
|
||||
var about model.About
|
||||
if err := r.DB.Preload("AboutDetail").Where("id = ?", id).First(&about).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, fmt.Errorf("about with ID %s not found", id)
|
||||
}
|
||||
return nil, fmt.Errorf("failed to fetch About by ID: %v", err)
|
||||
}
|
||||
return &about, nil
|
||||
}
|
||||
|
||||
func (r *aboutRepository) GetAboutDetailByID(id string) (*model.AboutDetail, error) {
|
||||
var aboutDetail model.AboutDetail
|
||||
if err := r.DB.Where("id = ?", id).First(&aboutDetail).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, fmt.Errorf("aboutdetail with ID %s not found", id)
|
||||
}
|
||||
return nil, fmt.Errorf("failed to fetch About by ID: %v", err)
|
||||
}
|
||||
return &aboutDetail, nil
|
||||
}
|
||||
|
||||
func (r *aboutRepository) UpdateAbout(id string, about *model.About) (*model.About, error) {
|
||||
if err := r.DB.Model(&about).Where("id = ?", id).Updates(about).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed to update About: %v", err)
|
||||
}
|
||||
return about, nil
|
||||
}
|
||||
|
||||
func (r *aboutRepository) UpdateAboutDetail(id string, aboutDetail *model.AboutDetail) (*model.AboutDetail, error) {
|
||||
if err := r.DB.Model(&aboutDetail).Where("id = ?", id).Updates(aboutDetail).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed to update AboutDetail: %v", err)
|
||||
}
|
||||
return aboutDetail, nil
|
||||
}
|
||||
|
||||
func (r *aboutRepository) DeleteAbout(id string) error {
|
||||
if err := r.DB.Where("id = ?", id).Delete(&model.About{}).Error; err != nil {
|
||||
return fmt.Errorf("failed to delete About: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *aboutRepository) DeleteAboutDetail(id string) error {
|
||||
if err := r.DB.Where("id = ?", id).Delete(&model.AboutDetail{}).Error; err != nil {
|
||||
return fmt.Errorf("failed to delete AboutDetail: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,426 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"mime/multipart"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"rijig/dto"
|
||||
"rijig/internal/repositories"
|
||||
"rijig/model"
|
||||
"rijig/utils"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type AboutService interface {
|
||||
CreateAbout(request dto.RequestAboutDTO, coverImageAbout *multipart.FileHeader) (*dto.ResponseAboutDTO, error)
|
||||
UpdateAbout(id string, request dto.RequestAboutDTO, coverImageAbout *multipart.FileHeader) (*dto.ResponseAboutDTO, error)
|
||||
GetAllAbout() ([]dto.ResponseAboutDTO, error)
|
||||
GetAboutByID(id string) (*dto.ResponseAboutDTO, error)
|
||||
GetAboutDetailById(id string) (*dto.ResponseAboutDetailDTO, error)
|
||||
DeleteAbout(id string) error
|
||||
|
||||
CreateAboutDetail(request dto.RequestAboutDetailDTO, coverImageAboutDetail *multipart.FileHeader) (*dto.ResponseAboutDetailDTO, error)
|
||||
UpdateAboutDetail(id string, request dto.RequestAboutDetailDTO, imageDetail *multipart.FileHeader) (*dto.ResponseAboutDetailDTO, error)
|
||||
DeleteAboutDetail(id string) error
|
||||
}
|
||||
|
||||
type aboutService struct {
|
||||
aboutRepo repositories.AboutRepository
|
||||
}
|
||||
|
||||
func NewAboutService(aboutRepo repositories.AboutRepository) AboutService {
|
||||
return &aboutService{aboutRepo: aboutRepo}
|
||||
}
|
||||
|
||||
func formatResponseAboutDetailDTO(about *model.AboutDetail) (*dto.ResponseAboutDetailDTO, error) {
|
||||
createdAt, _ := utils.FormatDateToIndonesianFormat(about.CreatedAt)
|
||||
updatedAt, _ := utils.FormatDateToIndonesianFormat(about.UpdatedAt)
|
||||
|
||||
response := &dto.ResponseAboutDetailDTO{
|
||||
ID: about.ID,
|
||||
AboutID: about.AboutID,
|
||||
ImageDetail: about.ImageDetail,
|
||||
Description: about.Description,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func formatResponseAboutDTO(about *model.About) (*dto.ResponseAboutDTO, error) {
|
||||
createdAt, _ := utils.FormatDateToIndonesianFormat(about.CreatedAt)
|
||||
updatedAt, _ := utils.FormatDateToIndonesianFormat(about.UpdatedAt)
|
||||
|
||||
response := &dto.ResponseAboutDTO{
|
||||
ID: about.ID,
|
||||
Title: about.Title,
|
||||
CoverImage: about.CoverImage,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (s *aboutService) saveCoverImageAbout(coverImageAbout *multipart.FileHeader) (string, error) {
|
||||
pathImage := "/uploads/coverabout/"
|
||||
coverImageAboutDir := "./public" + os.Getenv("BASE_URL") + pathImage
|
||||
if _, err := os.Stat(coverImageAboutDir); os.IsNotExist(err) {
|
||||
|
||||
if err := os.MkdirAll(coverImageAboutDir, os.ModePerm); err != nil {
|
||||
return "", fmt.Errorf("gagal membuat direktori untuk cover image about: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
allowedExtensions := map[string]bool{".jpg": true, ".jpeg": true, ".png": true, ".svg": true}
|
||||
extension := filepath.Ext(coverImageAbout.Filename)
|
||||
if !allowedExtensions[extension] {
|
||||
return "", fmt.Errorf("invalid file type, only .jpg, .jpeg, and .png are allowed")
|
||||
}
|
||||
|
||||
coverImageFileName := fmt.Sprintf("%s_coverabout%s", uuid.New().String(), extension)
|
||||
coverImagePath := filepath.Join(coverImageAboutDir, coverImageFileName)
|
||||
|
||||
src, err := coverImageAbout.Open()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to open uploaded file: %v", err)
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
dst, err := os.Create(coverImagePath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create cover image about file: %v", err)
|
||||
}
|
||||
defer dst.Close()
|
||||
|
||||
if _, err := dst.ReadFrom(src); err != nil {
|
||||
return "", fmt.Errorf("failed to save cover image about: %v", err)
|
||||
}
|
||||
|
||||
coverImageAboutUrl := fmt.Sprintf("%s%s", pathImage, coverImageFileName)
|
||||
|
||||
return coverImageAboutUrl, nil
|
||||
}
|
||||
|
||||
func (s *aboutService) saveCoverImageAboutDetail(coverImageAbout *multipart.FileHeader) (string, error) {
|
||||
pathImage := "/uploads/coverabout/coveraboutdetail"
|
||||
coverImageAboutDir := "./public" + os.Getenv("BASE_URL") + pathImage
|
||||
if _, err := os.Stat(coverImageAboutDir); os.IsNotExist(err) {
|
||||
|
||||
if err := os.MkdirAll(coverImageAboutDir, os.ModePerm); err != nil {
|
||||
return "", fmt.Errorf("gagal membuat direktori untuk cover image about: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
allowedExtensions := map[string]bool{".jpg": true, ".jpeg": true, ".png": true, ".svg": true}
|
||||
extension := filepath.Ext(coverImageAbout.Filename)
|
||||
if !allowedExtensions[extension] {
|
||||
return "", fmt.Errorf("invalid file type, only .jpg, .jpeg, and .png are allowed")
|
||||
}
|
||||
|
||||
coverImageFileName := fmt.Sprintf("%s_coveraboutdetail_%s", uuid.New().String(), extension)
|
||||
coverImagePath := filepath.Join(coverImageAboutDir, coverImageFileName)
|
||||
|
||||
src, err := coverImageAbout.Open()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to open uploaded file: %v", err)
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
dst, err := os.Create(coverImagePath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create cover image about file: %v", err)
|
||||
}
|
||||
defer dst.Close()
|
||||
|
||||
if _, err := dst.ReadFrom(src); err != nil {
|
||||
return "", fmt.Errorf("failed to save cover image about: %v", err)
|
||||
}
|
||||
|
||||
coverImageAboutUrl := fmt.Sprintf("%s%s", pathImage, coverImageFileName)
|
||||
|
||||
return coverImageAboutUrl, nil
|
||||
}
|
||||
|
||||
func deleteCoverImageAbout(coverimageAboutPath string) error {
|
||||
if coverimageAboutPath == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
baseDir := "./public/" + os.Getenv("BASE_URL")
|
||||
absolutePath := baseDir + coverimageAboutPath
|
||||
|
||||
if _, err := os.Stat(absolutePath); os.IsNotExist(err) {
|
||||
return fmt.Errorf("image file not found: %v", err)
|
||||
}
|
||||
|
||||
err := os.Remove(absolutePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete image: %v", err)
|
||||
}
|
||||
|
||||
log.Printf("Image deleted successfully: %s", absolutePath)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *aboutService) CreateAbout(request dto.RequestAboutDTO, coverImageAbout *multipart.FileHeader) (*dto.ResponseAboutDTO, error) {
|
||||
errors, valid := request.ValidateAbout()
|
||||
if !valid {
|
||||
return nil, fmt.Errorf("validation error: %v", errors)
|
||||
}
|
||||
|
||||
coverImageAboutPath, err := s.saveCoverImageAbout(coverImageAbout)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("gagal menyimpan cover image about: %v ", err)
|
||||
}
|
||||
|
||||
about := model.About{
|
||||
Title: request.Title,
|
||||
CoverImage: coverImageAboutPath,
|
||||
}
|
||||
|
||||
if err := s.aboutRepo.CreateAbout(&about); err != nil {
|
||||
return nil, fmt.Errorf("failed to create About: %v", err)
|
||||
}
|
||||
|
||||
response, err := formatResponseAboutDTO(&about)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error formatting About response: %v", err)
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (s *aboutService) UpdateAbout(id string, request dto.RequestAboutDTO, coverImageAbout *multipart.FileHeader) (*dto.ResponseAboutDTO, error) {
|
||||
|
||||
errors, valid := request.ValidateAbout()
|
||||
if !valid {
|
||||
return nil, fmt.Errorf("validation error: %v", errors)
|
||||
}
|
||||
|
||||
about, err := s.aboutRepo.GetAboutByID(id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("about not found: %v", err)
|
||||
}
|
||||
|
||||
if about.CoverImage != "" {
|
||||
err := deleteCoverImageAbout(about.CoverImage)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("gagal mengahpus gambar lama: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
var coverImageAboutPath string
|
||||
if coverImageAbout != nil {
|
||||
coverImageAboutPath, err = s.saveCoverImageAbout(coverImageAbout)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("gagal menyimpan gambar baru: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
about.Title = request.Title
|
||||
if coverImageAboutPath != "" {
|
||||
about.CoverImage = coverImageAboutPath
|
||||
}
|
||||
|
||||
updatedAbout, err := s.aboutRepo.UpdateAbout(id, about)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to update About: %v", err)
|
||||
}
|
||||
|
||||
response, err := formatResponseAboutDTO(updatedAbout)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error formatting About response: %v", err)
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (s *aboutService) GetAllAbout() ([]dto.ResponseAboutDTO, error) {
|
||||
|
||||
aboutList, err := s.aboutRepo.GetAllAbout()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get About list: %v", err)
|
||||
}
|
||||
|
||||
var aboutDTOList []dto.ResponseAboutDTO
|
||||
for _, about := range aboutList {
|
||||
response, err := formatResponseAboutDTO(&about)
|
||||
if err != nil {
|
||||
log.Printf("Error formatting About response: %v", err)
|
||||
continue
|
||||
}
|
||||
aboutDTOList = append(aboutDTOList, *response)
|
||||
}
|
||||
|
||||
return aboutDTOList, nil
|
||||
}
|
||||
|
||||
func (s *aboutService) GetAboutByID(id string) (*dto.ResponseAboutDTO, error) {
|
||||
|
||||
about, err := s.aboutRepo.GetAboutByID(id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("about not found: %v", err)
|
||||
}
|
||||
|
||||
response, err := formatResponseAboutDTO(about)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error formatting About response: %v", err)
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (s *aboutService) GetAboutDetailById(id string) (*dto.ResponseAboutDetailDTO, error) {
|
||||
|
||||
about, err := s.aboutRepo.GetAboutDetailByID(id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("about not found: %v", err)
|
||||
}
|
||||
|
||||
response, err := formatResponseAboutDetailDTO(about)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error formatting About response: %v", err)
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (s *aboutService) DeleteAbout(id string) error {
|
||||
about, err := s.aboutRepo.GetAboutByID(id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("about not found: %v", err)
|
||||
}
|
||||
|
||||
if about.CoverImage != "" {
|
||||
err := deleteCoverImageAbout(about.CoverImage)
|
||||
if err != nil {
|
||||
return fmt.Errorf("gagal mengahpus gambar lama: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.aboutRepo.DeleteAbout(id); err != nil {
|
||||
return fmt.Errorf("failed to delete About: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *aboutService) CreateAboutDetail(request dto.RequestAboutDetailDTO, coverImageAboutDetail *multipart.FileHeader) (*dto.ResponseAboutDetailDTO, error) {
|
||||
|
||||
errors, valid := request.ValidateAboutDetail()
|
||||
if !valid {
|
||||
return nil, fmt.Errorf("validation error: %v", errors)
|
||||
}
|
||||
|
||||
_, err := s.aboutRepo.GetAboutByID(request.AboutId)
|
||||
if err != nil {
|
||||
|
||||
return nil, fmt.Errorf("about_id tidak ditemukan: %v", err)
|
||||
}
|
||||
|
||||
coverImageAboutDetailPath, err := s.saveCoverImageAboutDetail(coverImageAboutDetail)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("gagal menyimpan cover image about detail: %v ", err)
|
||||
}
|
||||
|
||||
aboutDetail := model.AboutDetail{
|
||||
AboutID: request.AboutId,
|
||||
ImageDetail: coverImageAboutDetailPath,
|
||||
Description: request.Description,
|
||||
}
|
||||
|
||||
if err := s.aboutRepo.CreateAboutDetail(&aboutDetail); err != nil {
|
||||
return nil, fmt.Errorf("failed to create AboutDetail: %v", err)
|
||||
}
|
||||
|
||||
createdAt, _ := utils.FormatDateToIndonesianFormat(aboutDetail.CreatedAt)
|
||||
updatedAt, _ := utils.FormatDateToIndonesianFormat(aboutDetail.UpdatedAt)
|
||||
|
||||
response := &dto.ResponseAboutDetailDTO{
|
||||
ID: aboutDetail.ID,
|
||||
AboutID: aboutDetail.AboutID,
|
||||
ImageDetail: aboutDetail.ImageDetail,
|
||||
Description: aboutDetail.Description,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (s *aboutService) UpdateAboutDetail(id string, request dto.RequestAboutDetailDTO, imageDetail *multipart.FileHeader) (*dto.ResponseAboutDetailDTO, error) {
|
||||
|
||||
errors, valid := request.ValidateAboutDetail()
|
||||
if !valid {
|
||||
return nil, fmt.Errorf("validation error: %v", errors)
|
||||
}
|
||||
|
||||
aboutDetail, err := s.aboutRepo.GetAboutDetailByID(id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("about detail tidakck ditemukan: %v", err)
|
||||
}
|
||||
|
||||
if aboutDetail.ImageDetail != "" {
|
||||
err := deleteCoverImageAbout(aboutDetail.ImageDetail)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("gagal menghapus gambar lama: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
var coverImageAboutDeatilPath string
|
||||
if imageDetail != nil {
|
||||
coverImageAboutDeatilPath, err = s.saveCoverImageAbout(imageDetail)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("gagal menyimpan gambar baru: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
aboutDetail.Description = request.Description
|
||||
if coverImageAboutDeatilPath != "" {
|
||||
aboutDetail.ImageDetail = coverImageAboutDeatilPath
|
||||
}
|
||||
|
||||
aboutDetail, err = s.aboutRepo.UpdateAboutDetail(id, aboutDetail)
|
||||
if err != nil {
|
||||
log.Printf("Error updating about detail: %v", err)
|
||||
return nil, fmt.Errorf("failed to update about detail: %v", err)
|
||||
}
|
||||
|
||||
createdAt, _ := utils.FormatDateToIndonesianFormat(aboutDetail.CreatedAt)
|
||||
updatedAt, _ := utils.FormatDateToIndonesianFormat(aboutDetail.UpdatedAt)
|
||||
|
||||
response := &dto.ResponseAboutDetailDTO{
|
||||
ID: aboutDetail.ID,
|
||||
AboutID: aboutDetail.AboutID,
|
||||
ImageDetail: aboutDetail.ImageDetail,
|
||||
Description: aboutDetail.Description,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (s *aboutService) DeleteAboutDetail(id string) error {
|
||||
aboutDetail, err := s.aboutRepo.GetAboutDetailByID(id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("about detail tidakck ditemukan: %v", err)
|
||||
}
|
||||
|
||||
if aboutDetail.ImageDetail != "" {
|
||||
err := deleteCoverImageAbout(aboutDetail.ImageDetail)
|
||||
if err != nil {
|
||||
return fmt.Errorf("gagal menghapus gambar lama: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.aboutRepo.DeleteAboutDetail(id); err != nil {
|
||||
return fmt.Errorf("failed to delete AboutDetail: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type About struct {
|
||||
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4();unique;not null" json:"id"`
|
||||
Title string `gorm:"not null" json:"title"`
|
||||
CoverImage string `json:"cover_image"`
|
||||
AboutDetail []AboutDetail `gorm:"foreignKey:AboutID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"about_detail"`
|
||||
CreatedAt time.Time `gorm:"default:current_timestamp" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updated_at"`
|
||||
}
|
||||
|
||||
type AboutDetail struct {
|
||||
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4();unique;not null" json:"id"`
|
||||
AboutID string `gorm:"not null" json:"about_id"`
|
||||
ImageDetail string `json:"image_detail"`
|
||||
Description string `json:"description"`
|
||||
CreatedAt time.Time `gorm:"default:current_timestamp" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updated_at"`
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package presentation
|
||||
|
||||
import (
|
||||
"rijig/config"
|
||||
"rijig/internal/handler"
|
||||
"rijig/internal/repositories"
|
||||
"rijig/internal/services"
|
||||
"rijig/middleware"
|
||||
"rijig/utils"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func AboutRouter(api fiber.Router) {
|
||||
|
||||
aboutRepo := repositories.NewAboutRepository(config.DB)
|
||||
aboutService := services.NewAboutService(aboutRepo)
|
||||
aboutHandler := handler.NewAboutHandler(aboutService)
|
||||
|
||||
aboutRoutes := api.Group("/about")
|
||||
aboutRoute := api.Group("/about")
|
||||
aboutRoutes.Use(middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator))
|
||||
|
||||
aboutRoute.Get("/", aboutHandler.GetAllAbout)
|
||||
aboutRoute.Get("/:id", aboutHandler.GetAboutByID)
|
||||
aboutRoutes.Post("/", aboutHandler.CreateAbout)
|
||||
aboutRoutes.Put("/:id", aboutHandler.UpdateAbout)
|
||||
aboutRoutes.Delete("/:id", aboutHandler.DeleteAbout)
|
||||
|
||||
aboutDetailRoutes := api.Group("/about-detail")
|
||||
aboutDetailRoutes.Use(middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator))
|
||||
aboutDetailRoute := api.Group("/about-detail")
|
||||
aboutDetailRoute.Get("/:id", aboutHandler.GetAboutDetailById)
|
||||
aboutDetailRoutes.Post("/", aboutHandler.CreateAboutDetail)
|
||||
aboutDetailRoutes.Put("/:id", aboutHandler.UpdateAboutDetail)
|
||||
aboutDetailRoutes.Delete("/:id", aboutHandler.DeleteAboutDetail)
|
||||
}
|
|
@ -34,6 +34,7 @@ func SetupRoutes(app *fiber.App) {
|
|||
presentation.ArticleRouter(api)
|
||||
presentation.BannerRouter(api)
|
||||
presentation.InitialCointRoute(api)
|
||||
presentation.AboutRouter(api)
|
||||
presentation.TrashRouter(api)
|
||||
presentation.StoreRouter(api)
|
||||
presentation.ProductRouter(api)
|
||||
|
|
Loading…
Reference in New Issue