256 lines
7.8 KiB
Go
256 lines
7.8 KiB
Go
package handlers
|
|
|
|
import (
|
|
"Yimaru-Backend/internal/domain"
|
|
"Yimaru-Backend/internal/services/examprep"
|
|
"errors"
|
|
"strconv"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
)
|
|
|
|
// CreateExamPrepLesson godoc
|
|
// @Summary Create exam-prep lesson (under a unit module)
|
|
// @Tags exam-prep
|
|
// @Param moduleId path int true "Exam prep unit module ID"
|
|
// @Param body body domain.CreateExamPrepLessonInput true "Lesson"
|
|
// @Router /api/v1/exam-prep/modules/{moduleId}/lessons [post]
|
|
func (h *Handler) CreateExamPrepLesson(c *fiber.Ctx) error {
|
|
moduleID, err := strconv.ParseInt(c.Params("moduleId"), 10, 64)
|
|
if err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "Invalid module id",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
var req domain.CreateExamPrepLessonInput
|
|
if err := c.BodyParser(&req); err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "Invalid request body",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
if valErrs, ok := h.validator.Validate(c, req); !ok {
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "Validation failed",
|
|
Error: firstValidationError(valErrs),
|
|
})
|
|
}
|
|
les, err := h.examPrepSvc.CreateLesson(c.Context(), moduleID, req)
|
|
if err != nil {
|
|
if errors.Is(err, examprep.ErrModuleNotFound) {
|
|
return c.Status(fiber.StatusNotFound).JSON(domain.ErrorResponse{
|
|
Message: "Module not found",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
|
Message: "Failed to create lesson",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
return c.Status(fiber.StatusCreated).JSON(domain.Response{
|
|
Message: "Lesson created successfully",
|
|
Data: les,
|
|
Success: true,
|
|
StatusCode: fiber.StatusCreated,
|
|
})
|
|
}
|
|
|
|
// ListExamPrepLessonsByUnitModule godoc
|
|
// @Summary List exam-prep lessons for a unit module
|
|
// @Tags exam-prep
|
|
// @Param moduleId path int true "Exam prep unit module ID"
|
|
// @Param limit query int false "Page size" default(20)
|
|
// @Param offset query int false "Offset" default(0)
|
|
// @Router /api/v1/exam-prep/modules/{moduleId}/lessons [get]
|
|
func (h *Handler) ListExamPrepLessonsByUnitModule(c *fiber.Ctx) error {
|
|
moduleID, err := strconv.ParseInt(c.Params("moduleId"), 10, 64)
|
|
if err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "Invalid module id",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
limit, _ := strconv.Atoi(c.Query("limit", "20"))
|
|
offset, _ := strconv.Atoi(c.Query("offset", "0"))
|
|
items, total, err := h.examPrepSvc.ListLessonsByUnitModule(c.Context(), moduleID, int32(limit), int32(offset))
|
|
if err != nil {
|
|
if errors.Is(err, examprep.ErrModuleNotFound) {
|
|
return c.Status(fiber.StatusNotFound).JSON(domain.ErrorResponse{
|
|
Message: "Module not found",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
|
Message: "Failed to list lessons",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
return c.JSON(domain.Response{
|
|
Message: "Lessons retrieved successfully",
|
|
Data: fiber.Map{
|
|
"lessons": items,
|
|
"total_count": total,
|
|
"limit": limit,
|
|
"offset": offset,
|
|
},
|
|
Success: true,
|
|
StatusCode: fiber.StatusOK,
|
|
})
|
|
}
|
|
|
|
// ReorderExamPrepLessonsInUnitModule godoc
|
|
// @Summary Reorder lessons within an exam-prep unit module
|
|
// @Tags exam-prep
|
|
// @Router /api/v1/exam-prep/modules/{moduleId}/lessons/reorder [put]
|
|
func (h *Handler) ReorderExamPrepLessonsInUnitModule(c *fiber.Ctx) error {
|
|
moduleID, err := strconv.ParseInt(c.Params("moduleId"), 10, 64)
|
|
if err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "Invalid module id",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
var req domain.ReorderIDsRequest
|
|
if err := c.BodyParser(&req); err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "Invalid request body",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
if req.OrderedIDs == nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "ordered_ids is required (use an empty array if there are no lessons)",
|
|
Error: "missing ordered_ids",
|
|
})
|
|
}
|
|
if err := h.examPrepSvc.ReorderLessonsInUnitModule(c.Context(), moduleID, req.OrderedIDs); err != nil {
|
|
if errors.Is(err, examprep.ErrModuleNotFound) {
|
|
return c.Status(fiber.StatusNotFound).JSON(domain.ErrorResponse{
|
|
Message: "Module not found",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
if errors.Is(err, domain.ErrReorderInvalidIDSet) {
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: err.Error(),
|
|
Error: "INVALID_REORDER",
|
|
})
|
|
}
|
|
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
|
Message: "Failed to reorder lessons",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
return c.JSON(domain.Response{
|
|
Message: "Lessons reordered successfully",
|
|
Success: true,
|
|
StatusCode: fiber.StatusOK,
|
|
})
|
|
}
|
|
|
|
// GetExamPrepLessonByID godoc
|
|
// @Summary Get exam-prep lesson by ID
|
|
// @Tags exam-prep
|
|
// @Router /api/v1/exam-prep/lessons/{id} [get]
|
|
func (h *Handler) GetExamPrepLessonByID(c *fiber.Ctx) error {
|
|
id, err := strconv.ParseInt(c.Params("id"), 10, 64)
|
|
if err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "Invalid lesson id",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
les, err := h.examPrepSvc.GetLessonByID(c.Context(), id)
|
|
if err != nil {
|
|
if errors.Is(err, examprep.ErrLessonNotFound) {
|
|
return c.Status(fiber.StatusNotFound).JSON(domain.ErrorResponse{
|
|
Message: "Lesson not found",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
|
Message: "Failed to get lesson",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
return c.JSON(domain.Response{
|
|
Message: "Lesson retrieved successfully",
|
|
Data: les,
|
|
Success: true,
|
|
StatusCode: fiber.StatusOK,
|
|
})
|
|
}
|
|
|
|
// UpdateExamPrepLesson godoc
|
|
// @Summary Update exam-prep lesson
|
|
// @Tags exam-prep
|
|
// @Router /api/v1/exam-prep/lessons/{id} [put]
|
|
func (h *Handler) UpdateExamPrepLesson(c *fiber.Ctx) error {
|
|
id, err := strconv.ParseInt(c.Params("id"), 10, 64)
|
|
if err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "Invalid lesson id",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
var req domain.UpdateExamPrepLessonInput
|
|
if err := c.BodyParser(&req); err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "Invalid request body",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
les, err := h.examPrepSvc.UpdateLesson(c.Context(), id, req)
|
|
if err != nil {
|
|
if errors.Is(err, examprep.ErrLessonNotFound) {
|
|
return c.Status(fiber.StatusNotFound).JSON(domain.ErrorResponse{
|
|
Message: "Lesson not found",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
|
Message: "Failed to update lesson",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
return c.JSON(domain.Response{
|
|
Message: "Lesson updated successfully",
|
|
Data: les,
|
|
Success: true,
|
|
StatusCode: fiber.StatusOK,
|
|
})
|
|
}
|
|
|
|
// DeleteExamPrepLesson godoc
|
|
// @Summary Delete exam-prep lesson
|
|
// @Tags exam-prep
|
|
// @Router /api/v1/exam-prep/lessons/{id} [delete]
|
|
func (h *Handler) DeleteExamPrepLesson(c *fiber.Ctx) error {
|
|
id, err := strconv.ParseInt(c.Params("id"), 10, 64)
|
|
if err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "Invalid lesson id",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
if err := h.examPrepSvc.DeleteLesson(c.Context(), id); err != nil {
|
|
if errors.Is(err, examprep.ErrLessonNotFound) {
|
|
return c.Status(fiber.StatusNotFound).JSON(domain.ErrorResponse{
|
|
Message: "Lesson not found",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
|
Message: "Failed to delete lesson",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
return c.JSON(domain.Response{
|
|
Message: "Lesson deleted successfully",
|
|
Success: true,
|
|
StatusCode: fiber.StatusOK,
|
|
})
|
|
}
|