package web import ( "errors" "fmt" "html/template" "net/http" "net/url" "path/filepath" "strconv" "strings" ) var ( counter int = 1 ) func getContacts() map[string]any { return map[string]any{ "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", map[string]any{ "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", map[string]any{ "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 := map[string]any{} for k, v := range raw { if strings.Contains(strings.ToUpper(k), strings.ToUpper(q)) { filtered[k] = v } } templates.ExecuteTemplate(w, "contacts", map[string]any{ "contacts": filtered, "state": state, }) } } 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("/search", makeSearch4(templates)) } func UI(addr string) error { templates := template.Must(template.ParseGlob("./web/public/*.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 }