177 lines
4.0 KiB
Go
177 lines
4.0 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"sort"
|
|
"strconv"
|
|
|
|
"github.com/starfederation/datastar-go/datastar"
|
|
"github.com/zepyrshut/hrender"
|
|
)
|
|
|
|
type TodoList struct {
|
|
ID int
|
|
Name string
|
|
Completed bool
|
|
}
|
|
|
|
var todoList = []TodoList{
|
|
{
|
|
ID: 1,
|
|
Name: "Sacar a la perra",
|
|
Completed: false,
|
|
},
|
|
{
|
|
ID: 2,
|
|
Name: "Limpiar la casa",
|
|
Completed: false,
|
|
},
|
|
{
|
|
ID: 3,
|
|
Name: "Ir al supermercado",
|
|
Completed: false,
|
|
},
|
|
}
|
|
|
|
type TodoSignals struct {
|
|
NewTodoName string `json:"newtodo"`
|
|
}
|
|
|
|
func main() {
|
|
templatesFS := os.DirFS("./templates")
|
|
|
|
h := hrender.NewHTMLRender(templatesFS, false)
|
|
|
|
mux := http.NewServeMux()
|
|
mux.Handle("GET /", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set(hrender.ContentType, hrender.ContentTextHTMLUTF8)
|
|
err := h.RenderW(w, "pages/index", hrender.H{})
|
|
if err != nil {
|
|
http.Error(w, "error loading template", http.StatusInternalServerError)
|
|
}
|
|
}))
|
|
|
|
mux.Handle("GET /todo", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
sort.Slice(todoList, func(i, j int) bool {
|
|
return todoList[i].ID > todoList[j].ID
|
|
})
|
|
|
|
templ, err := h.RenderS("fragments/todo-widget", hrender.H{
|
|
"TodoList": todoList,
|
|
})
|
|
if err != nil {
|
|
http.Error(w, "error loading template", http.StatusInternalServerError)
|
|
}
|
|
|
|
sse := datastar.NewSSE(w, r)
|
|
if err := sse.PatchElements(templ); err != nil {
|
|
log.Println("error", err)
|
|
}
|
|
}))
|
|
|
|
mux.Handle("GET /todo/new", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
templ, err := h.RenderS("fragments/todo-row-edit", hrender.H{})
|
|
if err != nil {
|
|
http.Error(w, "error loading template", http.StatusInternalServerError)
|
|
}
|
|
|
|
sse := datastar.NewSSE(w, r)
|
|
if err := sse.PatchElements(templ,
|
|
datastar.WithModePrepend(),
|
|
datastar.WithSelectorID("todo-list-body"),
|
|
); err != nil {
|
|
log.Println("error", err)
|
|
}
|
|
}))
|
|
|
|
mux.Handle("POST /todo", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
var signals TodoSignals
|
|
if err := datastar.ReadSignals(r, &signals); err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
}
|
|
|
|
newID := 0
|
|
sort.Slice(todoList, func(i, j int) bool {
|
|
return todoList[i].ID > todoList[j].ID
|
|
})
|
|
newID = todoList[0].ID + 1
|
|
|
|
newItem := TodoList{
|
|
ID: newID,
|
|
Name: signals.NewTodoName,
|
|
Completed: false,
|
|
}
|
|
|
|
todoList = append(todoList, newItem)
|
|
|
|
templ, _ := h.RenderS("fragments/todo-row", hrender.H{
|
|
"ID": newID,
|
|
"Name": newItem.Name,
|
|
"Completed": false,
|
|
})
|
|
|
|
sse := datastar.NewSSE(w, r)
|
|
|
|
if err := sse.PatchElements(templ,
|
|
datastar.WithModeReplace(),
|
|
datastar.WithSelectorID("new-todo-row"),
|
|
); err != nil {
|
|
http.Error(w, "bad request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
signals.NewTodoName = ""
|
|
sse.MarshalAndPatchSignals(signals)
|
|
}))
|
|
|
|
mux.Handle("PATCH /todo/{id}/completed", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
log.Println("patch todo triggered")
|
|
|
|
idStr := r.PathValue("id")
|
|
id, err := strconv.Atoi(idStr)
|
|
if err != nil {
|
|
http.Error(w, "invalid id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var foundItem *TodoList
|
|
for i := range todoList {
|
|
if todoList[i].ID == id {
|
|
todoList[i].Completed = true
|
|
foundItem = &todoList[i]
|
|
break
|
|
}
|
|
}
|
|
|
|
if foundItem == nil {
|
|
http.Error(w, "item not found", http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
templ, err := h.RenderS("fragments/todo-row", hrender.H{
|
|
"ID": foundItem.ID,
|
|
"Name": foundItem.Name,
|
|
"Completed": true,
|
|
})
|
|
if err != nil {
|
|
http.Error(w, "error loading template", http.StatusInternalServerError)
|
|
}
|
|
|
|
sse := datastar.NewSSE(w, r)
|
|
if err := sse.PatchElements(templ, datastar.WithModeOuter(),
|
|
datastar.WithSelectorID(fmt.Sprintf("todo-%d", id)),
|
|
); err != nil {
|
|
http.Error(w, "error", http.StatusInternalServerError)
|
|
}
|
|
}))
|
|
|
|
log.Println("server started on port 8080")
|
|
err := http.ListenAndServe(":8080", mux)
|
|
if err != nil {
|
|
panic(fmt.Sprintf("server cannot start %v", err))
|
|
}
|
|
}
|