Implement task management commands: add, list, done, undo, remove

This commit is contained in:
2026-03-22 19:25:50 -05:00
parent 882bab506c
commit ace18923b9

310
main.go
View File

@@ -38,15 +38,118 @@ func init() {
log.Fatal("Unable to ping database:", err)
}
fmt.Println("Connected to PostgreSQL database!")
// fmt.Println("Connected to PostgreSQL database!")
}
func main() {
app := &cli.App{
Name: "Go Todo App",
Usage: "A simple CLI program to manage your tasks",
Name: "gotodo",
Usage: "A simple CLI program to manage your tasks",
Action: func(c *cli.Context) error {
tasks, err := getPendingTasks()
if err != nil {
return err
}
fmt.Println("Pending Tasks:")
printTasks(tasks)
return nil
},
Commands: []*cli.Command{
// We'll add commands here
{
Name: "add",
Aliases: []string{"a"},
Usage: "Add a new task",
Action: func(c *cli.Context) error {
text := c.Args().First()
if text == "" {
return fmt.Errorf("task text cannot be empty")
}
return createTask(text)
},
},
{
Name: "list",
Aliases: []string{"ls"},
Usage: "List tasks with filters",
Flags: []cli.Flag{
&cli.BoolFlag{Name: "all", Aliases: []string{"a"}, Usage: "List all tasks"},
&cli.BoolFlag{Name: "completed", Aliases: []string{"c"}, Usage: "List only completed tasks"},
&cli.BoolFlag{Name: "pending", Aliases: []string{"p"}, Usage: "List only pending tasks"},
},
Action: func(c *cli.Context) error {
var tasks []Task
var err error
title := "Pending Tasks:"
if c.Bool("all") {
tasks, err = getAllTasks()
title = "All Tasks:"
} else if c.Bool("completed") {
tasks, err = getCompletedTasks()
title = "Completed Tasks:"
} else {
tasks, err = getPendingTasks()
title = "Pending Tasks:"
}
if err != nil {
return err
}
fmt.Println(title)
printTasks(tasks)
return nil
},
},
{
Name: "done",
Aliases: []string{"do"},
Usage: "Mark a task as completed",
Action: func(c *cli.Context) error {
idStr := c.Args().First()
if idStr == "" {
return fmt.Errorf("task ID required")
}
var id int
if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
return fmt.Errorf("invalid task ID: %s", idStr)
}
return completeTask(id)
},
},
{
Name: "undo",
Aliases: []string{"ud"},
Usage: "Mark a task as not completed",
Action: func(c *cli.Context) error {
idStr := c.Args().First()
if idStr == "" {
return fmt.Errorf("task ID required")
}
var id int
if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
return fmt.Errorf("invalid task ID: %s", idStr)
}
return undoTask(id)
},
},
{
Name: "remove",
Aliases: []string{"rm"},
Usage: "Remove a task",
Action: func(c *cli.Context) error {
idStr := c.Args().First()
if idStr == "" {
return fmt.Errorf("task ID required")
}
var id int
if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
return fmt.Errorf("invalid task ID: %s", idStr)
}
return deleteTask(id)
},
},
},
}
@@ -55,3 +158,202 @@ func main() {
log.Fatal(err)
}
}
func createTask(text string) error {
sql := `
INSERT INTO tasks (text, completed)
VALUES ($1, $2)
RETURNING id
`
var id int
err := pool.QueryRow(ctx, sql, text, false).Scan(&id)
if err != nil {
return fmt.Errorf("error creating task: %w", err)
}
fmt.Printf("Created task with ID: %d\n", id)
return nil
}
func getAllTasks() ([]Task, error) {
sql := `
SELECT id, text, completed, created_at, updated_at
FROM tasks
ORDER BY created_at DESC
`
rows, err := pool.Query(ctx, sql)
if err != nil {
return nil, fmt.Errorf("error querying tasks: %w", err)
}
defer rows.Close()
var tasks []Task
for rows.Next() {
var task Task
err := rows.Scan(
&task.Id,
&task.Text,
&task.Completed,
&task.CreatedAt,
&task.UpdatedAt,
)
if err != nil {
return nil, fmt.Errorf("error scanning task row: %w", err)
}
tasks = append(tasks, task)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("error iterating task rows: %w", err)
}
return tasks, nil
}
func completeTask(id int) error {
sql := `
UPDATE tasks
SET completed = true, updated_at = NOW()
WHERE id = $1
`
commandTag, err := pool.Exec(ctx, sql, id)
if err != nil {
return fmt.Errorf("error completing task: %w", err)
}
if commandTag.RowsAffected() == 0 {
return fmt.Errorf("no task found with id %d", id)
}
return nil
}
func undoTask(id int) error {
sql := `
UPDATE tasks
SET completed = false, updated_at = NOW()
WHERE id = $1
`
commandTag, err := pool.Exec(ctx, sql, id)
if err != nil {
return fmt.Errorf("error updating task: %w", err)
}
if commandTag.RowsAffected() == 0 {
return fmt.Errorf("no task found with id %d", id)
}
return nil
}
func deleteTask(id int) error {
sql := `DELETE FROM tasks WHERE id = $1`
commandTag, err := pool.Exec(ctx, sql, id)
if err != nil {
return fmt.Errorf("error deleting task: %w", err)
}
if commandTag.RowsAffected() == 0 {
return fmt.Errorf("no task found with id %d", id)
}
return nil
}
func getPendingTasks() ([]Task, error) {
sql := `
SELECT id, text, completed, created_at, updated_at
FROM tasks
WHERE completed = false
ORDER BY created_at DESC
`
rows, err := pool.Query(ctx, sql)
if err != nil {
return nil, fmt.Errorf("error querying pending tasks: %w", err)
}
defer rows.Close()
var tasks []Task
for rows.Next() {
var task Task
err := rows.Scan(
&task.Id,
&task.Text,
&task.Completed,
&task.CreatedAt,
&task.UpdatedAt,
)
if err != nil {
return nil, fmt.Errorf("error scanning task row: %w", err)
}
tasks = append(tasks, task)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("error iterating task rows: %w", err)
}
return tasks, nil
}
func getCompletedTasks() ([]Task, error) {
sql := `
SELECT id, text, completed, created_at, updated_at
FROM tasks
WHERE completed = true
ORDER BY created_at DESC
`
rows, err := pool.Query(ctx, sql)
if err != nil {
return nil, fmt.Errorf("error querying completed tasks: %w", err)
}
defer rows.Close()
var tasks []Task
for rows.Next() {
var task Task
err := rows.Scan(
&task.Id,
&task.Text,
&task.Completed,
&task.CreatedAt,
&task.UpdatedAt,
)
if err != nil {
return nil, fmt.Errorf("error scanning task row: %w", err)
}
tasks = append(tasks, task)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("error iterating task rows: %w", err)
}
return tasks, nil
}
func printTasks(tasks []Task) {
if len(tasks) == 0 {
fmt.Println("No tasks found")
return
}
for _, task := range tasks {
status := "[ ]"
if task.Completed {
status = "[✓]"
}
fmt.Printf("%d. %s %s (Created: %s)\n",
task.Id,
status,
task.Text,
task.CreatedAt.Format("2006-01-02 15:04:05"))
}
}