DanzApp-BE-Test / controllers /event_controller.go
lifedebugger's picture
Deploy files from GitHub repository
a1d832a
package controllers
import (
"strconv"
"abdanhafidz.com/go-boilerplate/models/dto"
"abdanhafidz.com/go-boilerplate/services"
"github.com/gin-gonic/gin"
)
type EventController interface {
GetEvents(ctx *gin.Context)
GetEventDetail(ctx *gin.Context)
CreateEvent(ctx *gin.Context)
GetMyEvents(ctx *gin.Context)
UpdateEvent(ctx *gin.Context)
DeleteEvent(ctx *gin.Context)
AddEventPackage(ctx *gin.Context)
UpdateEventPackage(ctx *gin.Context)
DeleteEventPackage(ctx *gin.Context)
AddEventInstructor(ctx *gin.Context)
RemoveEventInstructor(ctx *gin.Context)
GetPendingEvents(ctx *gin.Context)
ApproveEvent(ctx *gin.Context)
RejectEvent(ctx *gin.Context)
}
type eventController struct {
eventService services.EventService
}
func NewEventController(eventService services.EventService) EventController {
return &eventController{eventService: eventService}
}
// GetEvents godoc
// @Summary List approved events
// @Description Returns a paginated list of approved events visible to members.
// @Tags Events
// @Produce json
// @Param page query int false "Page (default: 1)"
// @Param limit query int false "Limit (default: 10)"
// @Param search query string false "Search by title"
// @Success 200 {object} dto.EventListResponse
// @Security BearerAuth
// @Router /api/v1/events [get]
func (c *eventController) GetEvents(ctx *gin.Context) {
page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10"))
search := ctx.Query("search")
res, err := c.eventService.GetEvents(ctx.Request.Context(), page, limit, search)
ResponseJSON(ctx, "", res, err)
}
// GetEventDetail godoc
// @Summary Get event detail
// @Description Returns full event details for the member-facing detail page.
// @Tags Events
// @Produce json
// @Param event_id path string true "Event ID"
// @Success 200 {object} dto.EventDetailResponse
// @Failure 404 {object} dto.ErrorResponse
// @Security BearerAuth
// @Router /api/v1/events/{event_id} [get]
func (c *eventController) GetEventDetail(ctx *gin.Context) {
eventID := ctx.Param("event_id")
userID := ParseUserId(ctx)
res, err := c.eventService.GetEventDetail(ctx.Request.Context(), eventID, userID)
ResponseJSON(ctx, "", res, err)
}
// CreateEvent godoc
// @Summary Create an event
// @Description Allows an instructor (DI) to create a new event. Starts in PENDING_APPROVAL status.
// @Tags Events
// @Accept json
// @Produce json
// @Param request body dto.CreateEventRequest true "Event Data"
// @Success 201 {object} entities.Event
// @Failure 400 {object} dto.ErrorResponse
// @Failure 401 {object} dto.ErrorResponse
// @Security BearerAuth
// @Router /api/v1/events [post]
func (c *eventController) CreateEvent(ctx *gin.Context) {
userID := ParseUserId(ctx)
if userID == "" {
return
}
req, err := RequestJSON[dto.CreateEventRequest](ctx)
if err != nil {
return
}
res, err := c.eventService.CreateEvent(ctx.Request.Context(), userID, req)
if err != nil {
ResponseJSON(ctx, req, res, err)
return
}
ctx.JSON(201, gin.H{"success": true, "message": "Event created successfully. Pending approval.", "data": res})
}
// GetMyEvents godoc
// @Summary Get my events
// @Description Returns a paginated list of events created by the authenticated instructor.
// @Tags Events
// @Produce json
// @Param page query int false "Page (default: 1)"
// @Param limit query int false "Limit (default: 10)"
// @Success 200 {object} dto.EventListResponse
// @Security BearerAuth
// @Router /api/v1/events/me [get]
func (c *eventController) GetMyEvents(ctx *gin.Context) {
userID := ParseUserId(ctx)
if userID == "" {
return
}
page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10"))
res, err := c.eventService.GetMyEvents(ctx.Request.Context(), userID, page, limit)
ResponseJSON(ctx, "", res, err)
}
// UpdateEvent godoc
// @Summary Update an event
// @Description Partially update an event owned by the authenticated instructor.
// @Tags Events
// @Accept json
// @Produce json
// @Param event_id path string true "Event ID"
// @Param request body dto.UpdateEventRequest true "Fields to update"
// @Success 200 {object} entities.Event
// @Failure 400 {object} dto.ErrorResponse
// @Failure 403 {object} dto.ErrorResponse
// @Security BearerAuth
// @Router /api/v1/events/{event_id} [put]
func (c *eventController) UpdateEvent(ctx *gin.Context) {
userID := ParseUserId(ctx)
if userID == "" {
return
}
eventID := ctx.Param("event_id")
req, err := RequestJSON[dto.UpdateEventRequest](ctx)
if err != nil {
return
}
res, err := c.eventService.UpdateEvent(ctx.Request.Context(), userID, eventID, req)
if err != nil {
ResponseJSON(ctx, req, res, err)
return
}
ctx.JSON(200, gin.H{"success": true, "message": "Event updated successfully", "data": res})
}
// DeleteEvent godoc
// @Summary Delete an event
// @Description Delete an event owned by the authenticated instructor.
// @Tags Events
// @Produce json
// @Param event_id path string true "Event ID"
// @Success 200 {object} map[string]interface{}
// @Failure 403 {object} dto.ErrorResponse
// @Failure 404 {object} dto.ErrorResponse
// @Security BearerAuth
// @Router /api/v1/events/{event_id} [delete]
func (c *eventController) DeleteEvent(ctx *gin.Context) {
userID := ParseUserId(ctx)
if userID == "" {
return
}
eventID := ctx.Param("event_id")
err := c.eventService.DeleteEvent(ctx.Request.Context(), userID, eventID)
if err != nil {
ctx.JSON(400, gin.H{"success": false, "message": err.Error()})
return
}
ctx.JSON(200, gin.H{"success": true, "message": "Event deleted successfully"})
}
// AddEventPackage godoc
// @Summary Add package to event
// @Description Add a ticket package to an event. Only the event owner can do this.
// @Tags Events
// @Accept json
// @Produce json
// @Param event_id path string true "Event ID"
// @Param request body dto.CreateEventPackageRequest true "Package Data"
// @Success 201 {object} entities.EventPackage
// @Security BearerAuth
// @Router /api/v1/events/{event_id}/packages [post]
func (c *eventController) AddEventPackage(ctx *gin.Context) {
userID := ParseUserId(ctx)
if userID == "" {
return
}
eventID := ctx.Param("event_id")
req, err := RequestJSON[dto.CreateEventPackageRequest](ctx)
if err != nil {
return
}
res, err := c.eventService.AddEventPackage(ctx.Request.Context(), userID, eventID, req)
if err != nil {
ResponseJSON(ctx, req, res, err)
return
}
ctx.JSON(201, gin.H{"success": true, "message": "Package added successfully", "data": res})
}
// UpdateEventPackage godoc
// @Summary Update an event package
// @Description Partially update a ticket package. Only the event owner can do this.
// @Tags Events
// @Accept json
// @Produce json
// @Param package_id path string true "Package ID"
// @Param request body dto.UpdateEventPackageRequest true "Fields to update"
// @Success 200 {object} entities.EventPackage
// @Security BearerAuth
// @Router /api/v1/events/packages/{package_id} [put]
func (c *eventController) UpdateEventPackage(ctx *gin.Context) {
userID := ParseUserId(ctx)
if userID == "" {
return
}
packageID := ctx.Param("package_id")
req, err := RequestJSON[dto.UpdateEventPackageRequest](ctx)
if err != nil {
return
}
res, err := c.eventService.UpdateEventPackage(ctx.Request.Context(), userID, packageID, req)
if err != nil {
ResponseJSON(ctx, req, res, err)
return
}
ctx.JSON(200, gin.H{"success": true, "message": "Package updated successfully", "data": res})
}
// DeleteEventPackage godoc
// @Summary Delete an event package
// @Description Remove a ticket package from an event. Only the event owner can do this.
// @Tags Events
// @Produce json
// @Param package_id path string true "Package ID"
// @Success 200 {object} map[string]interface{}
// @Security BearerAuth
// @Router /api/v1/events/packages/{package_id} [delete]
func (c *eventController) DeleteEventPackage(ctx *gin.Context) {
userID := ParseUserId(ctx)
if userID == "" {
return
}
packageID := ctx.Param("package_id")
err := c.eventService.DeleteEventPackage(ctx.Request.Context(), userID, packageID)
if err != nil {
ctx.JSON(400, gin.H{"success": false, "message": err.Error()})
return
}
ctx.JSON(200, gin.H{"success": true, "message": "Package deleted successfully"})
}
// AddEventInstructor godoc
// @Summary Add instructor to event
// @Description Link a partner instructor to an event. Only the event owner can do this.
// @Tags Events
// @Accept json
// @Produce json
// @Param event_id path string true "Event ID"
// @Param request body dto.AddEventInstructorRequest true "Instructor Data"
// @Success 201 {object} entities.EventInstructor
// @Security BearerAuth
// @Router /api/v1/events/{event_id}/instructors [post]
func (c *eventController) AddEventInstructor(ctx *gin.Context) {
userID := ParseUserId(ctx)
if userID == "" {
return
}
eventID := ctx.Param("event_id")
req, err := RequestJSON[dto.AddEventInstructorRequest](ctx)
if err != nil {
return
}
res, err := c.eventService.AddEventInstructor(ctx.Request.Context(), userID, eventID, req)
if err != nil {
ResponseJSON(ctx, req, res, err)
return
}
ctx.JSON(201, gin.H{"success": true, "message": "Instructor added successfully", "data": res})
}
// RemoveEventInstructor godoc
// @Summary Remove instructor from event
// @Description Unlink a partner instructor from an event. Only the event owner can do this.
// @Tags Events
// @Produce json
// @Param event_id path string true "Event ID"
// @Param instructor_id path string true "Instructor ID"
// @Success 200 {object} map[string]interface{}
// @Security BearerAuth
// @Router /api/v1/events/{event_id}/instructors/{instructor_id} [delete]
func (c *eventController) RemoveEventInstructor(ctx *gin.Context) {
userID := ParseUserId(ctx)
if userID == "" {
return
}
eventID := ctx.Param("event_id")
instructorID := ctx.Param("instructor_id")
err := c.eventService.RemoveEventInstructor(ctx.Request.Context(), userID, eventID, instructorID)
if err != nil {
ctx.JSON(400, gin.H{"success": false, "message": err.Error()})
return
}
ctx.JSON(200, gin.H{"success": true, "message": "Instructor removed successfully"})
}
// GetPendingEvents godoc
// @Summary List pending events (approval queue)
// @Description Returns events awaiting approval. Accessible by admin/DI approvers.
// @Tags Events
// @Produce json
// @Param page query int false "Page (default: 1)"
// @Param limit query int false "Limit (default: 10)"
// @Success 200 {object} dto.EventListResponse
// @Security BearerAuth
// @Router /api/v1/events/pending [get]
func (c *eventController) GetPendingEvents(ctx *gin.Context) {
page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10"))
res, err := c.eventService.GetPendingEvents(ctx.Request.Context(), page, limit)
ResponseJSON(ctx, "", res, err)
}
// ApproveEvent godoc
// @Summary Approve an event
// @Description Approve a pending event so it becomes visible to members.
// @Tags Events
// @Produce json
// @Param event_id path string true "Event ID"
// @Success 200 {object} map[string]interface{}
// @Security BearerAuth
// @Router /api/v1/events/{event_id}/approve [put]
func (c *eventController) ApproveEvent(ctx *gin.Context) {
eventID := ctx.Param("event_id")
err := c.eventService.ApproveEvent(ctx.Request.Context(), eventID)
if err != nil {
ctx.JSON(400, gin.H{"success": false, "message": err.Error()})
return
}
ctx.JSON(200, gin.H{"success": true, "message": "Event approved successfully"})
}
// RejectEvent godoc
// @Summary Reject an event
// @Description Reject a pending event with an optional reason.
// @Tags Events
// @Accept json
// @Produce json
// @Param event_id path string true "Event ID"
// @Param request body dto.EventApprovalRequest false "Rejection reason"
// @Success 200 {object} map[string]interface{}
// @Security BearerAuth
// @Router /api/v1/events/{event_id}/reject [put]
func (c *eventController) RejectEvent(ctx *gin.Context) {
eventID := ctx.Param("event_id")
req, _ := RequestJSON[dto.EventApprovalRequest](ctx)
err := c.eventService.RejectEvent(ctx.Request.Context(), eventID, req.Reason)
if err != nil {
ctx.JSON(400, gin.H{"success": false, "message": err.Error()})
return
}
ctx.JSON(200, gin.H{"success": true, "message": "Event rejected"})
}