270 lines
7.0 KiB
Go
270 lines
7.0 KiB
Go
package handlers
|
|
|
|
import (
|
|
"go-server/internal/models"
|
|
"go-server/internal/service"
|
|
"net/http"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type TodoController struct {
|
|
service *service.TodoService
|
|
}
|
|
|
|
func NewTodoController(service *service.TodoService) *TodoController {
|
|
return &TodoController{
|
|
service: service,
|
|
}
|
|
}
|
|
|
|
// CreateTodo creates a new todo
|
|
// POST /api/todo/create
|
|
func (h *TodoController) CreateTodo(c *gin.Context) {
|
|
userID := getUserIDFromContext(c) // You'll need to implement this helper
|
|
if userID.IsZero() {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
|
|
return
|
|
}
|
|
|
|
var req service.CreateTodoRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
|
|
return
|
|
}
|
|
|
|
todo, err := h.service.CreateTodo(c.Request.Context(), userID, req)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create todo"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusCreated, todo)
|
|
}
|
|
|
|
// GetTodos gets all todos with stats for the authenticated user
|
|
// GET /api/todo/list
|
|
func (h *TodoController) GetTodos(c *gin.Context) {
|
|
userID := getUserIDFromContext(c)
|
|
if userID.IsZero() {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
|
|
return
|
|
}
|
|
|
|
todos, err := h.service.GetTodosWithStats(c.Request.Context(), userID)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get todos"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, todos)
|
|
}
|
|
|
|
// GetTodaysSummary gets today's todo summary
|
|
// GET /api/todo/today
|
|
func (h *TodoController) GetTodaysSummary(c *gin.Context) {
|
|
userID := getUserIDFromContext(c)
|
|
if userID.IsZero() {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
|
|
return
|
|
}
|
|
|
|
summary, err := h.service.GetTodaysSummary(c.Request.Context(), userID)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get today's summary"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, summary)
|
|
}
|
|
|
|
// UpdateTodo updates a todo
|
|
// PUT /api/todo/:id
|
|
func (h *TodoController) UpdateTodo(c *gin.Context) {
|
|
userID := getUserIDFromContext(c)
|
|
if userID.IsZero() {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
|
|
return
|
|
}
|
|
|
|
todoIDStr := c.Param("id")
|
|
todoID, err := models.ParseULID(todoIDStr)
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid todo ID"})
|
|
return
|
|
}
|
|
|
|
var req service.UpdateTodoRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
|
|
return
|
|
}
|
|
|
|
todo, err := h.service.UpdateTodo(c.Request.Context(), todoID, userID, req)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update todo"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, todo)
|
|
}
|
|
|
|
// DeleteTodo deletes a todo
|
|
// DELETE /api/todo/:id
|
|
func (h *TodoController) DeleteTodo(c *gin.Context) {
|
|
userID := getUserIDFromContext(c)
|
|
if userID.IsZero() {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
|
|
return
|
|
}
|
|
|
|
todoIDStr := c.Param("id")
|
|
todoID, err := models.ParseULID(todoIDStr)
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid todo ID"})
|
|
return
|
|
}
|
|
|
|
err = h.service.DeleteTodo(c.Request.Context(), todoID, userID)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete todo"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "Todo deleted successfully"})
|
|
}
|
|
|
|
// CompleteTodo marks a todo as completed
|
|
// POST /api/todo/:id/complete
|
|
func (h *TodoController) CompleteTodo(c *gin.Context) {
|
|
userID := getUserIDFromContext(c)
|
|
if userID.IsZero() {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
|
|
return
|
|
}
|
|
|
|
todoIDStr := c.Param("id")
|
|
todoID, err := models.ParseULID(todoIDStr)
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid todo ID"})
|
|
return
|
|
}
|
|
|
|
var req service.CompleteTodoRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
|
|
return
|
|
}
|
|
|
|
err = h.service.CompleteTodo(c.Request.Context(), todoID, userID, req)
|
|
if err != nil {
|
|
if err.Error() == "todo already completed today" {
|
|
c.JSON(http.StatusConflict, gin.H{"error": "Todo already completed today"})
|
|
return
|
|
}
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to complete todo"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "Todo completed successfully"})
|
|
}
|
|
|
|
// GetActivityLog gets the user's activity log
|
|
// GET /api/todo/activity
|
|
func (h *TodoController) GetActivityLog(c *gin.Context) {
|
|
userID := getUserIDFromContext(c)
|
|
if userID.IsZero() {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
|
|
return
|
|
}
|
|
|
|
// Parse pagination parameters
|
|
limitStr := c.DefaultQuery("limit", "50")
|
|
offsetStr := c.DefaultQuery("offset", "0")
|
|
|
|
limit, err := strconv.Atoi(limitStr)
|
|
if err != nil {
|
|
limit = 50
|
|
}
|
|
|
|
offset, err := strconv.Atoi(offsetStr)
|
|
if err != nil {
|
|
offset = 0
|
|
}
|
|
|
|
activities, err := h.service.GetActivityLog(c.Request.Context(), userID, limit, offset)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get activity log"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, activities)
|
|
}
|
|
|
|
// GetActivityLogByDate gets activity log for a specific date
|
|
// GET /api/todo/activity/:date
|
|
func (h *TodoController) GetActivityLogByDate(c *gin.Context) {
|
|
userID := getUserIDFromContext(c)
|
|
if userID.IsZero() {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
|
|
return
|
|
}
|
|
|
|
dateStr := c.Param("date")
|
|
date, err := time.Parse("2006-01-02", dateStr)
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid date format. Use YYYY-MM-DD"})
|
|
return
|
|
}
|
|
|
|
activities, err := h.service.GetActivityLogByDate(c.Request.Context(), userID, date)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get activity log"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, activities)
|
|
}
|
|
|
|
// GetWeeklySummary gets a weekly summary of todo completions
|
|
// GET /api/todo/weekly
|
|
func (h *TodoController) GetWeeklySummary(c *gin.Context) {
|
|
userID := getUserIDFromContext(c)
|
|
if userID.IsZero() {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
|
|
return
|
|
}
|
|
|
|
summary, err := h.service.GetWeeklySummary(c.Request.Context(), userID)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get weekly summary"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, summary)
|
|
}
|
|
|
|
// Helper function to get user ID from context
|
|
// You'll need to implement this based on your authentication middleware
|
|
func getUserIDFromContext(c *gin.Context) models.ULID {
|
|
testUserId := models.MustParseULID("01K54QBS528HKQDF985XNW2J6R")
|
|
return testUserId
|
|
// This is a placeholder - implement based on your auth system
|
|
// For example, if you store the user in context after JWT validation:
|
|
|
|
// userInterface, exists := c.Get("user")
|
|
// if !exists {
|
|
// return models.ULID{} // Return zero value
|
|
// }
|
|
|
|
// user, ok := userInterface.(*models.User)
|
|
// if !ok {
|
|
// return models.ULID{} // Return zero value
|
|
// }
|
|
|
|
// return user.ID
|
|
}
|
|
|