228 lines
6.5 KiB
Go
228 lines
6.5 KiB
Go
package handlers
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/inchstep/server/internal/middleware"
|
|
"github.com/inchstep/server/internal/models"
|
|
"github.com/inchstep/server/internal/services"
|
|
)
|
|
|
|
type CheckInHandler struct {
|
|
checkinSvc *services.CheckInService
|
|
pointsSvc *services.PointsService
|
|
}
|
|
|
|
func NewCheckInHandler(cs *services.CheckInService, ps *services.PointsService) *CheckInHandler {
|
|
return &CheckInHandler{checkinSvc: cs, pointsSvc: ps}
|
|
}
|
|
|
|
// ---------- 打卡项 ----------
|
|
|
|
func (h *CheckInHandler) CreateItem(c *gin.Context) {
|
|
userID := middleware.GetUserID(c)
|
|
var item models.CheckInItem
|
|
if err := c.ShouldBindJSON(&item); err != nil {
|
|
middleware.Error(c, http.StatusBadRequest, 400, "参数格式错误")
|
|
return
|
|
}
|
|
if item.Name == "" {
|
|
middleware.Error(c, http.StatusBadRequest, 400, "打卡项名称不能为空")
|
|
return
|
|
}
|
|
if err := h.checkinSvc.CreateItem(userID, &item); err != nil {
|
|
middleware.Error(c, http.StatusInternalServerError, 500, err.Error())
|
|
return
|
|
}
|
|
middleware.Success(c, item)
|
|
}
|
|
|
|
func (h *CheckInHandler) ListItems(c *gin.Context) {
|
|
userID := middleware.GetUserID(c)
|
|
items, err := h.checkinSvc.GetUserItems(userID)
|
|
if err != nil {
|
|
middleware.Error(c, http.StatusInternalServerError, 500, err.Error())
|
|
return
|
|
}
|
|
middleware.Success(c, items)
|
|
}
|
|
|
|
func (h *CheckInHandler) GetItem(c *gin.Context) {
|
|
userID := middleware.GetUserID(c)
|
|
id := c.Param("id")
|
|
item, err := h.checkinSvc.GetItemByID(id, userID)
|
|
if err != nil {
|
|
middleware.Error(c, http.StatusNotFound, 404, "打卡项不存在")
|
|
return
|
|
}
|
|
middleware.Success(c, item)
|
|
}
|
|
|
|
func (h *CheckInHandler) UpdateItem(c *gin.Context) {
|
|
userID := middleware.GetUserID(c)
|
|
id := c.Param("id")
|
|
var updates map[string]interface{}
|
|
if err := c.ShouldBindJSON(&updates); err != nil {
|
|
middleware.Error(c, http.StatusBadRequest, 400, "参数格式错误")
|
|
return
|
|
}
|
|
item, err := h.checkinSvc.UpdateItem(id, userID, updates)
|
|
if err != nil {
|
|
middleware.Error(c, http.StatusInternalServerError, 500, err.Error())
|
|
return
|
|
}
|
|
middleware.Success(c, item)
|
|
}
|
|
|
|
func (h *CheckInHandler) DeleteItem(c *gin.Context) {
|
|
userID := middleware.GetUserID(c)
|
|
id := c.Param("id")
|
|
if err := h.checkinSvc.DeleteItem(id, userID); err != nil {
|
|
middleware.Error(c, http.StatusInternalServerError, 500, err.Error())
|
|
return
|
|
}
|
|
middleware.Success(c, nil)
|
|
}
|
|
|
|
func (h *CheckInHandler) PauseItem(c *gin.Context) {
|
|
userID := middleware.GetUserID(c)
|
|
id := c.Param("id")
|
|
if err := h.checkinSvc.PauseItem(id, userID); err != nil {
|
|
middleware.Error(c, http.StatusInternalServerError, 500, err.Error())
|
|
return
|
|
}
|
|
middleware.Success(c, nil)
|
|
}
|
|
|
|
func (h *CheckInHandler) ResumeItem(c *gin.Context) {
|
|
userID := middleware.GetUserID(c)
|
|
id := c.Param("id")
|
|
if err := h.checkinSvc.ResumeItem(id, userID); err != nil {
|
|
middleware.Error(c, http.StatusInternalServerError, 500, err.Error())
|
|
return
|
|
}
|
|
middleware.Success(c, nil)
|
|
}
|
|
|
|
// ---------- 打卡记录 ----------
|
|
|
|
type createRecordReq struct {
|
|
ItemID string `json:"itemId" binding:"required"`
|
|
CheckDate string `json:"checkDate"`
|
|
Note *string `json:"note,omitempty"`
|
|
Images *string `json:"images,omitempty"`
|
|
}
|
|
|
|
func (h *CheckInHandler) CreateRecord(c *gin.Context) {
|
|
userID := middleware.GetUserID(c)
|
|
var req createRecordReq
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
middleware.Error(c, http.StatusBadRequest, 400, "参数格式错误")
|
|
return
|
|
}
|
|
|
|
checkDate := time.Now()
|
|
if req.CheckDate != "" {
|
|
if parsed, err := time.Parse("2006-01-02", req.CheckDate); err == nil {
|
|
checkDate = parsed
|
|
}
|
|
}
|
|
|
|
record, err := h.checkinSvc.CreateRecord(userID, req.ItemID, checkDate, req.Note, req.Images)
|
|
if err != nil {
|
|
middleware.Error(c, http.StatusBadRequest, 400, err.Error())
|
|
return
|
|
}
|
|
|
|
// 发放打卡积分
|
|
h.pointsSvc.AwardCheckIn(userID)
|
|
|
|
middleware.Success(c, record)
|
|
}
|
|
|
|
type makeupRecordReq struct {
|
|
ItemID string `json:"itemId" binding:"required"`
|
|
CheckDate string `json:"checkDate" binding:"required"`
|
|
}
|
|
|
|
func (h *CheckInHandler) MakeupRecord(c *gin.Context) {
|
|
userID := middleware.GetUserID(c)
|
|
var req makeupRecordReq
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
middleware.Error(c, http.StatusBadRequest, 400, "参数格式错误")
|
|
return
|
|
}
|
|
|
|
checkDate, err := time.Parse("2006-01-02", req.CheckDate)
|
|
if err != nil {
|
|
middleware.Error(c, http.StatusBadRequest, 400, "日期格式错误,请使用 YYYY-MM-DD")
|
|
return
|
|
}
|
|
|
|
record, err := h.checkinSvc.MakeupRecord(userID, req.ItemID, checkDate, 5)
|
|
if err != nil {
|
|
middleware.Error(c, http.StatusBadRequest, 400, err.Error())
|
|
return
|
|
}
|
|
middleware.Success(c, record)
|
|
}
|
|
|
|
func (h *CheckInHandler) GetRecords(c *gin.Context) {
|
|
userID := middleware.GetUserID(c)
|
|
itemID := c.Query("itemId")
|
|
|
|
startStr := c.DefaultQuery("start", time.Now().AddDate(0, -1, 0).Format("2006-01-02"))
|
|
endStr := c.DefaultQuery("end", time.Now().Format("2006-01-02"))
|
|
|
|
start, _ := time.Parse("2006-01-02", startStr)
|
|
end, _ := time.Parse("2006-01-02", endStr)
|
|
end = end.Add(24 * time.Hour)
|
|
|
|
records, err := h.checkinSvc.GetRecords(userID, itemID, start, end)
|
|
if err != nil {
|
|
middleware.Error(c, http.StatusInternalServerError, 500, err.Error())
|
|
return
|
|
}
|
|
middleware.Success(c, records)
|
|
}
|
|
|
|
func (h *CheckInHandler) GetStreak(c *gin.Context) {
|
|
userID := middleware.GetUserID(c)
|
|
itemID := c.Param("id")
|
|
streak, err := h.checkinSvc.GetStreak(itemID, userID)
|
|
if err != nil {
|
|
middleware.Error(c, http.StatusInternalServerError, 500, err.Error())
|
|
return
|
|
}
|
|
middleware.Success(c, gin.H{"itemId": itemID, "streak": streak})
|
|
}
|
|
|
|
func (h *CheckInHandler) GetMonthlyStats(c *gin.Context) {
|
|
userID := middleware.GetUserID(c)
|
|
yearStr := c.DefaultQuery("year", strconv.Itoa(time.Now().Year()))
|
|
monthStr := c.DefaultQuery("month", strconv.Itoa(int(time.Now().Month())))
|
|
|
|
year, _ := strconv.Atoi(yearStr)
|
|
month, _ := strconv.Atoi(monthStr)
|
|
|
|
stats, err := h.checkinSvc.GetMonthlyStats(userID, year, month)
|
|
if err != nil {
|
|
middleware.Error(c, http.StatusInternalServerError, 500, err.Error())
|
|
return
|
|
}
|
|
middleware.Success(c, stats)
|
|
}
|
|
|
|
|
|
func (h *CheckInHandler) GetTodayStatus(c *gin.Context) {
|
|
userID := middleware.GetUserID(c)
|
|
status, err := h.checkinSvc.GetTodayStatus(userID)
|
|
if err != nil {
|
|
middleware.Error(c, http.StatusInternalServerError, 500, err.Error())
|
|
return
|
|
}
|
|
middleware.Success(c, status)
|
|
} |