package web
import (
"errors"
"fmt"
"html/template"
"log"
"net/http"
"net/url"
"path/filepath"
"strconv"
"strings"
)
type (
gen map[string]any
)
var (
counter int = 1
)
func getContacts() gen {
return gen{
"Joe": "joe@example.com",
"Sarah": "sarah@example.com",
"Fred": "fred@example.com",
}
}
func makeContacts1(templates *template.Template) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
templates.ExecuteTemplate(w, "contacts", gen{
"contacts": getContacts(),
"counter": counter,
})
counter++
}
}
func makeNav(templates *template.Template) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
path := strings.SplitAfterN(r.URL.Path, "/", 3)[2]
htmlPath := r.Header.Get("Hx-Current-Url")
u, err := url.Parse(htmlPath)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
htmlPath = strings.SplitAfterN(u.Path, "/", 2)[1]
htmlPath = htmlPath[0 : len(htmlPath)-len(filepath.Ext(htmlPath))]
num, err := strconv.Atoi(htmlPath)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
switch path {
case "nav":
templates.ExecuteTemplate(w, "nav", gen{
"num": num,
"prev": fmt.Sprintf("%02d", num-1),
"curr": fmt.Sprintf("%2d", num),
"next": fmt.Sprintf("%02d", num+1),
})
default:
http.Error(w, path, http.StatusNotFound)
return
}
}
}
func makeSearch4(templates *template.Template) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
q := r.FormValue("q")
state := r.FormValue("state")
raw := getContacts()
filtered := gen{}
for k, v := range raw {
if strings.Contains(strings.ToUpper(k), strings.ToUpper(q)) {
filtered[k] = v
}
}
templates.ExecuteTemplate(w, "contacts", gen{
"contacts": filtered,
"state": state,
})
}
}
func makeMessages(templates *template.Template) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
message := r.FormValue("message")
log.Printf("%s %s: %q", r.Method, r.URL.Path, message)
if err := templates.ExecuteTemplate(w, "messages", gen{
"message": message,
}); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
}
func makeSettings(templates *template.Template) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if err := templates.ExecuteTemplate(w, "settings", gen{
"text1": "some value for text1",
}); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
}
func SetupRoutes(mux *http.ServeMux, templates *template.Template) {
mux.Handle("/", http.FileServer(http.Dir("./web/public/")))
mux.HandleFunc("/autonum/", makeNav(templates))
mux.HandleFunc("/contacts", makeContacts1(templates))
mux.HandleFunc("/messages", makeMessages(templates))
mux.HandleFunc("/search", makeSearch4(templates))
mux.HandleFunc("/settings", makeSettings(templates))
}
func UI(addr string) error {
templates := template.Must(template.ParseGlob("./web/templates/*.gohtml"))
mux := http.NewServeMux()
SetupRoutes(mux, templates)
if err := http.ListenAndServe(addr, mux); err != nil {
if !errors.Is(err, http.ErrServerClosed) {
return fmt.Errorf("http server error %w", err)
}
}
return nil
}