diff options
-rw-r--r-- | main.go | 65 | ||||
-rw-r--r-- | templates/search.tmpl | 50 |
2 files changed, 115 insertions, 0 deletions
@@ -16,6 +16,7 @@ import ( "time" "ricketyspace.net/peach/nws" + "ricketyspace.net/peach/photon" ) // peach port. defaults to 8151 @@ -61,6 +62,13 @@ type WeatherTimeline struct { Periods []WeatherPeriod } +type Search struct { + Title string + Location string + Message string + MatchingCoords []photon.Coordinates +} + func init() { flag.Parse() if *peachPort < 80 { @@ -73,6 +81,9 @@ func main() { // static files handler. http.Handle("/static/", http.FileServer(http.FS(peachFS))) + // search handler. + http.HandleFunc("/search", showSearch) + // default handler. http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/" { @@ -95,6 +106,8 @@ func main() { } showWeather(w, float32(lat), float32(lng)) }) + + // start server log.Fatal(http.ListenAndServe(peachAddr, nil)) } @@ -127,9 +140,28 @@ func showWeather(w http.ResponseWriter, lat, lng float32) { // render. err = peachTemplates.ExecuteTemplate(w, "weather.tmpl", weather) if err != nil { + log.Printf("weather: template: %v", err) + return + } +} + +func showSearch(w http.ResponseWriter, r *http.Request) { + // Search is disabled if photon is not enabled. + if !photon.Enabled() { + http.NotFound(w, r) + return + } + + search, err := NewSearch(r) + if err != nil { http.Error(w, err.Error(), 500) return } + err = peachTemplates.ExecuteTemplate(w, "search.tmpl", search) + if err != nil { + log.Printf("search: template: %v", err) + return + } } func NewWeather(point *nws.NWSPoint, f, fh *nws.NWSForecast) (*Weather, error) { @@ -178,3 +210,36 @@ func NewWeather(point *nws.NWSPoint, f, fh *nws.NWSForecast) (*Weather, error) { return w, nil } + +func NewSearch(r *http.Request) (*Search, error) { + s := new(Search) + s.Title = "search" + + if r.Method == "GET" { + return s, nil + } + + // get location. + err := r.ParseForm() + if err != nil { + return s, fmt.Errorf("form: %v", err) + } + location := strings.TrimSpace(r.PostForm.Get("location")) + s.Location = location + if len(location) < 2 { + s.Message = "location invalid" + } + + // try to fetch matching coordinates. + s.MatchingCoords, err = photon.Geocode(location) + if err != nil { + log.Printf("search: geocode: %v", err) + s.Message = "unable to lookup location" + return s, nil + } + if len(s.MatchingCoords) < 1 { + s.Message = "location not found" + return s, nil + } + return s, nil +} diff --git a/templates/search.tmpl b/templates/search.tmpl new file mode 100644 index 0000000..a6d7cff --- /dev/null +++ b/templates/search.tmpl @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="UTF-8"> + <title>peach - {{.Title}}</title> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <meta name="author" content="siddharth ravikumar"> + <link rel="preload" href="/static/peach.css" as="style" /> + <style>@import url("/static/peach.css");</style> + </head> + <body> + <div class="peach"> + <div class="root-container"> + + <div class="search-container"> + <form method="post"> + <div class="search-box"> + <input type="text" class="location" placeholder="us city" + value="{{ .Location }}" name="location" required> + </div> + <div class="search-btn"> + <input type="submit" value="search"> + </div> + </form> + </div> + + {{ if .Message }} + <div class="message-container"> + <div class="message-block"> + <p>{{ .Message }}</p> + </div> + </div> + {{ end }} + + {{ if .MatchingCoords }} + <div class="search-result-container"> + {{ range .MatchingCoords }} + <div class="item"> + <div class="location-name"> + <a href="/{{ printf "%.4f,%.4f" .Lat .Lng }}">{{ .Name }}</a> + </div> + </div> + {{ end }} + </div> + {{ end }} + + </div> <!-- root-container end --> + </div> <!-- peach end --> + </body> +</html> |