102 lines
2.7 KiB
Go
102 lines
2.7 KiB
Go
|
|
package handler
|
||
|
|
|
||
|
|
import (
|
||
|
|
"errors"
|
||
|
|
"net/http"
|
||
|
|
"strconv"
|
||
|
|
|
||
|
|
"github.com/gin-gonic/gin"
|
||
|
|
|
||
|
|
"dating-app/internal/dto"
|
||
|
|
"dating-app/internal/models"
|
||
|
|
"dating-app/internal/service"
|
||
|
|
"dating-app/internal/utils"
|
||
|
|
)
|
||
|
|
|
||
|
|
type DiscoveryHandler struct {
|
||
|
|
discoveryService *service.DiscoveryService
|
||
|
|
}
|
||
|
|
|
||
|
|
func NewDiscoveryHandler(discoveryService *service.DiscoveryService) *DiscoveryHandler {
|
||
|
|
return &DiscoveryHandler{discoveryService: discoveryService}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Feed GET /discover?max_distance_km=&min_age=&max_age=
|
||
|
|
func (h *DiscoveryHandler) Feed(c *gin.Context) {
|
||
|
|
user, ok := currentUser(c)
|
||
|
|
if !ok {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
var maxDistance *float64
|
||
|
|
if raw := c.Query("max_distance_km"); raw != "" {
|
||
|
|
if v, err := strconv.ParseFloat(raw, 64); err == nil {
|
||
|
|
maxDistance = &v
|
||
|
|
}
|
||
|
|
}
|
||
|
|
minAge, _ := strconv.Atoi(c.Query("min_age"))
|
||
|
|
maxAge, _ := strconv.Atoi(c.Query("max_age"))
|
||
|
|
|
||
|
|
candidates, err := h.discoveryService.GetFeed(user, maxDistance, minAge, maxAge)
|
||
|
|
if err != nil {
|
||
|
|
h.handleError(c, err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
utils.Success(c, http.StatusOK, "", candidates)
|
||
|
|
}
|
||
|
|
|
||
|
|
// CandidateDetail GET /discover/:id
|
||
|
|
func (h *DiscoveryHandler) CandidateDetail(c *gin.Context) {
|
||
|
|
user, ok := currentUser(c)
|
||
|
|
if !ok {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
targetID, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
||
|
|
if err != nil {
|
||
|
|
utils.Fail(c, http.StatusBadRequest, "شناسه نامعتبر است", nil)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
detail, err := h.discoveryService.GetCandidateDetail(user, uint(targetID))
|
||
|
|
if err != nil {
|
||
|
|
utils.Fail(c, http.StatusNotFound, "پروفایل یافت نشد", nil)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
utils.Success(c, http.StatusOK, "", detail)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Swipe POST /discover/:id/swipe body: {action: "like"|"pass"|"superlike"}
|
||
|
|
func (h *DiscoveryHandler) Swipe(c *gin.Context) {
|
||
|
|
user, ok := currentUser(c)
|
||
|
|
if !ok {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
targetID, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
||
|
|
if err != nil {
|
||
|
|
utils.Fail(c, http.StatusBadRequest, "شناسه نامعتبر است", nil)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
var req dto.SwipeRequest
|
||
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||
|
|
utils.Fail(c, http.StatusBadRequest, "ورودی نامعتبر است", err.Error())
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
result, err := h.discoveryService.Swipe(user, uint(targetID), models.SwipeAction(req.Action))
|
||
|
|
if err != nil {
|
||
|
|
h.handleError(c, err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
utils.Success(c, http.StatusOK, "", result)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (h *DiscoveryHandler) handleError(c *gin.Context, err error) {
|
||
|
|
switch {
|
||
|
|
case errors.Is(err, service.ErrGenderNotSet):
|
||
|
|
utils.Fail(c, http.StatusConflict, err.Error(), nil)
|
||
|
|
case errors.Is(err, service.ErrCannotSwipeSelf), errors.Is(err, service.ErrAlreadySwiped):
|
||
|
|
utils.Fail(c, http.StatusBadRequest, err.Error(), nil)
|
||
|
|
default:
|
||
|
|
utils.Fail(c, http.StatusInternalServerError, "خطای داخلی سرور", nil)
|
||
|
|
}
|
||
|
|
}
|