diff --git a/assets/output.css b/assets/output.css index 187746b..02ce93a 100644 --- a/assets/output.css +++ b/assets/output.css @@ -558,7 +558,37 @@ video { position: static; } +.flex { + display: flex; +} + +.flex-col { + flex-direction: column; +} + +.content-center { + align-content: center; +} + +.items-center { + align-items: center; +} + +.border { + border-width: 1px; +} + +.border-black { + --tw-border-opacity: 1; + border-color: rgb(0 0 0 / var(--tw-border-opacity)); +} + .text-xl { font-size: 1.25rem; line-height: 1.75rem; } + +.text-3xl { + font-size: 1.875rem; + line-height: 2.25rem; +} diff --git a/db/db.go b/db/db.go index e3ae1e5..ceabd8a 100644 --- a/db/db.go +++ b/db/db.go @@ -1,19 +1,61 @@ package db -import "github.com/google/uuid" +import ( + "fmt" -type Todo struct { - Id uuid.UUID - Name string - Done bool -} + "github.com/google/uuid" + "michaelthomson.dev/mthomson/go-todos-app/models" +) type TodosStore struct { - Todos []Todo + Todos []models.Todo +} + +func (ts *TodosStore) List() (todo []models.Todo, err error) { + return ts.Todos, nil +} + +func (ts *TodosStore) Get(id uuid.UUID) (todo models.Todo, err error) { + index := -1 + for i, todo := range ts.Todos { + if id == todo.Id { + index = i + } + } + + if index == -1 { + return models.Todo{}, fmt.Errorf("Could not find todo by id %q", id) + } + + ts.Todos = append(ts.Todos[:index], ts.Todos[index + 1:]...) + + return ts.Todos[index], nil +} + +func (ts *TodosStore) Add(todo models.Todo) (addedTodo models.Todo, err error) { + ts.Todos = append(ts.Todos, todo) + return todo, nil +} + +func (ts *TodosStore) Delete(id uuid.UUID) (err error) { + index := -1 + for i, todo := range ts.Todos { + if id == todo.Id { + index = i + } + } + + if index == -1 { + return fmt.Errorf("Could not find todo by id %q", id) + } + + ts.Todos = append(ts.Todos[:index], ts.Todos[index + 1:]...) + + return nil } func NewTodoStore() TodosStore { return TodosStore{ - Todos: []Todo{}, + Todos: []models.Todo{}, } } diff --git a/handlers/homeHandler.go b/handlers/homeHandler.go index bf06845..f2756b7 100644 --- a/handlers/homeHandler.go +++ b/handlers/homeHandler.go @@ -8,10 +8,10 @@ import ( ) type HomeHandler struct { - ts services.TodoService + ts *services.TodoService } -func NewHomeHandler(ts services.TodoService) HomeHandler { +func NewHomeHandler(ts *services.TodoService) HomeHandler { return HomeHandler{ts: ts} } @@ -32,7 +32,7 @@ func (h *HomeHandler) Home(w http.ResponseWriter, r *http.Request) { } } -func (h HomeHandler) Router() http.Handler { +func (h *HomeHandler) Router() http.Handler { router := http.NewServeMux() router.HandleFunc("/", h.Home) diff --git a/handlers/todoHandler.go b/handlers/todoHandler.go index dd9716f..b1ace43 100644 --- a/handlers/todoHandler.go +++ b/handlers/todoHandler.go @@ -9,14 +9,14 @@ import ( ) type TodoHandler struct { - ts services.TodoService + ts *services.TodoService } -func NewTodoHandler(ts services.TodoService) TodoHandler { +func NewTodoHandler(ts *services.TodoService) TodoHandler { return TodoHandler{ts: ts} } -func (h TodoHandler) Create(w http.ResponseWriter, r *http.Request) { +func (h *TodoHandler) Create(w http.ResponseWriter, r *http.Request) { var err error err = r.ParseForm() @@ -30,7 +30,7 @@ func (h TodoHandler) Create(w http.ResponseWriter, r *http.Request) { addedTodo, err := h.ts.AddTodo(name) if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -42,7 +42,7 @@ func (h TodoHandler) Create(w http.ResponseWriter, r *http.Request) { } } -func (h TodoHandler) Delete(w http.ResponseWriter, r *http.Request) { +func (h *TodoHandler) Delete(w http.ResponseWriter, r *http.Request) { var err error id, err := uuid.Parse(r.PathValue("id")) diff --git a/main.go b/main.go index 5d445c9..9bbb8f2 100644 --- a/main.go +++ b/main.go @@ -13,8 +13,8 @@ func main() { todosStore := db.NewTodoStore() ts := services.NewTodoService(&todosStore) - homeHandler := handlers.NewHomeHandler(*ts) - todoHandler := handlers.NewTodoHandler(*ts) + homeHandler := handlers.NewHomeHandler(ts) + todoHandler := handlers.NewTodoHandler(ts) router := http.NewServeMux() diff --git a/models/todo.go b/models/todo.go new file mode 100644 index 0000000..074855f --- /dev/null +++ b/models/todo.go @@ -0,0 +1,18 @@ +package models + +import "github.com/google/uuid" + +type Todo struct { + Id uuid.UUID + Name string + Done bool +} + +func NewTodo(name string, done bool) Todo { + return Todo{ + Id: uuid.New(), + Name: name, + Done: done, + } +} + diff --git a/services/todoService.go b/services/todoService.go index 6ced1ad..e6edb7a 100644 --- a/services/todoService.go +++ b/services/todoService.go @@ -4,58 +4,41 @@ import ( "fmt" "github.com/google/uuid" - "michaelthomson.dev/mthomson/go-todos-app/db" + "michaelthomson.dev/mthomson/go-todos-app/models" ) +type Db interface { + List() (todo []models.Todo, err error) + Get(id uuid.UUID) (todo models.Todo, err error) + Add(todo models.Todo) (addedTodo models.Todo, err error) + Delete(id uuid.UUID) (err error) +} + type TodoService struct { - store *db.TodosStore + db Db } -func NewTodoService(store *db.TodosStore) *TodoService { +func NewTodoService(db Db) *TodoService { return &TodoService{ - store: store, + db: db, } } -func (ts *TodoService) AddTodo(name string) (todo db.Todo, err error) { - addedTodo := db.Todo{ - Id: uuid.New(), - Name: name, - Done: false, +func (ts *TodoService) AddTodo(name string) (todo models.Todo, err error) { + if name == "" { + return models.Todo{}, fmt.Errorf("Must provide a name") } - - ts.store.Todos = append(ts.store.Todos, addedTodo) - - return addedTodo, nil + return ts.db.Add(models.NewTodo(name, false)) } -func (ts *TodoService) GetTodos() (todos []db.Todo, err error) { - return ts.store.Todos, nil +func (ts *TodoService) GetTodos() (todos []models.Todo, err error) { + return ts.db.List() } -func (ts *TodoService) GetTodoById(id uuid.UUID) (todo db.Todo, err error) { - for _, todo := range ts.store.Todos { - if id == todo.Id { - return todo, nil - } - } - - return db.Todo{}, fmt.Errorf("Could not find todo by id %q", id) +func (ts *TodoService) GetTodoById(id uuid.UUID) (todo models.Todo, err error) { + return ts.db.Get(id) } func (ts *TodoService) DeleteTodoById(id uuid.UUID) (err error) { - index := -1 - for i, todo := range ts.store.Todos { - if id == todo.Id { - index = i - } - } - - if index == -1 { - return fmt.Errorf("Could not find todo by id %q", id) - } - - ts.store.Todos = append(ts.store.Todos[:index], ts.store.Todos[index + 1:]...) - - return nil + return ts.db.Delete(id) } diff --git a/services/todoService_test.go b/services/todoService_test.go new file mode 100644 index 0000000..1fc9969 --- /dev/null +++ b/services/todoService_test.go @@ -0,0 +1,3 @@ +package services + +type DbMock struct {} diff --git a/templates/pages/home.templ b/templates/pages/home.templ index 629036d..800958d 100644 --- a/templates/pages/home.templ +++ b/templates/pages/home.templ @@ -1,20 +1,22 @@ package pages import "michaelthomson.dev/mthomson/go-todos-app/templates/shared" -import "michaelthomson.dev/mthomson/go-todos-app/db" import "michaelthomson.dev/mthomson/go-todos-app/templates/partials" +import "michaelthomson.dev/mthomson/go-todos-app/models" -templ Home(todos []db.Todo) { +templ Home(todos []models.Todo) { @shared.Page("Todos") { -
Todos
-
- - -
-
+
+

Todos

+
+ + +
+
for _, todo := range todos { @partials.Todo(todo) }
+
} } diff --git a/templates/pages/home_templ.go b/templates/pages/home_templ.go index ef47fac..4a2937d 100644 --- a/templates/pages/home_templ.go +++ b/templates/pages/home_templ.go @@ -11,10 +11,10 @@ import "io" import "bytes" import "michaelthomson.dev/mthomson/go-todos-app/templates/shared" -import "michaelthomson.dev/mthomson/go-todos-app/db" import "michaelthomson.dev/mthomson/go-todos-app/templates/partials" +import "michaelthomson.dev/mthomson/go-todos-app/models" -func Home(todos []db.Todo) templ.Component { +func Home(todos []models.Todo) templ.Component { return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) if !templ_7745c5c3_IsBuffer { @@ -33,7 +33,7 @@ func Home(todos []db.Todo) templ.Component { templ_7745c5c3_Buffer = templ.GetBuffer() defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
Todos
") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("

Todos

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -43,7 +43,7 @@ func Home(todos []db.Todo) templ.Component { return templ_7745c5c3_Err } } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/templates/partials/todo.templ b/templates/partials/todo.templ index e72c038..27ee505 100644 --- a/templates/partials/todo.templ +++ b/templates/partials/todo.templ @@ -1,14 +1,14 @@ package partials -import "michaelthomson.dev/mthomson/go-todos-app/db" +import "michaelthomson.dev/mthomson/go-todos-app/models" -func todoId(todo db.Todo) string { +func todoId(todo models.Todo) string { return "todo-" + todo.Id.String() } -templ Todo(todo db.Todo) { +templ Todo(todo models.Todo) {
- { todo.Id.String() }: { todo.Name } + { todo.Name }
} diff --git a/templates/partials/todo_templ.go b/templates/partials/todo_templ.go index 35177dd..a7071e0 100644 --- a/templates/partials/todo_templ.go +++ b/templates/partials/todo_templ.go @@ -10,13 +10,13 @@ import "context" import "io" import "bytes" -import "michaelthomson.dev/mthomson/go-todos-app/db" +import "michaelthomson.dev/mthomson/go-todos-app/models" -func todoId(todo db.Todo) string { +func todoId(todo models.Todo) string { return "todo-" + todo.Id.String() } -func Todo(todo db.Todo) templ.Component { +func Todo(todo models.Todo) templ.Component { return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) if !templ_7745c5c3_IsBuffer { @@ -47,37 +47,24 @@ func Todo(todo db.Todo) templ.Component { return templ_7745c5c3_Err } var templ_7745c5c3_Var3 string - templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(todo.Id.String()) + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(todo.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/partials/todo.templ`, Line: 11, Col: 22} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/partials/todo.templ`, Line: 11, Col: 15} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(": ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var4 string - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(todo.Name) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/partials/todo.templ`, Line: 11, Col: 37} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("