echo-todos/handler/handler.go

115 lines
2.7 KiB
Go
Raw Normal View History

2024-08-19 12:56:20 +00:00
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
}