package handler import ( "accounting-app/internal/service" "accounting-app/pkg/api" "github.com/gin-gonic/gin" ) // StreakHandler handles HTTP requests for user streaks type StreakHandler struct { streakService *service.StreakService } // NewStreakHandler creates a new StreakHandler instance func NewStreakHandler(streakService *service.StreakService) *StreakHandler { return &StreakHandler{ streakService: streakService, } } // GetStreak handles GET /api/v1/user/streak // Returns the user's current streak information func (h *StreakHandler) GetStreak(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { api.Unauthorized(c, "User not authenticated") return } // Check and reset streak if needed (in case user hasn't opened app in a while) if err := h.streakService.CheckAndResetStreak(userID.(uint)); err != nil { // Log error but don't fail the request // Just continue to get streak info } streakInfo, err := h.streakService.GetStreakInfo(userID.(uint)) if err != nil { api.InternalError(c, "Failed to get streak info: "+err.Error()) return } api.Success(c, streakInfo) } // RecalculateStreak handles POST /api/v1/user/streak/recalculate // Recalculates the streak from transaction history (admin/debug use) func (h *StreakHandler) RecalculateStreak(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { api.Unauthorized(c, "User not authenticated") return } if err := h.streakService.RecalculateStreak(userID.(uint)); err != nil { api.InternalError(c, "Failed to recalculate streak: "+err.Error()) return } streakInfo, err := h.streakService.GetStreakInfo(userID.(uint)) if err != nil { api.InternalError(c, "Failed to get streak info: "+err.Error()) return } api.Success(c, streakInfo) } // GetContributionData handles GET /api/v1/user/streak/contribution // Returns daily contribution data for heat map func (h *StreakHandler) GetContributionData(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { api.Unauthorized(c, "User not authenticated") return } contributionData, err := h.streakService.GetContributionData(userID.(uint)) if err != nil { api.InternalError(c, "Failed to get contribution data: "+err.Error()) return } api.Success(c, contributionData) } // RegisterRoutes registers streak-related routes func (h *StreakHandler) RegisterRoutes(rg *gin.RouterGroup) { rg.GET("/user/streak", h.GetStreak) rg.POST("/user/streak/recalculate", h.RecalculateStreak) rg.GET("/user/streak/contribution", h.GetContributionData) }