commit - ddd1846e580ab46048219bf6f2ab758da62320f3
commit + c5d28ad2701eddf2b1c05d0cc3d59240aae93dce
blob - 16dbc589ba4bcf57b0efde168a339eafa8f4f8fc
blob + 7579110a3722d91a8b420938f70ecfcf7300bdb7
--- cmd/rss/rss.go
+++ cmd/rss/rss.go
package main
import (
- "fmt"
"html/template"
"log"
"net/http"
)
-func render(w http.ResponseWriter, data any, pages ...string) {
- files := append([]string{"internal/templates/base.tmpl"}, pages...)
- tmpl := template.Must(template.ParseFiles(files...))
- tmpl.ExecuteTemplate(w, "base", data)
+type TemplateData struct {
+ Results []string
}
-func homeGET(w http.ResponseWriter, r *http.Request) {
- render(w, nil, "internal/templates/home.tmpl")
+func render(w http.ResponseWriter, name string, data any) {
+ tmpl := template.Must(template.ParseGlob("internal/templates/*.tmpl"))
+ tmpl.ExecuteTemplate(w, name, data)
}
-func homePOST(w http.ResponseWriter, r *http.Request) {
- fmt.Fprintln(w, "Posted to home page")
+func homeHandler(w http.ResponseWriter, r *http.Request) {
+ render(w, "home", nil)
}
+func searchHandler(w http.ResponseWriter, r *http.Request) {
+ isHtmx := r.Header.Get("HX-Request")
+ searchResult := r.URL.Query().Get("search")
+ if isHtmx == "true" {
+ render(w, "results", []string{searchResult})
+ } else {
+ render(w, "home", TemplateData{Results: []string{searchResult}})
+ }
+}
+
func main() {
mux := http.NewServeMux()
mux.Handle("GET /static/", http.StripPrefix("/static/", http.FileServer(http.Dir("web"))))
- mux.HandleFunc("GET /", homeGET)
- mux.HandleFunc("POST /", homePOST)
+ mux.HandleFunc("GET /", homeHandler)
+ mux.HandleFunc("GET /search", searchHandler)
addr := ":8080"
log.Printf("Server running at %s", addr)
blob - 6ae78fc13f10baf160cd7571d61db2e27d0b9a4e
blob + 5f73e7d290bddfea32f754b8902b26ee2e5bae8f
--- internal/templates/base.tmpl
+++ internal/templates/base.tmpl
-{{ define "base" }}
+{{ define "header" }}
<!DOCTYPE html>
<html lang="en">
<a class="link holo" href="/sign-up" style="margin-right: .5rem;">Sign up</a>
<a class="link" href="/login">Login</a>
</header>
- {{ block "content" . }}{{ end }}
+{{ end }}
+
+{{ define "footer" }}
<footer>
<a href="https://github.com/StreatCodes/rss">
<svg xmlns="http://www.w3.org/2000/svg" aria-label="Github" width="20" height="20" fill="white"
</a>
</footer>
</body>
-
</html>
{{ end }}
\ No newline at end of file
blob - 0601bf92fc5412aa7d5d0d8361c68f71aa216997
blob + 3bd640cfe45b9537c67de612912f71e541b42941
--- internal/templates/home.tmpl
+++ internal/templates/home.tmpl
-{{ define "content" }}
+{{ define "home" }}
+{{ template "header" }}
<main class="search-area">
<hgroup class="search-animation">
<h1>Subscribe to your favourite feed!</h1>
</div>
</hgroup>
- <form>
+ <form hx-get="/search" hx-target="#search-results" hx-push-url="true">
<div class="search-box">
<button type="button" aria-label="Filter">
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" fill="currentColor" class="bi bi-filter"
</button>
</div>
</form>
+
+ <div id="search-results">
+ {{ template "results" .Results }}
+ </div>
</main>
+{{ template "footer" }}
{{ end }}
\ No newline at end of file
blob - /dev/null
blob + 01923330f89d7dcde4d7ccf0cc1c3525e8813ab4 (mode 644)
--- /dev/null
+++ internal/templates/results.tmpl
+{{ define "results" }}
+ <div class="results">
+ {{ range . }}
+ <div class="result">{{ . }}</div>
+ {{ end }}
+ </div>
+{{ end }}
\ No newline at end of file
blob - 0e3fc5cd71bb2ec1a5d69217b25c73b56989547f
blob + 3524c12d5147538040afbfd08647f96705148531
--- web/style.css
+++ web/style.css
--pink: #ee8695;
--blue: #57c2ff;
--dark-blue: #468fb9;
- --black: #292831;
+ --gray: #35343d;
+ --dark-gray: #292831;
+ --black: #1c1b1e;
+
+ --shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
}
* {
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
- background-color: var(--black);
+ background-color: var(--dark-gray);
color: var(--white);
font-size: 1.2em;
margin: 0;
}
header {
- margin: 2rem;
+ padding: 1rem;
display: flex;
justify-content: end;
- display: flex;
align-items: center;
+ border-bottom: solid 1px var(--gray);
a.logo {
color: white;
a.link {
background-color: white;
- color: var(--black);
+ color: var(--dark-gray);
padding: .3rem .8rem;
border-radius: 25px;
font-size: 0.9em;
transition: height 300ms;
overflow-y: hidden;
height: 15rem;
+ margin-top: 2rem;
- &.results {
- height: 0;
- }
-
h1 {
- margin-top: 7rem;
+ margin-top: 5rem;
color: white;
margin-bottom: 1rem;
}
}
}
+}
+main:has(.results)>hgroup.search-animation {
+ height: 0;
}
.search-box {
- background-color: #212024;
+ background-color: var(--black);
border-radius: 100px;
padding: 0.5rem 0.65rem;
- box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
+ box-shadow: var(--shadow);
display: flex;
align-items: center;