web.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package web
  2. import (
  3. "errors"
  4. "fmt"
  5. "html/template"
  6. "log"
  7. "net/http"
  8. "net/url"
  9. "path/filepath"
  10. "strconv"
  11. "strings"
  12. )
  13. type (
  14. gen map[string]any
  15. )
  16. var (
  17. counter int = 1
  18. )
  19. func getContacts() gen {
  20. return gen{
  21. "Joe": "joe@example.com",
  22. "Sarah": "sarah@example.com",
  23. "Fred": "fred@example.com",
  24. }
  25. }
  26. func makeContacts1(templates *template.Template) http.HandlerFunc {
  27. return func(w http.ResponseWriter, r *http.Request) {
  28. templates.ExecuteTemplate(w, "contacts", gen{
  29. "contacts": getContacts(),
  30. "counter": counter,
  31. })
  32. counter++
  33. }
  34. }
  35. func makeNav(templates *template.Template) http.HandlerFunc {
  36. return func(w http.ResponseWriter, r *http.Request) {
  37. path := strings.SplitAfterN(r.URL.Path, "/", 3)[2]
  38. htmlPath := r.Header.Get("Hx-Current-Url")
  39. u, err := url.Parse(htmlPath)
  40. if err != nil {
  41. http.Error(w, err.Error(), http.StatusBadRequest)
  42. return
  43. }
  44. htmlPath = strings.SplitAfterN(u.Path, "/", 2)[1]
  45. htmlPath = htmlPath[0 : len(htmlPath)-len(filepath.Ext(htmlPath))]
  46. num, err := strconv.Atoi(htmlPath)
  47. if err != nil {
  48. http.Error(w, err.Error(), http.StatusBadRequest)
  49. return
  50. }
  51. switch path {
  52. case "nav":
  53. templates.ExecuteTemplate(w, "nav", gen{
  54. "num": num,
  55. "prev": fmt.Sprintf("%02d", num-1),
  56. "curr": fmt.Sprintf("%2d", num),
  57. "next": fmt.Sprintf("%02d", num+1),
  58. })
  59. default:
  60. http.Error(w, path, http.StatusNotFound)
  61. return
  62. }
  63. }
  64. }
  65. func makeSearch4(templates *template.Template) http.HandlerFunc {
  66. return func(w http.ResponseWriter, r *http.Request) {
  67. q := r.FormValue("q")
  68. state := r.FormValue("state")
  69. raw := getContacts()
  70. filtered := gen{}
  71. for k, v := range raw {
  72. if strings.Contains(strings.ToUpper(k), strings.ToUpper(q)) {
  73. filtered[k] = v
  74. }
  75. }
  76. templates.ExecuteTemplate(w, "contacts", gen{
  77. "contacts": filtered,
  78. "state": state,
  79. })
  80. }
  81. }
  82. func makeMessages(templates *template.Template) http.HandlerFunc {
  83. return func(w http.ResponseWriter, r *http.Request) {
  84. message := r.FormValue("message")
  85. log.Printf("%s %s: %q", r.Method, r.URL.Path, message)
  86. if err := templates.ExecuteTemplate(w, "messages", gen{
  87. "message": message,
  88. }); err != nil {
  89. http.Error(w, err.Error(), http.StatusInternalServerError)
  90. }
  91. }
  92. }
  93. func makeSettings(templates *template.Template) http.HandlerFunc {
  94. return func(w http.ResponseWriter, r *http.Request) {
  95. if err := templates.ExecuteTemplate(w, "settings", gen{
  96. "text1": "some value for text1",
  97. }); err != nil {
  98. http.Error(w, err.Error(), http.StatusInternalServerError)
  99. }
  100. }
  101. }
  102. func SetupRoutes(mux *http.ServeMux, templates *template.Template) {
  103. mux.Handle("/", http.FileServer(http.Dir("./web/public/")))
  104. mux.HandleFunc("/autonum/", makeNav(templates))
  105. mux.HandleFunc("/contacts", makeContacts1(templates))
  106. mux.HandleFunc("/messages", makeMessages(templates))
  107. mux.HandleFunc("/search", makeSearch4(templates))
  108. mux.HandleFunc("/settings", makeSettings(templates))
  109. }
  110. func UI(addr string) error {
  111. templates := template.Must(template.ParseGlob("./web/templates/*.gohtml"))
  112. mux := http.NewServeMux()
  113. SetupRoutes(mux, templates)
  114. if err := http.ListenAndServe(addr, mux); err != nil {
  115. if !errors.Is(err, http.ErrServerClosed) {
  116. return fmt.Errorf("http server error %w", err)
  117. }
  118. }
  119. return nil
  120. }