Skip to content

Commit

Permalink
ref(campaign) :CRUD campaign
Browse files Browse the repository at this point in the history
  • Loading branch information
Ndraaa15 committed Apr 27, 2024
1 parent 21a9bf8 commit c0b70b3
Show file tree
Hide file tree
Showing 8 changed files with 369 additions and 18 deletions.
5 changes: 5 additions & 0 deletions cmd/api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,21 @@ func main() {
api := app.Group("/api")
rest.RegisterUtilsHandler(api)

supabaseClient := conf.NewSupabaseImage(log)

userRepo := repository.NewUserRepository(db)
verifRepo := repository.NewVerificationRepository(db)
merchantRepo := repository.NewMerchantRepository(db)
campaignRepo := repository.NewCampaignRepository(db)
authUsecase := usecase.NewAuthUsecase(userRepo, verifRepo, mailer, log)
rest.RegisterAuthHandler(authUsecase, validator, api)
userUsecase := usecase.NewUserUsecase(userRepo, merchantRepo, supabaseImg, log)
rest.RegisterUserHandler(userUsecase, validator, api)
enclosureRepo := repository.NewEnclosureRepository(db)
animalUsecase := usecase.NewAnimalUsecase(userRepo, enclosureRepo)
rest.RegisterAnimalHandler(animalUsecase, api)
campaignUsecase := usecase.NewCampaignUsecase(campaignRepo, log, supabaseClient)
rest.RegisterCampaignHandler(campaignUsecase, api, validator)

if err := app.Listen(":" + os.Getenv("APP_PORT")); err != nil {
log.Fatalf("Fail to start server: %v", err)
Expand Down
117 changes: 115 additions & 2 deletions internal/delivery/rest/campaign.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,34 @@
package rest

import (
"mime/multipart"
"strconv"

"github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2"
"github.com/mirzahilmi/hackathon/internal/model"
"github.com/mirzahilmi/hackathon/internal/usecase"
)

type campaignHandler struct {
usecase usecase.CampaignUsecaseItf
usecase usecase.CampaignUsecaseItf
validator *validator.Validate
}

func RegisterCampaignHandler(
usecase usecase.CampaignUsecaseItf,
router fiber.Router,
validator *validator.Validate,
) {
campaignHandler := campaignHandler{usecase}
campaignHandler := campaignHandler{usecase, validator}
router = router.Group("/campaigns")
router.Get("", campaignHandler.FetchAll)
router.Get("/:id<int>", campaignHandler.FetchSingle)
router.Post("", campaignHandler.Create)
router.Patch("/:id<int>", campaignHandler.Update)
router.Delete("/:id<int>", campaignHandler.Delete)
router.Get("/_admin", campaignHandler.GetAllForAdmin)
router.Get("/_admin/:id<int>", campaignHandler.GetByIDForAdmin)
}

func (h *campaignHandler) FetchAll(c *fiber.Ctx) error {
Expand All @@ -40,3 +50,106 @@ func (h *campaignHandler) FetchSingle(c *fiber.Ctx) error {
}
return c.Status(fiber.StatusOK).JSON(campaign)
}

func (h *campaignHandler) Create(c *fiber.Ctx) error {
pict, err := c.FormFile("picture")
if err != nil {
return err
}

reward, err := strconv.ParseUint(c.FormValue("reward"), 10, 64)
if err != nil {
return err
}

req := model.CampaignRequest{
Picture: pict,
Title: c.FormValue("title"),
Description: c.FormValue("description"),
Reward: int(reward),
}

if err := h.validator.Struct(&req); err != nil {
return err
}

err = h.usecase.Create(c.Context(), req)
if err != nil {
return err
}
return c.Status(fiber.StatusCreated).JSON(fiber.Map{"message": "Campaign created successfully"})
}

func (h *campaignHandler) Update(c *fiber.Ctx) error {
id, err := strconv.ParseInt(c.Params("id"), 10, 64)
if err != nil {
return err
}

var pict *multipart.FileHeader
pict, err = c.FormFile("picture")
if err != nil {
if err.Error() == "there is no uploaded file associated with the given key" {
pict = nil
} else {
return err
}
}

var reward uint64
if c.FormValue("reward") == "" {
reward = 0
} else {
reward, err = strconv.ParseUint(c.FormValue("reward"), 10, 64)
if err != nil {
return err
}
}

req := model.CampaignRequest{
Picture: pict,
Title: c.FormValue("title"),
Description: c.FormValue("description"),
Reward: int(reward),
}

err = h.usecase.Update(c.Context(), req, id)
if err != nil {
return err
}
return c.Status(fiber.StatusCreated).JSON(fiber.Map{"message": "Campaign updated successfully"})

}

func (h *campaignHandler) Delete(c *fiber.Ctx) error {
id, err := strconv.ParseInt(c.Params("id"), 10, 64)
if err != nil {
return err
}

err = h.usecase.Delete(c.Context(), id)
if err != nil {
return err
}
return c.Status(fiber.StatusOK).JSON(fiber.Map{"message": "Campaign deleted successfully"})
}

func (h *campaignHandler) GetAllForAdmin(c *fiber.Ctx) error {
campaigns, err := h.usecase.GetAll(c.Context())
if err != nil {
return err
}
return c.Status(fiber.StatusOK).JSON(campaigns)
}

func (h *campaignHandler) GetByIDForAdmin(c *fiber.Ctx) error {
id, err := strconv.ParseInt(c.Params("id"), 10, 64)
if err != nil {
return err
}
campaign, err := h.usecase.GetByID(c.Context(), id)
if err != nil {
return err
}
return c.Status(fiber.StatusOK).JSON(campaign)
}
9 changes: 9 additions & 0 deletions internal/model/campaign.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package model

import "mime/multipart"

type Campaign struct {
ID int64 `db:"ID" json:"id,omitempty"`
Picture string `db:"Picture" json:"picture"`
Expand All @@ -9,3 +11,10 @@ type Campaign struct {
Submitted bool `db:"Submitted" json:"submitted"`
Submission string `db:"Submission" json:"submission,omitempty"`
}

type CampaignRequest struct {
Picture *multipart.FileHeader `form:"picture" validate:"required"`
Title string `form:"title" validate:"required"`
Description string `form:"description" validate:"required"`
Reward int `form:"reward" validate:"required"`
}
69 changes: 66 additions & 3 deletions internal/repository/campaign.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package repository
import (
"context"

"github.com/gofiber/fiber/v2"
"github.com/jmoiron/sqlx"
"github.com/mirzahilmi/hackathon/internal/model"
)
Expand All @@ -21,8 +22,13 @@ func NewCampaignRepository(db *sqlx.DB) CampaignRepositoryItf {

type CampaignQueryerItf interface {
txCompat
GetAll(ctx context.Context, userID int64) ([]model.Campaign, error)
GetAllByUserID(ctx context.Context, userID int64) ([]model.Campaign, error)
GetWithSubmission(ctx context.Context, id, userID int64) (model.Campaign, error)
Create(ctx context.Context, campaign model.Campaign) error
Update(ctx context.Context, campaign model.Campaign) error
Delete(ctx context.Context, id int64) error
GetByID(ctx context.Context, id int64) (model.Campaign, error)
GetAll(ctx context.Context) ([]model.Campaign, error)
}

type campaignQueryer struct {
Expand Down Expand Up @@ -63,9 +69,9 @@ func (q *campaignQueryer) Ext() sqlx.ExtContext {
return q.ext
}

func (q *campaignQueryer) GetAll(ctx context.Context, userID int64) ([]model.Campaign, error) {
func (q *campaignQueryer) GetAllByUserID(ctx context.Context, userID int64) ([]model.Campaign, error) {
var campaigns []model.Campaign
if err := sqlx.SelectContext(ctx, q.ext, &campaigns, qGetAllCampaign, userID); err != nil {
if err := sqlx.SelectContext(ctx, q.ext, &campaigns, qGetAllCampaignByUserID, userID); err != nil {
return nil, err
}
return campaigns, nil
Expand All @@ -78,3 +84,60 @@ func (q *campaignQueryer) GetWithSubmission(ctx context.Context, id, userID int6
}
return campaign, nil
}

func (q *campaignQueryer) Create(ctx context.Context, campaign model.Campaign) error {
query, args, err := sqlx.Named(qCreateCampaign, fiber.Map{
"Picture": campaign.Picture,
"Title": campaign.Title,
"Description": campaign.Description,
"Reward": campaign.Reward,
})
if err != nil {
return err
}
_, err = q.ext.ExecContext(ctx, query, args...)
if err != nil {
return err
}
return err
}

func (q *campaignQueryer) Update(ctx context.Context, campaign model.Campaign) error {
query, args, err := sqlx.Named(qUpdateCampaign, fiber.Map{
"ID": campaign.ID,
"Picture": campaign.Picture,
"Title": campaign.Title,
"Description": campaign.Description,
"Reward": campaign.Reward,
})
if err != nil {
return err
}
_, err = q.ext.ExecContext(ctx, query, args...)
return err
}

func (q *campaignQueryer) Delete(ctx context.Context, id int64) error {
_, err := q.ext.ExecContext(ctx, qDeleteCampaign, id)
if err != nil {
return err
}

return nil
}

func (q *campaignQueryer) GetByID(ctx context.Context, id int64) (model.Campaign, error) {
var campaign model.Campaign
if err := sqlx.GetContext(ctx, q.ext, &campaign, qGetCampaignByID, id); err != nil {
return model.Campaign{}, err
}
return campaign, nil
}

func (q *campaignQueryer) GetAll(ctx context.Context) ([]model.Campaign, error) {
var campaigns []model.Campaign
if err := sqlx.SelectContext(ctx, q.ext, &campaigns, qGetAllCampaign); err != nil {
return nil, err
}
return campaigns, nil
}
42 changes: 41 additions & 1 deletion internal/repository/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ const (
`

// Campaign
qGetAllCampaign = `
qGetAllCampaignByUserID = `
SELECT
Campaigns.ID,
Campaigns.Picture,
Expand All @@ -118,6 +118,46 @@ const (
WHERE Campaigns.ID = ? AND CampaignSubmissions.UserID = ?
LIMIT 1;
`
qCreateCampaign = `
INSERT INTO Campaigns
(Picture, Title, Description, Reward)
VALUE
(:Picture, :Title, :Description, :Reward);
`
qUpdateCampaign = `
UPDATE
Campaigns
SET
Picture = :Picture,
Title = :Title,
Description = :Description,
Reward = :Reward
WHERE ID = :ID;
`
qDeleteCampaign = `
DELETE FROM Campaigns
WHERE ID = ?;
`
qGetCampaignByID = `
SELECT
ID,
Picture,
Title,
Description,
Reward
FROM Campaigns
WHERE ID = ?
LIMIT 1;
`
qGetAllCampaign = `
SELECT
ID,
Picture,
Title,
Description,
Reward
FROM Campaigns
`

// Exchanges
qCreateExchange = `
Expand Down
Loading

0 comments on commit c0b70b3

Please sign in to comment.