Skip to content

Commit

Permalink
feature: get article by id
Browse files Browse the repository at this point in the history
feature: get article by id & filter by date
  • Loading branch information
masnann authored Nov 25, 2023
2 parents 7b55736 + 52ded50 commit 9388f1a
Show file tree
Hide file tree
Showing 10 changed files with 301 additions and 184 deletions.
6 changes: 3 additions & 3 deletions module/entities/category_models.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ type CategoryModels struct {
Name string `gorm:"column:name;type:varchar(255)" json:"name"`
Photo string `gorm:"column:photo;type:varchar(255)" json:"photo"`
TotalProduct uint64 `gorm:"column:total_product;type:BIGINT UNSIGNED" json:"total_product"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp DEFAULT CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp DEFAULT CURRENT_TIMESTAMP" json:"updated_at"`
DeletedAt *time.Time `gorm:"column:deleted_at;index" json:"deleted_at"`
CreatedAt time.Time `gorm:"column:created_at;type:TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:TIMESTAMP" json:"updated_at"`
DeletedAt *time.Time `gorm:"column:deleted_at;type:TIMESTAMP;index" json:"deleted_at"`
Products []ProductModels `gorm:"many2many:product_categories;" json:"products"`
}

Expand Down
12 changes: 6 additions & 6 deletions module/entities/product_models.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ type ProductModels struct {
Exp uint64 `gorm:"column:exp;type:BIGINT UNSIGNED" json:"product_exp"`
Rating float64 `gorm:"column:rating;type:DECIMAL(3, 1)" json:"rating"`
TotalReview uint64 `gorm:"column:total_review;type:BIGINT UNSIGNED" json:"total_review"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp DEFAULT CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp DEFAULT CURRENT_TIMESTAMP" json:"updated_at"`
DeletedAt *time.Time `gorm:"column:deleted_at;index" json:"deleted_at"`
CreatedAt time.Time `gorm:"column:created_at;type:TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:TIMESTAMP" json:"updated_at"`
DeletedAt *time.Time `gorm:"column:deleted_at;type:TIMESTAMP;index" json:"deleted_at"`
ProductPhotos []ProductPhotosModels `gorm:"foreignKey:ProductID" json:"product_photos"`
ProductReview []ReviewModels `gorm:"foreignKey:ProductID;references:ID" json:"review"`
Categories []CategoryModels `gorm:"many2many:product_categories;" json:"categories"`
Expand All @@ -27,9 +27,9 @@ type ProductPhotosModels struct {
ID uint64 `gorm:"column:id;type:bigint;primaryKey" json:"id"`
ProductID uint64 `gorm:"column:product_id;type:BIGINT UNSIGNED" json:"product_id"`
ImageURL string `gorm:"column:url;type:varchar(255)" json:"url"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp DEFAULT CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp DEFAULT CURRENT_TIMESTAMP" json:"updated_at"`
DeletedAt *time.Time `gorm:"column:deleted_at;index" json:"deleted_at"`
CreatedAt time.Time `gorm:"column:created_at;type:TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:TIMESTAMP" json:"updated_at"`
DeletedAt *time.Time `gorm:"column:deleted_at;type:TIMESTAMP;index" json:"deleted_at"`
}

func (ProductModels) TableName() string {
Expand Down
4 changes: 2 additions & 2 deletions module/entities/reviews_models.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type ReviewModels struct {
Date time.Time `gorm:"column:date;type:DATETIME" json:"date"`
CreatedAt time.Time `gorm:"column:created_at;type:TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:TIMESTAMP" json:"updated_at"`
DeletedAt *time.Time `gorm:"column:deleted_at;index" json:"deleted_at"`
DeletedAt *time.Time `gorm:"column:deleted_at;type:TIMESTAMP;index" json:"deleted_at"`
Photos []ReviewPhotoModels `gorm:"foreignKey:ReviewID" json:"photos"`
}

Expand All @@ -21,7 +21,7 @@ type ReviewPhotoModels struct {
ImageURL string `gorm:"column:url;type:varchar(255)" json:"url"`
CreatedAt time.Time `gorm:"column:created_at;type:TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:TIMESTAMP" json:"updated_at"`
DeletedAt *time.Time `gorm:"column:deleted_at;index" json:"deleted_at"`
DeletedAt *time.Time `gorm:"column:deleted_at;type:TIMESTAMP;index" json:"deleted_at"`
}

type ReviewDetail struct {
Expand Down
6 changes: 3 additions & 3 deletions module/entities/users_models.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ type UserModels struct {
Level string `gorm:"column:level;type:VARCHAR(255)" json:"level"`
Exp uint64 `gorm:"column:exp;type:BIGINT UNSIGNED" json:"exp"`
IsVerified bool `gorm:"column:is_verified;default:false" json:"is_verified"`
CreatedAt time.Time `gorm:"column:created_at;type:timestamp DEFAULT CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp DEFAULT CURRENT_TIMESTAMP" json:"updated_at"`
DeletedAt *time.Time `gorm:"column:deleted_at;index" json:"deleted_at"`
CreatedAt time.Time `gorm:"column:created_at;type:TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at;type:TIMESTAMP" json:"updated_at"`
DeletedAt *time.Time `gorm:"column:deleted_at;type:TIMESTAMP;index" json:"deleted_at"`
Address []AddressModels `gorm:"foreignKey:UserID" json:"addresses"`
Articles []ArticleModels `gorm:"many2many:user_bookmarks;" json:"users"`
Reviews []ReviewModels `gorm:"foreignKey:UserID" json:"reviews"`
Expand Down
2 changes: 2 additions & 0 deletions module/feature/article/dto/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type ArticleFormatter struct {
Content string `json:"content"`
Author string `json:"author"`
Date time.Time `json:"date"`
Views uint64 `json:"views"`
}

func FormatArticle(article entities.ArticleModels) ArticleFormatter {
Expand All @@ -23,6 +24,7 @@ func FormatArticle(article entities.ArticleModels) ArticleFormatter {
articleFormatter.Content = article.Content
articleFormatter.Author = article.Author
articleFormatter.Date = article.UpdatedAt
articleFormatter.Views = article.Views

return articleFormatter
}
Expand Down
187 changes: 105 additions & 82 deletions module/feature/article/handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ func (h *ArticleHandler) CreateArticle() echo.HandlerFunc {
return func(c echo.Context) error {
currentUser := c.Get("CurrentUser").(*entities.UserModels)
if currentUser.Role != "admin" {
return response.SendErrorResponse(c, http.StatusUnauthorized, "Tidak diizinkan:: Anda tidak memiliki izin")
return response.SendErrorResponse(c, http.StatusUnauthorized, "Tidak diizinkan: Anda tidak memiliki izin")
}

articleRequest := new(dto.CreateArticleRequest)
file, err := c.FormFile("photo")
var uploadedURL string
Expand All @@ -37,6 +38,7 @@ func (h *ArticleHandler) CreateArticle() echo.HandlerFunc {
if err != nil {
return response.SendErrorResponse(c, http.StatusInternalServerError, "Gagal membuka file: "+err.Error())
}

defer func(fileToUpload multipart.File) {
_ = fileToUpload.Close()
}(fileToUpload)
Expand All @@ -48,7 +50,7 @@ func (h *ArticleHandler) CreateArticle() echo.HandlerFunc {
}

if err := c.Bind(articleRequest); err != nil {
return response.SendErrorResponse(c, http.StatusBadRequest, "Format input yang Anda masukkan tidak sesuai.")
return response.SendErrorResponse(c, http.StatusBadRequest, "Format input yang Anda masukkan tidak sesuai: "+err.Error())
}

if err := utils.ValidateStruct(articleRequest); err != nil {
Expand All @@ -62,71 +64,35 @@ func (h *ArticleHandler) CreateArticle() echo.HandlerFunc {
}

createdArticle, err := h.service.CreateArticle(newArticle)
if err!= nil {
return response.SendErrorResponse(c, http.StatusInternalServerError, "Kesalahan Server Internal: "+err.Error())
}
return response.SendSuccessResponse(c, "Berhasil menambahkan artikel", dto.FormatArticle(*createdArticle))
}
}

func (h *ArticleHandler) GetAllArticles() echo.HandlerFunc {
return func(c echo.Context) error {
page, _ := strconv.Atoi(c.QueryParam("page"))
pageConv, _ := strconv.Atoi(strconv.Itoa(page))
perPage := 10

var articles []entities.ArticleModels
var totalItems int64
var err error
search := c.QueryParam("search")
if search != "" {
articles, totalItems, err = h.service.GetArticlesByTitle(page, perPage, search)
if err != nil {
c.Logger().Error("handler: failed to fetch articles by title:", err.Error())
return response.SendErrorResponse(c, http.StatusInternalServerError, "Internal Server Error")
}
} else {
articles, totalItems, err = h.service.GetAll(pageConv, perPage)
}
if err != nil {
c.Logger().Error("handler: failed to fetch all articles:", err.Error())
return response.SendErrorResponse(c, http.StatusInternalServerError, "Internal Server Error")
return response.SendErrorResponse(c, http.StatusInternalServerError, "Kesalahan Server Internal: "+err.Error())
}

current_page, total_pages := h.service.CalculatePaginationValues(pageConv, int(totalItems), perPage)
nextPage := h.service.GetNextPage(current_page, total_pages)
prevPage := h.service.GetPrevPage(current_page)

return response.Pagination(c, dto.FormatterArticle(articles), current_page, total_pages, int(totalItems), nextPage, prevPage, "Daftar artikel")
return response.SendSuccessResponse(c, "Berhasil menambahkan artikel", dto.FormatArticle(*createdArticle))
}
}

func (h *ArticleHandler) UpdateArticleById() echo.HandlerFunc {
return func(c echo.Context) error {
currentUser := c.Get("CurrentUser").(*entities.UserModels)
if currentUser.Role!= "admin" {
return response.SendErrorResponse(c, http.StatusUnauthorized, "Tidak diizinkan:: Anda tidak memiliki izin")
}
if currentUser.Role != "admin" {
return response.SendErrorResponse(c, http.StatusUnauthorized, "Tidak diizinkan: Anda tidak memiliki izin")
}

updateRequest := new(dto.UpdateArticleRequest)
articleID, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err!= nil {
return response.SendErrorResponse(c, http.StatusBadRequest, "Format input yang Anda masukkan tidak sesuai.")
}

exitingArticle, err := h.service.GetArticleById(articleID)
if err!= nil {
return response.SendErrorResponse(c, http.StatusInternalServerError, "Gagal mendapatkan artikel: "+err.Error())
}
if exitingArticle == nil {
return response.SendErrorResponse(c, http.StatusNotFound, "Artikel tidak ditemukan"+err.Error())
}
if err != nil {
return response.SendErrorResponse(c, http.StatusBadRequest, "Format input yang Anda masukkan tidak sesuai: "+err.Error())
}

file, err := c.FormFile("photo")
var uploadedURL string
if err == nil {
fileToUpload, err := file.Open()
if err != nil {
return response.SendErrorResponse(c, http.StatusInternalServerError, "Gagal membuka file: "+err.Error())
}

defer func(fileToUpload multipart.File) {
_ = fileToUpload.Close()
}(fileToUpload)
Expand All @@ -136,50 +102,107 @@ func (h *ArticleHandler) UpdateArticleById() echo.HandlerFunc {
return response.SendErrorResponse(c, http.StatusInternalServerError, "Gagal mengunggah foto: "+err.Error())
}
}
if err := c.Bind(updateRequest); err!= nil {
return response.SendErrorResponse(c, http.StatusBadRequest, "Format input yang Anda masukkan tidak sesuai.")
}

if err := utils.ValidateStruct(updateRequest); err!= nil {
return response.SendErrorResponse(c, http.StatusBadRequest, "Validasi gagal: "+err.Error())
}
if err := c.Bind(updateRequest); err != nil {
return response.SendErrorResponse(c, http.StatusBadRequest, "Format input yang Anda masukkan tidak sesuai: "+err.Error())
}

if err := utils.ValidateStruct(updateRequest); err != nil {
return response.SendErrorResponse(c, http.StatusBadRequest, "Validasi gagal: "+err.Error())
}

newData := &entities.ArticleModels{
Title: updateRequest.Title,
Photo: uploadedURL,
Content: updateRequest.Content,
}
Photo: uploadedURL,
Content: updateRequest.Content,
}

updatedArticle, err := h.service.UpdateArticleById(articleID, newData)
if err!= nil {
return response.SendErrorResponse(c, http.StatusInternalServerError, "Gagal mengubah article: "+err.Error())
}
if err != nil {
return response.SendErrorResponse(c, http.StatusInternalServerError, "Gagal mengubah artikel: "+err.Error())
}

return response.SendSuccessResponse(c, "Berhasil mengubah artikel", dto.FormatArticle(*updatedArticle))
}
}

func (h *ArticleHandler) DeleteArticleById() echo.HandlerFunc {
return func(c echo.Context) error {
currentUser := c.Get("CurrentUser").(*entities.UserModels)
if currentUser.Role!= "admin" {
return response.SendErrorResponse(c, http.StatusUnauthorized, "Tidak diizinkan:: Anda tidak memiliki izin")
}
if currentUser.Role != "admin" {
return response.SendErrorResponse(c, http.StatusUnauthorized, "Tidak diizinkan: Anda tidak memiliki izin")
}

articleID, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err!= nil {
return response.SendErrorResponse(c, http.StatusBadRequest, "Format input yang Anda masukkan tidak sesuai.")
}

exitingArticle, err := h.service.GetArticleById(articleID)
if err!= nil {
return response.SendErrorResponse(c, http.StatusInternalServerError, "Gagal mendapatkan artikel: "+err.Error())
}
if exitingArticle == nil {
return response.SendErrorResponse(c, http.StatusNotFound, "Artikel tidak ditemukan"+err.Error())
}

err = h.service.DeleteArticleById(articleID)
if err!= nil {
return response.SendErrorResponse(c, http.StatusInternalServerError, "Gagal menghapus artikel: "+err.Error())
}
return response.SendStatusOkResponse(c, "Berhasil menghapus artikel")
}
if err != nil {
return response.SendErrorResponse(c, http.StatusBadRequest, "Format input yang Anda masukkan tidak sesuai: "+err.Error())
}

err = h.service.DeleteArticleById(articleID)
if err != nil {
return response.SendErrorResponse(c, http.StatusInternalServerError, "Gagal menghapus artikel: "+err.Error())
}

return response.SendStatusOkResponse(c, "Berhasil menghapus artikel")
}
}

func (h *ArticleHandler) GetAllArticles() echo.HandlerFunc {
return func(c echo.Context) error {
page, _ := strconv.Atoi(c.QueryParam("page"))
pageConv, _ := strconv.Atoi(strconv.Itoa(page))
perPage := 10

var articles []entities.ArticleModels
var totalItems int64
var err error
search := c.QueryParam("search")
filterType := c.QueryParam("filter_type")
if search != "" {
articles, totalItems, err = h.service.GetArticlesByTitle(page, perPage, search)
if err != nil {
return response.SendErrorResponse(c, http.StatusInternalServerError, "Internal Server Error: " + err.Error())
}
} else if filterType != "" {
articles, totalItems, err = h.service.GetArticlesByDateRange(page, perPage, filterType)
if err != nil {
return response.SendErrorResponse(c, http.StatusInternalServerError, "Internal Server Error: " + err.Error())
}
} else {
articles, totalItems, err = h.service.GetAll(pageConv, perPage)
if err != nil {
return response.SendErrorResponse(c, http.StatusInternalServerError, "Internal Server Error: " + err.Error())
}
}

if err != nil {
return response.SendErrorResponse(c, http.StatusInternalServerError, "Internal Server Error: " + err.Error())
}

current_page, total_pages := h.service.CalculatePaginationValues(pageConv, int(totalItems), perPage)
nextPage := h.service.GetNextPage(current_page, total_pages)
prevPage := h.service.GetPrevPage(current_page)

return response.Pagination(c, dto.FormatterArticle(articles), current_page, total_pages, int(totalItems), nextPage, prevPage, "Daftar artikel")
}
}

func (h *ArticleHandler) GetArticleById() echo.HandlerFunc {
return func(c echo.Context) error {
id := c.Param("id")
articleID, err := strconv.ParseUint(id, 10, 64)
if err != nil {
return response.SendErrorResponse(c, http.StatusBadRequest, "Format input yang Anda masukkan tidak sesuai: " + err.Error())
}

currentUser := c.Get("CurrentUser").(*entities.UserModels)
incrementViews := currentUser.Role != "admin"

getArticleID, err := h.service.GetArticleById(articleID, incrementViews)
if err != nil {
return response.SendErrorResponse(c, http.StatusInternalServerError, "Gagal mengambil artikel: " + err.Error())
}

return response.SendSuccessResponse(c, "Detail artikel", dto.FormatArticle(*getArticleID))
}
}
23 changes: 15 additions & 8 deletions module/feature/article/interface.go
Original file line number Diff line number Diff line change
@@ -1,36 +1,43 @@
package article

import (
"time"

"github.com/capstone-kelompok-7/backend-disappear/module/entities"
"github.com/labstack/echo/v4"
)

type RepositoryArticleInterface interface {
CreateArticle(article *entities.ArticleModels) (*entities.ArticleModels, error)
GetArticleById(id uint64) (*entities.ArticleModels, error)
UpdateArticleById(id uint64, updatedArticle *entities.ArticleModels) (*entities.ArticleModels, error)
UpdateArticleViews(article *entities.ArticleModels) error
DeleteArticleById(id uint64) error
FindAll(page, perpage int) ([]entities.ArticleModels, error)
GetTotalArticleCount() (int64, error)
FindByTitle(page, perpage int, title string) ([]entities.ArticleModels, error)
GetTotalArticleCountByTitle(title string) (int64, error)
UpdateArticleById(id uint64, updatedArticle *entities.ArticleModels) (*entities.ArticleModels, error)
DeleteArticleById(id uint64) error
GetArticleById(id uint64) (*entities.ArticleModels, error)
GetArticlesByDateRange(page, perpage int, startDate, endDate time.Time) ([]entities.ArticleModels, error)
GetTotalArticleCountByDateRange(startDate, endDate time.Time) (int64, error)
}

type ServiceArticleInterface interface {
CreateArticle(articleData *entities.ArticleModels) (*entities.ArticleModels, error)
UpdateArticleById(id uint64, updatedArticle *entities.ArticleModels) (*entities.ArticleModels, error)
DeleteArticleById(id uint64) error
GetAll(page, perPage int) ([]entities.ArticleModels, int64, error)
GetArticlesByTitle(page, perPage int, title string) ([]entities.ArticleModels, int64, error)
GetArticleById(id uint64, incrementVIews bool) (*entities.ArticleModels, error)
GetArticlesByDateRange(page, perPage int, filterType string) ([]entities.ArticleModels, int64, error)
CalculatePaginationValues(page int, totalItems int, perPage int) (int, int)
GetNextPage(currentPage, totalPages int) int
GetPrevPage(currentPage int) int
GetArticlesByTitle(page, perPage int, title string) ([]entities.ArticleModels, int64, error)
GetArticleById(id uint64) (*entities.ArticleModels, error)
UpdateArticleById(id uint64, updatedArticle *entities.ArticleModels) (*entities.ArticleModels, error)
DeleteArticleById(id uint64) error
}

type HandlerArticleInterface interface {
CreateArticle() echo.HandlerFunc
GetAllArticles() echo.HandlerFunc
UpdateArticleById() echo.HandlerFunc
DeleteArticleById() echo.HandlerFunc
GetAllArticles() echo.HandlerFunc
GetArticleById() echo.HandlerFunc
}
Loading

0 comments on commit 9388f1a

Please sign in to comment.