package handler import ( "net/http" "datarush/internal/gw/domain" "datarush/internal/gw/grpc_client" "datarush/internal/gw/utils" reviewpb "datarush/pkg/api/review" ) type ReviewHandler struct { reviewClient *grpc_client.ReviewClient } func NewReviewHandler(reviewClient *grpc_client.ReviewClient) *ReviewHandler { return &ReviewHandler{reviewClient: reviewClient} } func (h *ReviewHandler) ListSubmissionsForReview(w http.ResponseWriter, r *http.Request) { token := getPathParam(r, "token") pageSize := getQueryParamInt32(r, "page_size", 20) pageToken := getQueryParamInt32(r, "page_token", 0) statusStr := getQueryParam(r, "status") req := &reviewpb.ListSubmissionsForReviewRequest{ Token: token, PageSize: pageSize, PageToken: pageToken, } if statusStr != "" { status := stringToReviewStatus(statusStr) req.Status = &status } resp, err := h.reviewClient.ListSubmissionsForReview(r.Context(), req) if err != nil { utils.RespondError(w, domain.NewUnauthorizedError("invalid review token")) return } submissions := make([]domain.SubmissionSummaryResponse, len(resp.Submissions)) for i, sub := range resp.Submissions { submissions[i] = *utils.SubmissionSummaryProtoToHTTP(sub) } utils.RespondJSON(w, http.StatusOK, &domain.ListSubmissionsForReviewResponse{ TotalCount: resp.TotalCount, NextPageToken: resp.NextPageToken, Submissions: submissions, }) } func (h *ReviewHandler) GetSubmissionForReview(w http.ResponseWriter, r *http.Request) { token := getPathParam(r, "token") submissionID := getPathParam(r, "submission_id") submission, err := h.reviewClient.GetSubmissionForReview(r.Context(), token, submissionID) if err != nil { utils.RespondError(w, domain.NewNotFoundError("submission not found")) return } utils.RespondJSON(w, http.StatusOK, utils.SubmissionForReviewProtoToHTTP(submission)) } func (h *ReviewHandler) EvaluateSubmission(w http.ResponseWriter, r *http.Request) { token := getPathParam(r, "token") submissionID := getPathParam(r, "submission_id") var reqBody domain.EvaluateSubmissionRequest if err := utils.DecodeJSON(r, &reqBody); err != nil { utils.RespondError(w, err) return } marks := make([]*reviewpb.CriteriaMark, len(reqBody.Marks)) for i, m := range reqBody.Marks { marks[i] = &reviewpb.CriteriaMark{ Slug: m.Slug, Mark: m.Mark, } } req := &reviewpb.EvaluateSubmissionRequest{ Token: token, SubmissionId: submissionID, EarnedPoints: reqBody.EarnedPoints, ReviewerComment: reqBody.ReviewerComment, Marks: marks, } resp, err := h.reviewClient.EvaluateSubmission(r.Context(), req) if err != nil { utils.RespondError(w, domain.NewInternalServerError("failed to evaluate submission")) return } utils.RespondJSON(w, http.StatusOK, &domain.EvaluateSubmissionResponse{ SubmissionID: resp.SubmissionId, FinalScore: resp.FinalScore, NewStatus: utils.ReviewStatusToString(resp.NewStatus), }) } func (h *ReviewHandler) ReleaseSubmission(w http.ResponseWriter, r *http.Request) { token := getPathParam(r, "token") submissionID := getPathParam(r, "submission_id") if err := h.reviewClient.ReleaseSubmission(r.Context(), token, submissionID); err != nil { utils.RespondError(w, domain.NewInternalServerError("failed to release submission")) return } w.WriteHeader(http.StatusNoContent) } func stringToReviewStatus(s string) reviewpb.ReviewStatus { switch s { case "pending": return reviewpb.ReviewStatus_REVIEW_STATUS_PENDING case "in_review": return reviewpb.ReviewStatus_REVIEW_STATUS_IN_REVIEW case "completed": return reviewpb.ReviewStatus_REVIEW_STATUS_COMPLETED case "rejected": return reviewpb.ReviewStatus_REVIEW_STATUS_REJECTED default: return reviewpb.ReviewStatus_REVIEW_STATUS_UNSPECIFIED } }