ai cooking
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Codex/add location button to homepage (#294)

* nevermind htmx on zip lookup

* unncessary test

---------

Co-authored-by: paul miller <paul.miller>

authored by

Paul Miller
paul miller
and committed by
GitHub
0286a150 80379976

+23 -55
+14 -24
cmd/careme/web_e2e_test.go
··· 113 113 114 114 } 115 115 116 - func TestZipFromCoordinatesHTMXRedirect(t *testing.T) { 116 + func TestZipFromCoordinatesRedirect(t *testing.T) { 117 117 srv := newTestServer(t) 118 118 defer srv.Close() 119 119 120 - client := newTestClient(t) 120 + client := newNoRedirectClient() 121 121 req, err := http.NewRequest(http.MethodGet, srv.URL+"/locations/zip-from-coordinates?lat=47.6097&lon=-122.3331", nil) 122 122 if err != nil { 123 123 t.Fatalf("failed to build request: %v", err) 124 124 } 125 - req.Header.Set("HX-Request", "true") 126 125 127 126 resp, err := client.Do(req) 128 127 if err != nil { ··· 134 133 } 135 134 }() 136 135 137 - if resp.StatusCode != http.StatusNoContent { 138 - t.Fatalf("expected status %d, got %d", http.StatusNoContent, resp.StatusCode) 136 + if resp.StatusCode != http.StatusFound { 137 + t.Fatalf("expected status %d, got %d", http.StatusFound, resp.StatusCode) 139 138 } 140 - if got := resp.Header.Get("HX-Redirect"); got != "/locations?zip=98101" { 141 - t.Fatalf("expected HX-Redirect %q, got %q", "/locations?zip=98101", got) 142 - } 143 - } 144 - 145 - func TestZipFromCoordinatesRejectsNonHTMX(t *testing.T) { 146 - srv := newTestServer(t) 147 - defer srv.Close() 148 - 149 - client := newTestClient(t) 150 - resp := mustGet(t, client, srv.URL+"/locations/zip-from-coordinates?lat=47.6097&lon=-122.3331") 151 - defer func() { 152 - if err := resp.Body.Close(); err != nil { 153 - t.Fatalf("failed to close response body: %v", err) 154 - } 155 - }() 156 - 157 - if resp.StatusCode != http.StatusBadRequest { 158 - t.Fatalf("expected status %d, got %d", http.StatusBadRequest, resp.StatusCode) 139 + if got := resp.Header.Get("Location"); got != "/locations?zip=98101" { 140 + t.Fatalf("expected Location %q, got %q", "/locations?zip=98101", got) 159 141 } 160 142 } 161 143 ··· 200 182 201 183 func newTestClient(t *testing.T) *http.Client { 202 184 return &http.Client{} 185 + } 186 + 187 + func newNoRedirectClient() *http.Client { 188 + return &http.Client{ 189 + CheckRedirect: func(_ *http.Request, _ []*http.Request) error { 190 + return http.ErrUseLastResponse 191 + }, 192 + } 203 193 } 204 194 205 195 func mustGet(t *testing.T, client *http.Client, url string) *http.Response {
+1 -3
docs/htmx-migration-plan.md
··· 12 12 ## Page-by-Page Plan 13 13 14 14 ### `internal/templates/home.html` 15 - - Current state: no custom interaction JS. 16 - - Plan: optional future HTMX ZIP lookup preview, otherwise keep as-is. 17 - - Priority: low. 15 + - Debated using htmx for location lookup of zip (see commit 8037997) but sicne it didn't do anything online and geolocation needs js anyways inline javascript was simpler. 18 16 19 17 ### `internal/templates/locations.html` 20 18 - Current state: migrated
+4 -14
internal/locations/locations.go
··· 293 293 294 294 func (l *locationServer) Register(mux *http.ServeMux, authClient auth.AuthClient) { 295 295 mux.HandleFunc("GET /locations/zip-from-coordinates", func(w http.ResponseWriter, r *http.Request) { 296 - isHXRequest := r.Header.Get("HX-Request") == "true" 297 - if !isHXRequest { 298 - http.Error(w, "htmx request required", http.StatusBadRequest) 299 - return 300 - } 301 - 302 296 lat, err := strconv.ParseFloat(r.URL.Query().Get("lat"), 64) 303 297 if err != nil { 304 - w.Header().Set("Content-Type", "text/plain; charset=utf-8") 305 - _, _ = w.Write([]byte("Try again, chef. We could not read your location.")) 298 + http.Error(w, "invalid latitude", http.StatusBadRequest) 306 299 return 307 300 } 308 301 lon, err := strconv.ParseFloat(r.URL.Query().Get("lon"), 64) 309 302 if err != nil { 310 - w.Header().Set("Content-Type", "text/plain; charset=utf-8") 311 - _, _ = w.Write([]byte("Try again, chef. We could not read your location.")) 303 + http.Error(w, "invalid longitude", http.StatusBadRequest) 312 304 return 313 305 } 314 306 315 307 zip, ok := l.zipFetcher.NearestZIPToCoordinates(lat, lon) 316 308 if !ok { 317 - w.Header().Set("Content-Type", "text/plain; charset=utf-8") 318 - _, _ = w.Write([]byte("Try again, chef. We could not find your ZIP code.")) 309 + http.Error(w, "zip not found for coordinates", http.StatusNotFound) 319 310 return 320 311 } 321 312 322 - w.Header().Set("HX-Redirect", "/locations?zip="+url.QueryEscape(zip)) 323 - w.WriteHeader(http.StatusNoContent) 313 + http.Redirect(w, r, "/locations?zip="+url.QueryEscape(zip), http.StatusFound) 324 314 }) 325 315 326 316 mux.HandleFunc("GET /locations", func(w http.ResponseWriter, r *http.Request) {
+4 -14
internal/templates/home.html
··· 75 75 Find stores 76 76 </button> 77 77 <button type="button" id="use-location-btn" 78 - hx-get="/locations/zip-from-coordinates" 79 - hx-trigger="zip:lookup" 80 - hx-include="#use-location-lat,#use-location-lon" 81 - hx-target="#use-location-message" 82 - hx-swap="innerHTML" 83 78 class="inline-flex w-full items-center justify-center rounded-lg border border-brand-300 bg-white px-3 py-2 text-sm font-medium text-brand-700 shadow-sm transition hover:bg-brand-50 focus:outline-none focus:ring-2 focus:ring-brand-400 focus:ring-offset-2"> 84 79 Use your location 85 80 </button> 86 - <input id="use-location-lat" name="lat" type="hidden" /> 87 - <input id="use-location-lon" name="lon" type="hidden" /> 88 81 <p id="use-location-message" class="hidden text-xs text-ink-600" aria-live="polite"></p> 89 82 </div> 90 83 </form> ··· 149 142 </section> 150 143 </main> 151 144 {{template "clerk_refresh.html" .}} 152 - <script src="/static/htmx@2.0.8.js"></script> 153 145 <script> 154 146 (() => { 155 147 const button = document.getElementById("use-location-btn"); 156 148 const message = document.getElementById("use-location-message"); 157 - const latInput = document.getElementById("use-location-lat"); 158 - const lonInput = document.getElementById("use-location-lon"); 159 149 160 - if (!button || !message || !latInput || !lonInput || !window.htmx) { 150 + if (!button || !message) { 161 151 return; 162 152 } 163 153 ··· 175 165 showMessage("Finding your ZIP code..."); 176 166 navigator.geolocation.getCurrentPosition( 177 167 (position) => { 178 - latInput.value = position.coords.latitude.toString(); 179 - lonInput.value = position.coords.longitude.toString(); 180 - window.htmx.trigger(button, "zip:lookup"); 168 + const lat = encodeURIComponent(position.coords.latitude.toString()); 169 + const lon = encodeURIComponent(position.coords.longitude.toString()); 170 + window.location.assign(`/locations/zip-from-coordinates?lat=${lat}&lon=${lon}`); 181 171 }, 182 172 () => { 183 173 showMessage("Sorry, chef. Have to allow location access.");