Yimaru-BackEnd/internal/web_server/handlers/initial_assessment.go

143 lines
4.3 KiB
Go

package handlers
import (
"Yimaru-Backend/internal/domain"
"Yimaru-Backend/internal/services/authentication"
"errors"
"strconv"
"github.com/gofiber/fiber/v2"
)
// CreateAssessmentQuestion godoc
// @Summary Create assessment question
// @Description Creates a new question for the initial knowledge assessment
// @Tags assessment
// @Accept json
// @Produce json
// @Param question body domain.AssessmentQuestion true "Assessment question payload"
// @Success 201 {object} domain.Response{data=domain.AssessmentQuestion}
// @Failure 400 {object} domain.ErrorResponse
// @Failure 500 {object} domain.ErrorResponse
// @Router /api/v1/assessment/questions [post]
func (h *Handler) CreateAssessmentQuestion(c *fiber.Ctx) error {
var req domain.AssessmentQuestion
if err := c.BodyParser(&req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
Message: "Invalid request body",
Error: err.Error(),
})
}
question, err := h.assessmentSvc.CreateAssessmentQuestion(c.Context(), req)
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
Message: "Failed to create assessment question",
Error: err.Error(),
})
}
return c.Status(fiber.StatusCreated).JSON(domain.Response{
Message: "Assessment question created successfully",
Data: question,
})
}
// GetActiveAssessmentQuestions godoc
// @Summary Get active initial assessment questions
// @Description Returns all active questions used for initial knowledge assessment
// @Tags assessment
// @Accept json
// @Produce json
// @Success 200 {object} domain.Response{data=[]domain.AssessmentQuestion}
// @Failure 500 {object} domain.ErrorResponse
// @Router /api/v1/assessment/questions [get]
func (h *Handler) GetActiveAssessmentQuestions(c *fiber.Ctx) error {
questions, err := h.assessmentSvc.GetActiveAssessmentQuestions(c.Context())
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
Message: "Failed to fetch assessment questions",
Error: err.Error(),
})
}
return c.Status(fiber.StatusOK).JSON(domain.Response{
Message: "Assessment questions fetched successfully",
Data: questions,
})
}
// SubmitAssessment godoc
// @Summary Submit initial knowledge assessment
// @Description Evaluates user responses, calculates knowledge level, updates user profile, and sends notification
// @Tags assessment
// @Accept json
// @Produce json
// @Param user_id path int true "User ID"
// @Param payload body domain.SubmitAssessmentReq true "Assessment responses"
// @Success 200 {object} domain.Response
// @Failure 400 {object} domain.ErrorResponse
// @Failure 404 {object} domain.ErrorResponse
// @Failure 500 {object} domain.ErrorResponse
// @Router /api/v1/{tenant_slug}/assessment/submit [post]
func (h *Handler) SubmitAssessment(c *fiber.Ctx) error {
// User ID (from auth context or path, depending on your setup)
userIDStr, ok := c.Locals("user_id").(string)
if !ok || userIDStr == "" {
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
Message: "Invalid user context",
Error: "User ID not found in request context",
})
}
userID, err := strconv.ParseInt(userIDStr, 10, 64)
if err != nil || userID <= 0 {
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
Message: "Invalid user ID",
Error: "User ID must be a positive integer",
})
}
// Parse request body
var req domain.SubmitAssessmentReq
if err := c.BodyParser(&req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
Message: "Invalid request body",
Error: err.Error(),
})
}
if len(req.Answers) == 0 {
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
Message: "No answers submitted",
Error: "Assessment answers cannot be empty",
})
}
// Submit assessment
attempt, err := h.assessmentSvc.SubmitAssessment(
c.Context(),
userID,
req.Answers,
)
if err != nil {
if errors.Is(err, authentication.ErrUserNotFound) {
return c.Status(fiber.StatusNotFound).JSON(domain.ErrorResponse{
Message: "User not found",
Error: err.Error(),
})
}
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
Message: "Failed to submit assessment",
Error: err.Error(),
})
}
return c.Status(fiber.StatusOK).JSON(domain.Response{
Message: "Assessment submitted successfully",
Data: attempt,
})
}