package main import ( "errors" "os" "strconv" "time" "github.com/aquasecurity/table" ) type Todo struct { Title string Completed bool CreatedAt time.Time CompletedAt *time.Time } type Todos []Todo func (todos *Todos) add(title string) { todo := Todo{ Title: title, Completed: false, CompletedAt: nil, CreatedAt: time.Now(), } *todos = append(*todos, todo) } func (todos *Todos) validateIndex(index int) error { if index < 0 || index >= len(*todos) { err := errors.New("invalid index") return err } return nil } func (todos *Todos) delete(index int) error { t := *todos if err := t.validateIndex(index); err != nil { return err } *todos = append(t[:index], t[index+1:]...) return nil } func (todos *Todos) toggle(index int) error { t := *todos if err := t.validateIndex(index); err != nil { return err } isCompeleted := t[index].Completed if !isCompeleted { completionTime := time.Now() t[index].CompletedAt = &completionTime } t[index].Completed = !isCompeleted return nil } func (todos *Todos) edit(index int, newTitle string) error { t := *todos if err := t.validateIndex(index); err != nil { return err } t[index].Title = newTitle return nil } func (todos *Todos) print() { table := table.New(os.Stdout) table.SetRowLines(false) table.SetHeaders("Index", "Titile", "Completed", "Created at", "Completed at") for index, t := range *todos { completed := "❌" completedAt := "" if t.Completed { completed = "✅" if t.CompletedAt != nil { completedAt = t.CompletedAt.Format(time.RFC1123) } } table.AddRow(strconv.Itoa(index), t.Title, completed, t.CreatedAt.Format(time.RFC1123), completedAt) } table.Render() }