updates
This commit is contained in:
181
server/internal/service/todo_service.go
Normal file
181
server/internal/service/todo_service.go
Normal file
@@ -0,0 +1,181 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"go-server/internal/models"
|
||||
"go-server/internal/repository"
|
||||
"time"
|
||||
)
|
||||
|
||||
type TodoService struct {
|
||||
todoRepo *repository.TodoRepository
|
||||
}
|
||||
|
||||
func NewTodoService(todoRepo *repository.TodoRepository) *TodoService {
|
||||
return &TodoService{
|
||||
todoRepo: todoRepo,
|
||||
}
|
||||
}
|
||||
|
||||
// CreateTodoRequest represents the request to create a new todo
|
||||
type CreateTodoRequest struct {
|
||||
Title string `json:"title" validate:"required,min=1,max=200"`
|
||||
Description string `json:"description" validate:"max=1000"`
|
||||
Color string `json:"color" validate:"required,hexcolor"`
|
||||
}
|
||||
|
||||
// UpdateTodoRequest represents the request to update a todo
|
||||
type UpdateTodoRequest struct {
|
||||
Title string `json:"title" validate:"required,min=1,max=200"`
|
||||
Description string `json:"description" validate:"max=1000"`
|
||||
Color string `json:"color" validate:"required,hexcolor"`
|
||||
}
|
||||
|
||||
// CompleteTodoRequest represents the request to complete a todo
|
||||
type CompleteTodoRequest struct {
|
||||
Description string `json:"description" validate:"max=1000"`
|
||||
}
|
||||
|
||||
// CreateTodo creates a new todo for a user
|
||||
func (s *TodoService) CreateTodo(ctx context.Context, userID models.ULID, req CreateTodoRequest) (*models.Todo, error) {
|
||||
todo := &models.Todo{
|
||||
UserID: userID,
|
||||
Title: req.Title,
|
||||
Description: req.Description,
|
||||
Color: req.Color,
|
||||
IsActive: true,
|
||||
}
|
||||
|
||||
err := s.todoRepo.CreateTodo(ctx, todo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return todo, nil
|
||||
}
|
||||
|
||||
// GetTodosWithStats gets all todos for a user with completion statistics
|
||||
func (s *TodoService) GetTodosWithStats(ctx context.Context, userID models.ULID) ([]models.TodoWithStats, error) {
|
||||
return s.todoRepo.GetTodosWithStats(ctx, userID)
|
||||
}
|
||||
|
||||
// GetTodoByID gets a todo by ID (with user verification)
|
||||
func (s *TodoService) GetTodoByID(ctx context.Context, todoID, userID models.ULID) (*models.Todo, error) {
|
||||
return s.todoRepo.GetTodoByID(ctx, todoID, userID)
|
||||
}
|
||||
|
||||
// UpdateTodo updates a todo
|
||||
func (s *TodoService) UpdateTodo(ctx context.Context, todoID, userID models.ULID, req UpdateTodoRequest) (*models.Todo, error) {
|
||||
todo, err := s.todoRepo.GetTodoByID(ctx, todoID, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
todo.Title = req.Title
|
||||
todo.Description = req.Description
|
||||
todo.Color = req.Color
|
||||
|
||||
err = s.todoRepo.UpdateTodo(ctx, todo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return todo, nil
|
||||
}
|
||||
|
||||
// DeleteTodo deletes (deactivates) a todo
|
||||
func (s *TodoService) DeleteTodo(ctx context.Context, todoID, userID models.ULID) error {
|
||||
return s.todoRepo.DeleteTodo(ctx, todoID, userID)
|
||||
}
|
||||
|
||||
// CompleteTodo marks a todo as completed for today
|
||||
func (s *TodoService) CompleteTodo(ctx context.Context, todoID, userID models.ULID, req CompleteTodoRequest) error {
|
||||
// First check if the todo exists and belongs to the user
|
||||
todo, err := s.todoRepo.GetTodoByID(ctx, todoID, userID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if already completed today
|
||||
completedToday, err := s.todoRepo.CheckTodoCompletedToday(ctx, todoID, userID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if completedToday {
|
||||
return errors.New("todo already completed today")
|
||||
}
|
||||
|
||||
// Create completion record
|
||||
completion := &models.TodoCompletion{
|
||||
TodoID: todo.ID,
|
||||
UserID: userID,
|
||||
CompletedAt: time.Now(),
|
||||
Description: req.Description,
|
||||
}
|
||||
|
||||
return s.todoRepo.CompleteTodo(ctx, completion)
|
||||
}
|
||||
|
||||
// GetTodaysSummary gets today's todo summary
|
||||
func (s *TodoService) GetTodaysSummary(ctx context.Context, userID models.ULID) (*models.DailyTodoSummary, error) {
|
||||
todos, err := s.todoRepo.GetTodosWithStats(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
completedCount := 0
|
||||
for _, todo := range todos {
|
||||
if todo.CompletedToday {
|
||||
completedCount++
|
||||
}
|
||||
}
|
||||
|
||||
summary := &models.DailyTodoSummary{
|
||||
Date: time.Now(),
|
||||
Todos: todos,
|
||||
CompletedCount: completedCount,
|
||||
TotalCount: len(todos),
|
||||
}
|
||||
|
||||
return summary, nil
|
||||
}
|
||||
|
||||
// GetActivityLog gets the user's activity log with pagination
|
||||
func (s *TodoService) GetActivityLog(ctx context.Context, userID models.ULID, limit, offset int) ([]models.TodoCompletion, error) {
|
||||
if limit <= 0 {
|
||||
limit = 50 // Default limit
|
||||
}
|
||||
if limit > 200 {
|
||||
limit = 200 // Max limit
|
||||
}
|
||||
|
||||
return s.todoRepo.GetActivityLog(ctx, userID, limit, offset)
|
||||
}
|
||||
|
||||
// GetActivityLogByDate gets activity log for a specific date
|
||||
func (s *TodoService) GetActivityLogByDate(ctx context.Context, userID models.ULID, date time.Time) ([]models.TodoCompletion, error) {
|
||||
return s.todoRepo.GetActivityLogByDate(ctx, userID, date)
|
||||
}
|
||||
|
||||
// GetWeeklySummary gets a summary of the past 7 days
|
||||
func (s *TodoService) GetWeeklySummary(ctx context.Context, userID models.ULID) (map[string][]models.TodoCompletion, error) {
|
||||
endDate := time.Now().Add(24 * time.Hour) // Include today
|
||||
startDate := endDate.Add(-7 * 24 * time.Hour) // 7 days ago
|
||||
|
||||
completions, err := s.todoRepo.GetCompletionsByDateRange(ctx, userID, startDate, endDate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Group by date
|
||||
dailyCompletions := make(map[string][]models.TodoCompletion)
|
||||
for _, completion := range completions {
|
||||
dateKey := completion.CompletedAt.Format("2006-01-02")
|
||||
dailyCompletions[dateKey] = append(dailyCompletions[dateKey], completion)
|
||||
}
|
||||
|
||||
return dailyCompletions, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user