Files
pgx-learning/cmd/main.go
2026-03-30 17:01:32 -05:00

193 lines
4.5 KiB
Go

package main
import (
"context"
"fmt"
"os"
"git.ksdemosapps.com/kylesoda/pgx-learning/internal/config"
"git.ksdemosapps.com/kylesoda/pgx-learning/internal/db"
"git.ksdemosapps.com/kylesoda/pgx-learning/internal/db/postgres"
"git.ksdemosapps.com/kylesoda/pgx-learning/internal/models"
"git.ksdemosapps.com/kylesoda/pgx-learning/internal/repository"
"github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
)
func main() {
ctx := context.Background()
pool, err := db.Connect(ctx, config.Db.Url)
if err != nil {
logrus.Fatal(err)
}
defer db.Close(pool)
taskRespository := postgres.NewTaskRepository(pool)
app := &cli.App{
Name: "gotodo",
Usage: "A simple CLI program to manage your tasks",
Action: func(c *cli.Context) error {
completedState := false
tasks, err := taskRespository.GetAll(ctx, repository.GetAllTaskFilters{
Limit: 100,
Completed: &completedState,
})
if err != nil {
return err
}
fmt.Println("Pending Tasks:")
printTasks(tasks)
return nil
},
Commands: []*cli.Command{
{
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 taskRespository.Save(ctx, &models.Task{
Text: 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 []models.Task
var err error
title := "Pending Tasks:"
if c.Bool("all") {
tasks, err = taskRespository.GetAll(ctx, repository.GetAllTaskFilters{
Limit: 100,
})
title = "All Tasks:"
} else if c.Bool("completed") {
completedState := true
tasks, err = taskRespository.GetAll(ctx, repository.GetAllTaskFilters{
Limit: 100,
Completed: &completedState,
})
title = "Completed Tasks:"
} else {
completedState := false
tasks, err = taskRespository.GetAll(ctx, repository.GetAllTaskFilters{
Limit: 100,
Completed: &completedState,
})
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)
}
completedState := true
_, err := taskRespository.Update(ctx, id, &models.UpdateTaskInput{
Completed: &completedState,
})
return err
},
},
{
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)
}
completedState := false
_, err := taskRespository.Update(ctx, id, &models.UpdateTaskInput{
Completed: &completedState,
})
return err
},
},
{
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 taskRespository.Delete(ctx, id)
},
},
},
}
err = app.Run(os.Args)
if err != nil {
logrus.Fatal(err)
}
}
func printTasks(tasks []models.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"))
}
}