diff --git a/internal/handler/article_handler.go b/internal/handler/article_handler.go index d2d9751..59db089 100644 --- a/internal/handler/article_handler.go +++ b/internal/handler/article_handler.go @@ -59,3 +59,18 @@ func (h *ArticleHandler) GetAllArticles(c *fiber.Ctx) error { return utils.NonPaginatedResponse(c, article, totalArticle, "Article fetched successfully") } + +func (h *ArticleHandler) GetArticleByID(c *fiber.Ctx) error { + + id := c.Params("article_id") + if id == "" { + return utils.GenericErrorResponse(c, fiber.StatusBadRequest, "Article ID is required") + } + + article, err := h.ArticleService.GetArticleByID(id) + if err != nil { + return utils.GenericErrorResponse(c, fiber.StatusNotFound, err.Error()) + } + + return utils.SuccessResponse(c, article, "Article fetched successfully") +} diff --git a/internal/services/article_service.go b/internal/services/article_service.go index 6fff972..f766e5e 100644 --- a/internal/services/article_service.go +++ b/internal/services/article_service.go @@ -13,6 +13,7 @@ import ( type ArticleService interface { CreateArticle(articleDTO dto.RequestArticleDTO) (*dto.ArticleResponseDTO, error) GetAllArticles(page, limit int) ([]dto.ArticleResponseDTO, int, error) + GetArticleByID(id string) (*dto.ArticleResponseDTO, error) } type articleService struct { @@ -123,3 +124,54 @@ func (s *articleService) GetAllArticles(page, limit int) ([]dto.ArticleResponseD return articleDTOs, total, nil } + +func (s *articleService) GetArticleByID(id string) (*dto.ArticleResponseDTO, error) { + cacheKey := fmt.Sprintf("article:%s", id) + + cachedData, err := utils.GetJSONData(cacheKey) + if err == nil && cachedData != nil { + articleData, ok := cachedData["data"].(map[string]interface{}) + if ok { + article := dto.ArticleResponseDTO{ + ID: articleData["article_id"].(string), + Title: articleData["title"].(string), + CoverImage: articleData["coverImage"].(string), + Author: articleData["author"].(string), + Heading: articleData["heading"].(string), + Content: articleData["content"].(string), + PublishedAt: articleData["publishedAt"].(string), + UpdatedAt: articleData["updatedAt"].(string), + } + return &article, nil + } + } + + article, err := s.ArticleRepo.FindArticleByID(id) + if err != nil { + return nil, fmt.Errorf("failed to fetch article by ID: %v", err) + } + + createdAt, _ := utils.FormatDateToIndonesianFormat(article.PublishedAt) + updatedAt, _ := utils.FormatDateToIndonesianFormat(article.UpdatedAt) + + articleResponseDTO := &dto.ArticleResponseDTO{ + ID: article.ID, + Title: article.Title, + CoverImage: article.CoverImage, + Author: article.Author, + Heading: article.Heading, + Content: article.Content, + PublishedAt: createdAt, + UpdatedAt: updatedAt, + } + + cacheData := map[string]interface{}{ + "data": articleResponseDTO, + } + err = utils.SetJSONData(cacheKey, cacheData, time.Hour*24) + if err != nil { + fmt.Printf("Error caching article to Redis: %v\n", err) + } + + return articleResponseDTO, nil +} diff --git a/presentation/article_route.go b/presentation/article_route.go index 6fae6a4..e942dd3 100644 --- a/presentation/article_route.go +++ b/presentation/article_route.go @@ -19,4 +19,5 @@ func ArticleRouter(api fiber.Router) { articleAPI.Post("/create-article", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator), articleHandler.CreateArticle) articleAPI.Get("/view-article", middleware.AuthMiddleware, articleHandler.GetAllArticles) + articleAPI.Get("/view-article/:article_id", middleware.AuthMiddleware, articleHandler.GetArticleByID) }