174 lines
4.3 KiB
Go
Raw Permalink Normal View History

2025-08-23 21:51:33 +02:00
package main
import (
"bufio"
"context"
"fmt"
"log/slog"
"os"
"strconv"
"strings"
"gitea.kleinsense.nl/DariusKlein/kleinTodo/common"
"github.com/urfave/cli/v3"
)
// Todo Command
func Todo() *cli.Command {
return &cli.Command{
Name: "todo",
Usage: "print todo items and allow for updating",
Action: todo,
HideHelpCommand: true,
}
}
func todo(context context.Context, c *cli.Command) error {
// bufio.Scanner is a great way to read user input line by line.
scanner := bufio.NewScanner(os.Stdin)
store, err := common.GetTodoDataStore()
if err != nil {
return err
}
todos := store.GetTodoList(cfg.Server.Credentials.Username)
if err != nil {
return err
}
// This is the main application loop for the interactive mode.
for {
clearScreen()
printTodos(todos)
fmt.Print("What would you like to do? (update, delete, add, quit) [u/d/a/q]: ")
// Wait for and read the user's next command.
scanner.Scan()
command := strings.ToLower(strings.TrimSpace(scanner.Text()))
switch command {
case "u", "update":
todos = handleUpdate(scanner, todos, store)
case "d", "delete":
todos = handleDelete(scanner, todos, store)
case "a", "add":
todos = handleAdd(scanner, todos, store)
case "q", "quit":
fmt.Println("Goodbye!")
return nil // Exit the program
default:
fmt.Println("Invalid command. Please try again.")
}
}
}
func clearScreen() {
fmt.Print("\033[H\033[2J")
}
func printTodos(todos []common.Todo) {
fmt.Printf("Todo items:\n")
for i, t := range todos {
t.PrintIndexed(i + 1)
}
}
// handleDelete prompts for an index and removes the item.
func handleDelete(scanner *bufio.Scanner, todos []common.Todo, store *common.BoltStore) []common.Todo {
fmt.Print("Enter the number of the item to delete: ")
scanner.Scan()
input := strings.TrimSpace(scanner.Text())
index, err := strconv.Atoi(input)
if err != nil || index < 1 || index > len(todos) {
fmt.Println("Invalid number. Returning to main menu.")
return todos
}
removedItem := todos[index-1]
err = store.RemoveValueFromBucket(cfg.Server.Credentials.Username, removedItem.Name)
if err != nil {
slog.Error(err.Error())
return todos
}
fmt.Printf("Item '%s' deleted.\n", removedItem.Name)
todos = append(todos[:index-1], todos[index:]...)
return todos
}
// handleUpdate prompts for an index and new values.
func handleUpdate(scanner *bufio.Scanner, todos []common.Todo, store *common.BoltStore) []common.Todo {
fmt.Print("Enter the number of the item to update: ")
scanner.Scan()
input := strings.TrimSpace(scanner.Text())
index, err := strconv.Atoi(input)
if err != nil || index < 1 || index > len(todos) {
fmt.Println("Invalid number. Returning to main menu.")
return todos
}
// Adjust for 0-based slice index
itemToUpdate := todos[index-1]
fmt.Printf("Updating '%s'. Press Enter to keep current value.\n", itemToUpdate.Name)
fmt.Printf("New name [%s]: ", itemToUpdate.Name)
scanner.Scan()
newName := strings.TrimSpace(scanner.Text())
if newName != "" {
itemToUpdate.Name = newName
}
fmt.Printf("New description [%s]: ", itemToUpdate.Description)
scanner.Scan()
newDescription := strings.TrimSpace(scanner.Text())
if newDescription != "" {
itemToUpdate.Description = newDescription
}
fmt.Printf("New status [%s]: ", itemToUpdate.Status)
scanner.Scan()
newStatus := strings.TrimSpace(scanner.Text())
if newStatus != "" {
itemToUpdate.Status = newStatus
}
err = itemToUpdate.Store(store, cfg.Server.Credentials.Username)
if err != nil {
slog.Error(err.Error())
return todos
}
fmt.Println("Item updated.")
todos[index-1] = itemToUpdate
return todos
}
// handleAdd prompts for the details of a new item.
func handleAdd(scanner *bufio.Scanner, todos []common.Todo, store *common.BoltStore) []common.Todo {
fmt.Print("Enter the name of the new task: ")
scanner.Scan()
name := strings.TrimSpace(scanner.Text())
fmt.Print("Enter the description: ")
scanner.Scan()
description := strings.TrimSpace(scanner.Text())
newTodo := common.Todo{
Name: name, Description: description, Status: common.NotStarted, Owner: cfg.Server.Credentials.Username,
}
err := newTodo.Store(store, cfg.Server.Credentials.Username)
if err != nil {
slog.Error(err.Error())
return todos
}
fmt.Println("New item added.")
return append(todos, newTodo)
}