Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions app/app.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package app

import (
blogPost "github.com/hammer-code/lms-be/app/blog_post"
"github.com/hammer-code/lms-be/app/middlewares"
newsletters "github.com/hammer-code/lms-be/app/newsletters"
users "github.com/hammer-code/lms-be/app/users"
Expand All @@ -20,6 +21,7 @@ type App struct {
NewLetterHandler domain.NewslettterHandler
EventHandler domain.EventHandler
ImageHandler domain.ImageHandler
BlogPostHandler domain.BlogPostHandler
}

func InitApp(
Expand All @@ -39,6 +41,7 @@ func InitApp(
newsletterRepo := newsletters.InitRepository(dbTx)
eventRepo := events.InitRepository(dbTx)
imgRepo := images.InitRepository(dbTx)
blogPostRepo := blogPost.InitRepository(dbTx)

// Middlewares
middleware := middlewares.InitMiddleware(jwtInstance, userRepo)
Expand All @@ -48,18 +51,21 @@ func InitApp(
newsletterUC := newsletters.InitUsecase(cfg, newsletterRepo, dbTx, jwt.NewJwt(cfg.JWT_SECRET_KEY))
eventUC := events.InitUsecase(eventRepo, imgRepo, dbTx)
imgUc := images.InitUsecase(imgRepo, dbTx)
blogPostUc := blogPost.InitUseCase(blogPostRepo, jwtInstance)

// handler
userHandler := users.InitHandler(userUsecase)
newsletterHandler := newsletters.InitHandler(newsletterUC, middleware)
eventHandler := events.InitHandler(eventUC)
ImageHandler := images.InitHandler(imgUc)
blogPostHandler := blogPost.InitHandler(blogPostUc)

return App{
UserHandler: userHandler,
NewLetterHandler: newsletterHandler,
Middleware: middleware,
EventHandler: eventHandler,
ImageHandler: ImageHandler,
BlogPostHandler: blogPostHandler,
}
}
22 changes: 22 additions & 0 deletions app/blog_post/blogPost.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package blog_post

import (
blog_post_handler "github.com/hammer-code/lms-be/app/blog_post/delivery/http"
blog_post_repo "github.com/hammer-code/lms-be/app/blog_post/repository"
blog_post_usecase "github.com/hammer-code/lms-be/app/blog_post/usecase"
"github.com/hammer-code/lms-be/domain"
"github.com/hammer-code/lms-be/pkg/db"
"github.com/hammer-code/lms-be/pkg/jwt"
)

func InitRepository(db db.DatabaseTransaction) domain.BlogPostRepository {
return blog_post_repo.NewRepository(db)
}

func InitUseCase(repository domain.BlogPostRepository, jwt jwt.JWT) domain.BlogPostUsecase {
return blog_post_usecase.NewUsecase(repository, jwt)
}

func InitHandler(usecase domain.BlogPostUsecase) domain.BlogPostHandler {
return blog_post_handler.NewHandler(usecase)
}
239 changes: 239 additions & 0 deletions app/blog_post/delivery/http/http.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
package http

import (
"encoding/json"
"io"
"net/http"
"strconv"
"strings"
"time"

"github.com/gorilla/mux"
"github.com/hammer-code/lms-be/domain"
"github.com/hammer-code/lms-be/utils"
"github.com/sirupsen/logrus"
)

type Handler struct {
usecase domain.BlogPostUsecase
}

// CreateBlogPost implements domain.BlogPostHandler.
func (h Handler) CreateBlogPost(w http.ResponseWriter, r *http.Request) {
bodyBytes, err := io.ReadAll(r.Body)
if err != nil {
resp := utils.CustomErrorResponse(err)
utils.Response(resp, w)
return
}

var token string
if hasToken := strings.HasPrefix(r.Header.Get("Authorization"), "Bearer "); hasToken {
token = strings.TrimPrefix(r.Header.Get("Authorization"), "Bearer ")
if token == "" {
resp := utils.CustomErrorResponse(utils.NewUnauthorizedError(r.Context(), "Authorization token is required", nil))
utils.Response(resp, w)
return
}
}

BlogPost := domain.BlogPost{}
if err = json.Unmarshal(bodyBytes, &BlogPost); err != nil {
resp := utils.CustomErrorResponse(err)
utils.Response(resp, w)
return
}

data, err := h.usecase.CreateBlogPost(r.Context(), BlogPost, token)
if err != nil {
resp := utils.CustomErrorResponse(err)
utils.Response(resp, w)
return
}

utils.Response(domain.HttpResponse{
Code: http.StatusCreated,
Message: "Blog post created successfully",
Data: data,
}, w)

}

// DeleteBlogPost implements domain.BlogPostHandler.
func (h Handler) DeleteBlogPost(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
idString := vars["id"]

value, err := strconv.ParseUint(idString, 10, 32)
if err != nil {
logrus.Error("failed to convert string to uint: ", err)
utils.Response(domain.HttpResponse{
Code: 500,
Message: err.Error(),
}, w)
return
}

err = h.usecase.DeleteBlogPost(r.Context(), uint(value))
if err != nil {
logrus.Error("failed to delete event : ", err)
utils.Response(domain.HttpResponse{
Code: 500,
Message: err.Error(),
}, w)
return
}

utils.Response(domain.HttpResponse{
Code: 200,
Message: "success",
Data: nil,
}, w)
}

// GetAllBlogPosts implements domain.BlogPostHandler.
func (h Handler) GetAllBlogPosts(w http.ResponseWriter, r *http.Request) {
resp, err := h.usecase.GetAllBlogPosts(r.Context())
if err != nil {
resp := utils.CustomErrorResponse(err)
utils.Response(resp, w)
return
}

utils.Response(domain.HttpResponse{
Code: http.StatusOK,
Message: "Blog posts retrieved successfully",
Data: resp,
}, w)

}

// GetDetailBlogPost implements domain.BlogPostHandler.
func (h Handler) GetDetailBlogPost(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
slug := vars["slug"]

if slug == "" {
resp := utils.CustomErrorResponse(utils.NewBadRequestError(r.Context(), "Slug is required", nil))
utils.Response(resp, w)
return
}

resp, err := h.usecase.GetDetailBlogPost(r.Context(), slug, 0)
if err != nil {
resp := utils.CustomErrorResponse(err)
utils.Response(resp, w)
return
}

utils.Response(domain.HttpResponse{
Code: http.StatusOK,
Message: "Blog post retrieved successfully",
Data: resp,
}, w)
}

// UpdateBlogPost implements domain.BlogPostHandler.
func (h Handler) UpdateBlogPost(w http.ResponseWriter, r *http.Request) {
idS := mux.Vars(r)["id"]
id, err := strconv.ParseUint(idS, 10, 32)
if err != nil {
logrus.Error("failed to convert string to uint: ", err)
utils.Response(domain.HttpResponse{
Code: http.StatusBadRequest,
Message: "Invalid ID format",
}, w)
return
}

existingPost, err := h.usecase.GetDetailBlogPost(r.Context(), "", uint(id))
if err != nil {
logrus.Error("failed to get existing blog post: ", err)
utils.Response(domain.HttpResponse{
Code: http.StatusNotFound,
Message: "Blog post not found",
}, w)
return
}

body, err := io.ReadAll(r.Body)
if err != nil {
logrus.Error("failed to read body: ", err)
utils.Response(domain.HttpResponse{
Code: http.StatusBadRequest,
Message: "Invalid request body",
}, w)
return
}

var patchData map[string]interface{}
if err := json.Unmarshal(body, &patchData); err != nil {
logrus.Error("failed to unmarshal: ", err)
utils.Response(domain.HttpResponse{
Code: http.StatusBadRequest,
Message: "Invalid request format",
}, w)
return
}

updatedPost := existingPost
if title, ok := patchData["title"].(string); ok {
updatedPost.Title = title
}
if content, ok := patchData["content"].(string); ok {
updatedPost.Content = content
}
if excerpt, ok := patchData["excerpt"].(string); ok {
updatedPost.Excerpt = excerpt
}
if category, ok := patchData["category"].(string); ok {
updatedPost.Category = category
}
if status, ok := patchData["status"].(string); ok {
updatedPost.Status = status
}
if tags, ok := patchData["tags"].([]interface{}); ok {
updatedPost.Tags = make([]string, len(tags))
for i, tag := range tags {
updatedPost.Tags[i] = tag.(string)
}
}

if authorData, ok := patchData["author"].(map[string]interface{}); ok {
if avatar, ok := authorData["avatar"].(string); ok && avatar != "" {
updatedPost.Author.Avatar = avatar
}
}

updatedPost.UpdatedAt = time.Now()

err = h.usecase.UpdateBlogPost(r.Context(), updatedPost, uint(id))
if err != nil {
logrus.Error("failed to update blog post: ", err)
utils.Response(domain.HttpResponse{
Code: http.StatusInternalServerError,
Message: "Failed to update blog post",
}, w)
return
}

utils.Response(domain.HttpResponse{
Code: http.StatusOK,
Message: "Blog post updated successfully",
Data: updatedPost,
}, w)
}

var (
handlr *Handler
)

func NewHandler(usecase domain.BlogPostUsecase) domain.BlogPostHandler {
if handlr == nil {
handlr = &Handler{
usecase: usecase,
}

}
return *handlr
}
Loading