feat: add feature how to and how about

This commit is contained in:
pahmiudahgede 2025-05-06 22:49:31 +07:00
parent 9f1a4eb8fa
commit 30d082f4e9
8 changed files with 830 additions and 0 deletions

View File

@ -60,6 +60,8 @@ func ConnectDatabase() {
&model.Article{}, &model.Article{},
&model.Banner{}, &model.Banner{},
&model.InitialCoint{}, &model.InitialCoint{},
&model.About{},
&model.AboutDetail{},
// =>Trash Model<= // =>Trash Model<=
&model.TrashCategory{}, &model.TrashCategory{},

71
dto/about_dto.go Normal file
View File

@ -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"`
}

View File

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

View File

@ -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
}

View File

@ -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
}

23
model/about_model.go Normal file
View File

@ -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"`
}

View File

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

View File

@ -34,6 +34,7 @@ func SetupRoutes(app *fiber.App) {
presentation.ArticleRouter(api) presentation.ArticleRouter(api)
presentation.BannerRouter(api) presentation.BannerRouter(api)
presentation.InitialCointRoute(api) presentation.InitialCointRoute(api)
presentation.AboutRouter(api)
presentation.TrashRouter(api) presentation.TrashRouter(api)
presentation.StoreRouter(api) presentation.StoreRouter(api)
presentation.ProductRouter(api) presentation.ProductRouter(api)