diff options
Diffstat (limited to 'internal/store/native_tasks.go')
| -rw-r--r-- | internal/store/native_tasks.go | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/internal/store/native_tasks.go b/internal/store/native_tasks.go new file mode 100644 index 0000000..3ec043b --- /dev/null +++ b/internal/store/native_tasks.go @@ -0,0 +1,135 @@ +package store + +import ( + "encoding/json" + "log" + "time" + + "task-dashboard/internal/models" +) + +// GetNativeTasks returns all non-completed native tasks. +func (s *Store) GetNativeTasks() ([]models.Task, error) { + rows, err := s.db.Query(` + SELECT id, content, description, project_name, due_date, priority, completed, labels, created_at + FROM native_tasks + WHERE completed = 0 + ORDER BY CASE WHEN due_date IS NULL THEN 1 ELSE 0 END, due_date ASC, priority DESC + `) + if err != nil { + return nil, err + } + defer func() { _ = rows.Close() }() + return scanNativeTasks(rows) +} + +// GetNativeTasksByDateRange returns non-completed native tasks due within the given range. +func (s *Store) GetNativeTasksByDateRange(start, end time.Time) ([]models.Task, error) { + rows, err := s.db.Query(` + SELECT id, content, description, project_name, due_date, priority, completed, labels, created_at + FROM native_tasks + WHERE completed = 0 AND due_date IS NOT NULL AND due_date >= ? AND due_date < ? + ORDER BY due_date ASC, priority DESC + `, start, end) + if err != nil { + return nil, err + } + defer func() { _ = rows.Close() }() + return scanNativeTasks(rows) +} + +// GetUndatedNativeTasks returns non-completed native tasks with no due date. +func (s *Store) GetUndatedNativeTasks() ([]models.Task, error) { + rows, err := s.db.Query(` + SELECT id, content, description, project_name, due_date, priority, completed, labels, created_at + FROM native_tasks + WHERE completed = 0 AND due_date IS NULL + ORDER BY priority DESC, created_at ASC + `) + if err != nil { + return nil, err + } + defer func() { _ = rows.Close() }() + return scanNativeTasks(rows) +} + +// CreateNativeTask inserts a new native task. +func (s *Store) CreateNativeTask(task models.Task) error { + labelsJSON, _ := json.Marshal(task.Labels) + _, err := s.db.Exec(` + INSERT INTO native_tasks (id, content, description, project_name, due_date, priority, labels, created_at, updated_at) + VALUES (?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) + `, task.ID, task.Content, task.Description, task.ProjectName, task.DueDate, task.Priority, string(labelsJSON)) + return err +} + +// UpdateNativeTask updates a native task's content and description. +func (s *Store) UpdateNativeTask(id, content, description string) error { + _, err := s.db.Exec(` + UPDATE native_tasks SET content = ?, description = ?, updated_at = CURRENT_TIMESTAMP + WHERE id = ? + `, content, description, id) + return err +} + +// CompleteNativeTask marks a task as completed. +func (s *Store) CompleteNativeTask(id string) error { + _, err := s.db.Exec(` + UPDATE native_tasks SET completed = 1, updated_at = CURRENT_TIMESTAMP WHERE id = ? + `, id) + return err +} + +// UncompleteNativeTask marks a task as not completed. +func (s *Store) UncompleteNativeTask(id string) error { + _, err := s.db.Exec(` + UPDATE native_tasks SET completed = 0, updated_at = CURRENT_TIMESTAMP WHERE id = ? + `, id) + return err +} + +// ImportFromTodoist copies all incomplete tasks from the Todoist cache into native_tasks. +// Skips tasks already present (by ID). Returns the count of newly imported tasks. +func (s *Store) ImportFromTodoist() (int, error) { + result, err := s.db.Exec(` + INSERT OR IGNORE INTO native_tasks + (id, content, description, project_name, due_date, priority, completed, labels, created_at, updated_at) + SELECT + id, content, COALESCE(description, ''), COALESCE(project_name, ''), + due_date, priority, 0, COALESCE(labels, '[]'), created_at, CURRENT_TIMESTAMP + FROM tasks + WHERE completed = 0 + `) + if err != nil { + return 0, err + } + n, _ := result.RowsAffected() + log.Printf("ImportFromTodoist: imported %d tasks", n) + return int(n), nil +} + +func scanNativeTasks(rows interface{ Next() bool; Scan(...interface{}) error; Err() error }) ([]models.Task, error) { + var tasks []models.Task + for rows.Next() { + var t models.Task + var labelsJSON string + var dueDateStr *string + if err := rows.Scan(&t.ID, &t.Content, &t.Description, &t.ProjectName, &dueDateStr, &t.Priority, &t.Completed, &labelsJSON, &t.CreatedAt); err != nil { + return nil, err + } + if dueDateStr != nil { + if parsed, err := time.Parse(time.RFC3339, *dueDateStr); err == nil { + t.DueDate = &parsed + } else if parsed, err := time.Parse("2006-01-02 15:04:05", *dueDateStr); err == nil { + t.DueDate = &parsed + } else if parsed, err := time.Parse("2006-01-02", *dueDateStr); err == nil { + t.DueDate = &parsed + } + } + if err := json.Unmarshal([]byte(labelsJSON), &t.Labels); err != nil { + t.Labels = nil + } + tasks = append(tasks, t) + } + return tasks, rows.Err() +} |
