todo.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. package todo
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "os"
  7. "time"
  8. )
  9. type item struct {
  10. Task string
  11. Done bool
  12. CreatedAt time.Time
  13. CompletedAt time.Time
  14. }
  15. type List []item
  16. // Add creates a new todo item and appends it to the list
  17. func (l *List) Add(task string) {
  18. t := item{
  19. Task: task,
  20. Done: false,
  21. CreatedAt: time.Now(),
  22. CompletedAt: time.Time{},
  23. }
  24. *l = append(*l, t)
  25. }
  26. // Complete method marks a todo item as completed by
  27. // setting the Done field to true and setting the CompletedAt to the current time
  28. func (l *List) Complete(i int) error {
  29. ls := *l
  30. if i <= 0 || i > len(ls) {
  31. return fmt.Errorf("item %d does not exist", i)
  32. }
  33. // Adjusting index for 0 base index
  34. ls[i-1].Done = true
  35. ls[i-1].CompletedAt = time.Now()
  36. return nil
  37. }
  38. // Delete method removes a todo item from the list
  39. func (l *List) Delete(i int) error {
  40. ls := *l
  41. if i <= 0 || i > len(ls) {
  42. return fmt.Errorf("item %d does not exist", i)
  43. }
  44. // Adjusting index for 0 base index
  45. *l = append(ls[:i-1], ls[i:]...)
  46. return nil
  47. }
  48. // Save method encodes the List as JSON and saves it
  49. // using the provided filename
  50. func (l *List) Save(filename string) error {
  51. js, err := json.Marshal(l)
  52. if err != nil {
  53. return err
  54. }
  55. return os.WriteFile(filename, js, 0644)
  56. }
  57. // Get method opens the provided file name, decodes
  58. // the JSON data and parses it into a List
  59. func (l *List) Get(filename string) error {
  60. file, err := os.ReadFile(filename)
  61. if err != nil {
  62. if errors.Is(err, os.ErrNotExist) {
  63. return nil
  64. }
  65. return err
  66. }
  67. return json.Unmarshal(file, l)
  68. }
  69. // String method returns a string representation of the List
  70. // Implementation of the fmt.Stringer interface
  71. func (l *List) String() string {
  72. formatted := ""
  73. for k, v := range *l {
  74. prefix := " "
  75. if v.Done {
  76. prefix = "X "
  77. }
  78. formatted += fmt.Sprintf("%s%d: %s\n", prefix, k+1, v.Task)
  79. }
  80. return formatted
  81. }