]> git.earlybird.gay Git - today/commitdiff
start working on some standard components
authorearly <me@earlybird.gay>
Sun, 25 Aug 2024 06:50:28 +0000 (00:50 -0600)
committerearly <me@earlybird.gay>
Sun, 25 Aug 2024 06:50:28 +0000 (00:50 -0600)
standard/part/contact_form.go [new file with mode: 0644]
standard/part/contact_form.html [new file with mode: 0644]

diff --git a/standard/part/contact_form.go b/standard/part/contact_form.go
new file mode 100644 (file)
index 0000000..45515fc
--- /dev/null
@@ -0,0 +1,104 @@
+package stdpart
+
+import (
+       "errors"
+       "fmt"
+       "net/http"
+       "net/url"
+
+       "git.earlybird.gay/today-engine/part"
+       "git.earlybird.gay/today-engine/render"
+)
+
+var (
+       ErrFormValidation = errors.New("form input is invalid")
+)
+
+func Err(base error, reason string) error {
+       return errors.Join(base, errors.New(reason))
+}
+
+type ContactFormResponse struct {
+       ID       string
+       Name     string
+       Contact  string
+       Category string
+       Content  string
+}
+
+func parseContactFormResponse(r *http.Request) (ContactFormResponse, error) {
+       resp := ContactFormResponse{}
+       err := r.ParseForm()
+       if err != nil {
+               return resp, err
+       }
+       f := r.Form
+
+       resp.ID = f.Get("id")
+       resp.Name = f.Get("name")
+       resp.Contact = f.Get("contact")
+       resp.Category = f.Get("category")
+       resp.Content = f.Get("content")
+
+       return resp, nil
+}
+
+func ContactForm(categories []string) *part.Part {
+       return part.New("stdp-contact-form", "contact_form.html",
+               part.OnLoad(func(data render.Data) error {
+                       data.Set("categories", categories)
+
+                       // Set message if one is given for this part
+                       r := data.Request()
+                       q := r.URL.Query()
+                       id := data.ID()
+
+                       if q.Get("resp_to") == id {
+                               message, err := url.QueryUnescape(q.Get("message"))
+                               if err != nil {
+                                       message = "invalid response message from server"
+                               }
+                               data.Set("message", map[string]any{
+                                       "success": q.Get("success") == "true",
+                                       "message": message,
+                               })
+                       }
+                       return nil
+               }),
+       )
+}
+
+func HandleContactForm(validate, handle func(ContactFormResponse) error) http.Handler {
+       return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+               resp, err := parseContactFormResponse(r)
+               callback := r.FormValue("callback")
+               respond := func(ok bool, msg string) {
+                       msg = url.QueryEscape(msg)
+                       w.Header().Set("Location", fmt.Sprintf("%s?resp_to=%s&success=%t&message=%s", callback, resp.ID, ok, msg))
+                       w.WriteHeader(http.StatusSeeOther)
+               }
+               if err != nil {
+                       respond(false, "unexpected error, please try again later")
+                       return
+               }
+
+               if validate != nil {
+                       err = validate(resp)
+                       if err != nil {
+                               respond(false, err.Error())
+                       }
+               }
+
+               err = handle(resp)
+               if err != nil {
+                       respond(false, "unexpected error, please try again later")
+               }
+
+               respond(true, "message sent")
+       })
+}
+
+func PrintContact(resp ContactFormResponse) error {
+       fmt.Printf("%+v\n", resp)
+       return nil
+}
diff --git a/standard/part/contact_form.html b/standard/part/contact_form.html
new file mode 100644 (file)
index 0000000..273ed38
--- /dev/null
@@ -0,0 +1,27 @@
+<template>
+  {{ $id := .id }}
+  <form action="{{.action}}"
+    {{ with .method }}method="{{.}}"{{ end }}>
+    <input type="hidden" id="{{$id}}-callback" name="callback" value="{{.request.URL.Path}}">
+    <input type="hidden" id="{{$id}}-id" name="id" value="{{.id}}">
+    <label for="{{$id}}-name">Name:</label>
+    <input type="text" name="name" id="{{$id}}-name">
+    <label for="{{$id}}-contact">Contact Info:</label>
+    <input type="text" name="contact" id="{{$id}}-contact">
+    {{- with .categories }}
+    <label for="{{$id}}-category">Category:</label>
+    <select name="category" id="{{$id}}-category">
+      <option value="">--Select a category--</option>
+      {{- range . }}
+      <option value="{{.}}">{{.}}</option>
+      {{ end -}}
+    </select>
+    {{ end -}}
+    <label for="{{$id}}-content">Message:</label>
+    <textarea name="content" id="{{$id}}-content"></textarea>
+    <input type="submit">
+  </form>
+  {{- with .message }}
+  <p class="{{ if .success }}success{{ else }}error{{ end }}">{{ .message }}</p>
+  {{ end -}}
+</template>
\ No newline at end of file