package handler import ( "net/http" "strconv" "time" "lifelog/internal/model" "lifelog/internal/service" "github.com/gin-gonic/gin" ) type Handler struct { todoSvc *service.TodoService dailyLogSvc *service.DailyLogService financeSvc *service.FinanceService } func NewHandler(todoSvc *service.TodoService, dailyLogSvc *service.DailyLogService, financeSvc *service.FinanceService) *Handler { return &Handler{todoSvc: todoSvc, dailyLogSvc: dailyLogSvc, financeSvc: financeSvc} } // Todo handlers func (h *Handler) GetTodos(c *gin.Context) { todos, err := h.todoSvc.GetAll() if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"data": todos}) } func (h *Handler) CreateTodo(c *gin.Context) { var req struct { Title string `json:"title" binding:"required"` Priority int `json:"priority"` DueDate string `json:"due_date"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if req.Priority == 0 { req.Priority = 2 } var dueDate *time.Time if req.DueDate != "" { t, err := time.Parse("2006-01-02", req.DueDate) if err == nil { dueDate = &t } } todo, err := h.todoSvc.Create(req.Title, req.Priority, dueDate) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusCreated, gin.H{"data": todo}) } func (h *Handler) UpdateTodo(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid id"}) return } var req struct { Title string `json:"title" binding:"required"` Priority int `json:"priority"` Done bool `json:"done"` DueDate string `json:"due_date"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } var dueDate *time.Time if req.DueDate != "" { t, err := time.Parse("2006-01-02", req.DueDate) if err == nil { dueDate = &t } } todo, err := h.todoSvc.Update(id, req.Title, req.Priority, req.Done, dueDate) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"data": todo}) } func (h *Handler) ToggleTodo(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid id"}) return } todo, err := h.todoSvc.ToggleDone(id) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"data": todo}) } func (h *Handler) DeleteTodo(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid id"}) return } err = h.todoSvc.Delete(id) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "deleted"}) } // DailyLog handlers func (h *Handler) GetDailyLog(c *gin.Context) { date := c.Param("date") if date == "" { date = time.Now().Format("2006-01-02") } log, err := h.dailyLogSvc.GetByDate(date) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"data": log}) } func (h *Handler) GetRecentLogs(c *gin.Context) { limitStr := c.DefaultQuery("limit", "30") limit, _ := strconv.Atoi(limitStr) logs, err := h.dailyLogSvc.GetRecent(limit) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"data": logs}) } func (h *Handler) SaveDailyLog(c *gin.Context) { date := c.Param("date") if date == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "date is required"}) return } var req struct { Morning string `json:"morning"` Afternoon string `json:"afternoon"` Evening string `json:"evening"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } log, err := h.dailyLogSvc.Save(date, req.Morning, req.Afternoon, req.Evening) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"data": log}) } // Finance handlers func (h *Handler) GetFinanceByYear(c *gin.Context) { yearStr := c.Param("year") year, err := strconv.Atoi(yearStr) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid year"}) return } entries, err := h.financeSvc.GetByYear(year) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"data": entries}) } func (h *Handler) CreateFinanceEntry(c *gin.Context) { var req struct { Year int `json:"year" binding:"required"` Month int `json:"month"` Type string `json:"type" binding:"required"` // income / expense Category string `json:"category" binding:"required"` // fixed / extra Description string `json:"description"` Amount float64 `json:"amount" binding:"required"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } entry := &model.FinanceEntry{ Year: req.Year, Month: req.Month, Type: req.Type, Category: req.Category, Description: req.Description, Amount: req.Amount, } if err := h.financeSvc.Create(entry); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusCreated, gin.H{"data": entry}) } func (h *Handler) UpdateFinanceEntry(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid id"}) return } var req struct { Year int `json:"year"` Month int `json:"month"` Type string `json:"type"` Category string `json:"category"` Description string `json:"description"` Amount float64 `json:"amount"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } err = h.financeSvc.Update(&model.FinanceEntry{ ID: id, Year: req.Year, Month: req.Month, Type: req.Type, Category: req.Category, Description: req.Description, Amount: req.Amount, }) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "updated"}) } func (h *Handler) DeleteFinanceEntry(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid id"}) return } if err := h.financeSvc.Delete(id); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "deleted"}) }