Spaces:
Runtime error
Runtime error
| 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"}) | |
| } | |