114 lines
2.7 KiB
Go
114 lines
2.7 KiB
Go
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
|
|
}
|