package handler import ( "errors" "net/http" "github.com/gin-gonic/gin" "dating-app/internal/dto" "dating-app/internal/models" "dating-app/internal/repository" "dating-app/internal/service" "dating-app/internal/utils" ) type OnboardingHandler struct { onboardingService *service.OnboardingService } func NewOnboardingHandler(onboardingService *service.OnboardingService) *OnboardingHandler { return &OnboardingHandler{onboardingService: onboardingService} } func (h *OnboardingHandler) handleStepError(c *gin.Context, err error) { switch { case errors.Is(err, service.ErrStepOutOfOrder): utils.Fail(c, http.StatusConflict, err.Error(), nil) case errors.Is(err, service.ErrInvalidBirthDate), errors.Is(err, service.ErrOptionsNotFound), errors.Is(err, service.ErrQuestionsInvalid), errors.Is(err, service.ErrDuplicateQuestion): utils.Fail(c, http.StatusBadRequest, err.Error(), nil) case errors.Is(err, repository.ErrCategoryNotFound): utils.Fail(c, http.StatusInternalServerError, "دسته‌ی موردنیاز در سیستم تعریف نشده است", nil) case errors.Is(err, service.ErrSelectionCount): utils.Fail(c, http.StatusBadRequest, err.Error(), nil) default: utils.Fail(c, http.StatusBadRequest, err.Error(), nil) } } // Status GET /onboarding/status func (h *OnboardingHandler) Status(c *gin.Context) { user, ok := currentUser(c) if !ok { return } utils.Success(c, http.StatusOK, "", h.onboardingService.GetStatus(user)) } // BasicInfo POST /onboarding/basic-info func (h *OnboardingHandler) BasicInfo(c *gin.Context) { user, ok := currentUser(c) if !ok { return } var req dto.BasicInfoRequest if err := c.ShouldBindJSON(&req); err != nil { utils.Fail(c, http.StatusBadRequest, "ورودی نامعتبر است", err.Error()) return } if err := h.onboardingService.SetBasicInfo(user, req); err != nil { h.handleStepError(c, err) return } utils.Success(c, http.StatusOK, "اطلاعات پایه ثبت شد", h.onboardingService.GetStatus(user)) } // BodyInfo POST /onboarding/body-info func (h *OnboardingHandler) BodyInfo(c *gin.Context) { user, ok := currentUser(c) if !ok { return } var req dto.BodyInfoRequest if err := c.ShouldBindJSON(&req); err != nil { utils.Fail(c, http.StatusBadRequest, "ورودی نامعتبر است", err.Error()) return } if err := h.onboardingService.SetBodyInfo(user, req); err != nil { h.handleStepError(c, err) return } utils.Success(c, http.StatusOK, "قد و وزن ثبت شد", h.onboardingService.GetStatus(user)) } // AvailableQuestions GET /onboarding/profile-questions func (h *OnboardingHandler) AvailableQuestions(c *gin.Context) { questions, err := h.onboardingService.GetAvailableQuestions() if err != nil { utils.Fail(c, http.StatusInternalServerError, "خطا در دریافت سوالات", nil) return } utils.Success(c, http.StatusOK, "", questions) } // SetProfileQuestions POST /onboarding/profile-questions func (h *OnboardingHandler) SetProfileQuestions(c *gin.Context) { user, ok := currentUser(c) if !ok { return } var req dto.ProfileQuestionsRequest if err := c.ShouldBindJSON(&req); err != nil { utils.Fail(c, http.StatusBadRequest, "ورودی نامعتبر است (باید دقیقاً ۳ سوال با پاسخ ارسال شود)", err.Error()) return } if err := h.onboardingService.SetProfileQuestions(user, req); err != nil { h.handleStepError(c, err) return } utils.Success(c, http.StatusOK, "پاسخ‌ها ثبت شد", h.onboardingService.GetStatus(user)) } // Education POST /onboarding/education func (h *OnboardingHandler) Education(c *gin.Context) { user, ok := currentUser(c) if !ok { return } var req dto.EducationRequest if err := c.ShouldBindJSON(&req); err != nil { utils.Fail(c, http.StatusBadRequest, "ورودی نامعتبر است", err.Error()) return } if err := h.onboardingService.SetEducation(user, req); err != nil { h.handleStepError(c, err) return } utils.Success(c, http.StatusOK, "اطلاعات تحصیلی ثبت شد", h.onboardingService.GetStatus(user)) } // Occupations POST /onboarding/occupations func (h *OnboardingHandler) Occupations(c *gin.Context) { user, ok := currentUser(c) if !ok { return } var req dto.OptionSelectionRequest if err := c.ShouldBindJSON(&req); err != nil { utils.Fail(c, http.StatusBadRequest, "ورودی نامعتبر است", err.Error()) return } if err := h.onboardingService.SetOccupations(user, req.OptionIDs); err != nil { h.handleStepError(c, err) return } utils.Success(c, http.StatusOK, "فعالیت‌ها ثبت شد", h.onboardingService.GetStatus(user)) } // RelationshipImportance POST /onboarding/relationship-importance func (h *OnboardingHandler) RelationshipImportance(c *gin.Context) { user, ok := currentUser(c) if !ok { return } var req dto.OptionSelectionRequest if err := c.ShouldBindJSON(&req); err != nil { utils.Fail(c, http.StatusBadRequest, "ورودی نامعتبر است", err.Error()) return } if err := h.onboardingService.SetRelationshipImportance(user, req.OptionIDs); err != nil { h.handleStepError(c, err) return } utils.Success(c, http.StatusOK, "موارد مهم در رابطه ثبت شد", h.onboardingService.GetStatus(user)) } // Interests POST /onboarding/interests func (h *OnboardingHandler) Interests(c *gin.Context) { user, ok := currentUser(c) if !ok { return } var req dto.OptionSelectionRequest if err := c.ShouldBindJSON(&req); err != nil { utils.Fail(c, http.StatusBadRequest, "ورودی نامعتبر است", err.Error()) return } if err := h.onboardingService.SetInterests(user, req.OptionIDs); err != nil { h.handleStepError(c, err) return } utils.Success(c, http.StatusOK, "علاقه‌مندی‌ها ثبت شد", h.onboardingService.GetStatus(user)) } // LookingFor POST /onboarding/looking-for func (h *OnboardingHandler) LookingFor(c *gin.Context) { user, ok := currentUser(c) if !ok { return } var req dto.OptionSelectionRequest if err := c.ShouldBindJSON(&req); err != nil { utils.Fail(c, http.StatusBadRequest, "ورودی نامعتبر است", err.Error()) return } if err := h.onboardingService.SetLookingFor(user, req.OptionIDs); err != nil { h.handleStepError(c, err) return } utils.Success(c, http.StatusOK, "هدف شما ثبت شد", h.onboardingService.GetStatus(user)) } // Options GET /onboarding/options/:category // category یکی از: education_level, field_of_study, occupation, // important_in_relationship, interest, looking_for func (h *OnboardingHandler) Options(c *gin.Context) { key := models.CategoryKey(c.Param("category")) valid := false for _, k := range models.AllCategoryKeys { if k == key { valid = true break } } if !valid { utils.Fail(c, http.StatusNotFound, "دسته‌ی نامعتبر است", nil) return } options, err := h.onboardingService.GetActiveOptions(key) if err != nil { utils.Fail(c, http.StatusInternalServerError, "خطا در دریافت گزینه‌ها", nil) return } utils.Success(c, http.StatusOK, "", options) }