package handler import ( "context" "database/sql" "log/slog" "net/http" "strconv" "strings" "git.wittern.io/public/echo-todos/model" "git.wittern.io/public/echo-todos/pkg/db" "git.wittern.io/public/echo-todos/view" "github.com/a-h/templ" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" ) func render(ctx echo.Context, status int, t templ.Component) error { ctx.Response().Writer.WriteHeader(status) err := t.Render(context.Background(), ctx.Response().Writer) if err != nil { return ctx.String(http.StatusInternalServerError, "failed to render response template") } return nil } type DBHandler struct { DB *sql.DB } func (h DBHandler) Index(c echo.Context) error { todos, err := db.ListTodos(h.DB) if err != nil { slog.Error("failed to get todos", "Error", err) render(c, http.StatusInternalServerError, view.ErrorPage("failed to get todos")) return c.String(http.StatusInternalServerError, "failed to get todos") } render(c, http.StatusOK, view.Index(todos)) return nil } func (h DBHandler) getTodos(c echo.Context) error { todos, err := db.ListTodos(h.DB) if err != nil { return c.String(http.StatusInternalServerError, "failed to get todos") } render(c, http.StatusOK, view.Index(todos)) return nil } func (h DBHandler) Post(c echo.Context) error { title := c.FormValue("todo") todo := model.Todo{Title: title, Done: false} db.InsertTodo(h.DB, todo) todos, _ := db.ListTodos(h.DB) render(c, http.StatusCreated, view.TodosList(todos)) return nil } func (h DBHandler) Delete(c echo.Context) error { todoIdParam := c.Param("id") id := extractTodoID(todoIdParam) err := db.DeleteTodoByID(h.DB, id) if err != nil { return c.String(http.StatusInternalServerError, "failed to delete todo") } todos, _ := db.ListTodos(h.DB) render(c, http.StatusOK, view.TodosList(todos)) return nil } func (h DBHandler) Toggle(c echo.Context) error { todoIdParam := c.Param("id") id := extractTodoID(todoIdParam) todos, err := db.ToggleTodoByID(h.DB, id) if err != nil { return c.String(http.StatusInternalServerError, "failed to toggle todo") } render(c, http.StatusOK, view.TodosList(todos)) return nil } func AddRoutes(h DBHandler, e *echo.Echo) { e.Use(middleware.Static("static")) e.Use(middleware.Logger()) e.HTTPErrorHandler = func(err error, c echo.Context) { slog.Error(err.Error()) render(c, http.StatusInternalServerError, view.ErrorPage(err.Error())) } e.GET("/todos", h.getTodos) e.POST("/todos", h.Post) e.PUT("/todos/:id", h.Toggle) e.DELETE("/todos/:id", h.Delete) e.GET("/", h.Index) // e.POST("/", h.Post(e, h)) } func extractTodoID(str string) int { parts := strings.Split(str, "-") todoID, _ := strconv.Atoi(parts[1]) return todoID }