diff --git a/cmd/server/main.go b/cmd/server/main.go index d45f05c..1bbd5e2 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -51,30 +51,37 @@ func main() { fs := http.FileServer(http.Dir("./static")) mux.Handle("/static/", http.StripPrefix("/static/", fs)) - // Index page (Search) + // Homepage (Catalog) mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { http.NotFound(w, r) return } - q := r.URL.Query().Get("q") - templates.Index(q).Render(r.Context(), w) + templates.Catalog().Render(r.Context(), w) }) - // Search endpoint initial query + // Search page mux.HandleFunc("/search", func(w http.ResponseWriter, r *http.Request) { query := r.URL.Query().Get("q") if query == "" { + templates.Search("").Render(r.Context(), w) return } - res, err := jikanClient.Search(query, 1) - if err != nil { - log.Printf("search error: %v", err) - http.Error(w, "Failed to search anime", http.StatusInternalServerError) + // Check if HTMX request for results only + if r.Header.Get("HX-Request") == "true" { + res, err := jikanClient.Search(query, 1) + if err != nil { + log.Printf("search error: %v", err) + http.Error(w, "Failed to search anime", http.StatusInternalServerError) + return + } + templates.SearchResultsWrapper(query, res.Animes, 2, res.HasNextPage).Render(r.Context(), w) return } - templates.SearchResultsWrapper(query, res.Animes, 2, res.HasNextPage).Render(r.Context(), w) + + // Full page with query + templates.Search(query).Render(r.Context(), w) }) // Search endpoint (HTMX Infinite Scroll) @@ -96,11 +103,6 @@ func main() { templates.SearchItems(query, res.Animes, page+1, res.HasNextPage).Render(r.Context(), w) }) - // Catalog page - mux.HandleFunc("/catalog", func(w http.ResponseWriter, r *http.Request) { - templates.Catalog().Render(r.Context(), w) - }) - // Catalog endpoint (HTMX Infinite Scroll) mux.HandleFunc("/api/catalog", func(w http.ResponseWriter, r *http.Request) { pageStr := r.URL.Query().Get("page") @@ -135,7 +137,19 @@ func main() { return } - templates.AnimeDetails(anime).Render(r.Context(), w) + // Get current watchlist status if user is logged in + currentStatus := "" + if user := middleware.GetUser(r.Context()); user != nil { + entry, err := queries.GetWatchListEntry(r.Context(), database.GetWatchListEntryParams{ + UserID: user.ID, + AnimeID: int64(id), + }) + if err == nil { + currentStatus = entry.Status + } + } + + templates.AnimeDetails(anime, currentStatus).Render(r.Context(), w) }) // Anime Relations API endpoint (HTMX "Suspense") diff --git a/internal/templates/catalog.templ b/internal/templates/catalog.templ index 94467a8..c9c8409 100644 --- a/internal/templates/catalog.templ +++ b/internal/templates/catalog.templ @@ -6,8 +6,13 @@ import "fmt" templ Catalog() { @Layout("malago - catalog") {
-
-
> loading catalog...
+
+
+
+
+
+ loading catalog +
} @@ -29,8 +34,8 @@ templ CatalogItems(animes []jikan.Anime, nextPage int, hasNext bool) { templ CatalogItem(anime jikan.Anime) { - if anime.Images.Webp.LargeImageURL != "" { - { + if anime.ImageURL() != "" { + { } else {
no image
} diff --git a/internal/templates/catalog_templ.go b/internal/templates/catalog_templ.go index 8d816c3..7242bb7 100644 --- a/internal/templates/catalog_templ.go +++ b/internal/templates/catalog_templ.go @@ -44,7 +44,7 @@ func Catalog() templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
> loading catalog...
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
loading catalog
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -88,7 +88,7 @@ func CatalogItems(animes []jikan.Anime, nextPage int, hasNext bool) templ.Compon var templ_7745c5c3_Var4 string templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(string(templ.URL(fmt.Sprintf("/api/catalog?page=%d", nextPage)))) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/catalog.templ`, Line: 19, Col: 102} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/catalog.templ`, Line: 24, Col: 102} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) if templ_7745c5c3_Err != nil { @@ -153,7 +153,7 @@ func CatalogItem(anime jikan.Anime) templ.Component { var templ_7745c5c3_Var6 templ.SafeURL templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinURLErrs(templ.URL(fmt.Sprintf("/anime/%d", anime.MalID))) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/catalog.templ`, Line: 31, Col: 59} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/catalog.templ`, Line: 36, Col: 59} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) if templ_7745c5c3_Err != nil { @@ -163,15 +163,15 @@ func CatalogItem(anime jikan.Anime) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - if anime.Images.Webp.LargeImageURL != "" { + if anime.ImageURL() != "" { templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, " -
- - -
-
- if q != "" { -
- > fetching from jikan... +
+
+
+
+ searching
} else { -
-
- no results yet. -
+
+
search for anime
+
use the search bar above to find anime to add to your watchlist
} } @@ -32,7 +27,10 @@ templ Index(q string) { templ SearchResultsWrapper(query string, animes []jikan.Anime, nextPage int, hasNext bool) { if len(animes) == 0 { -
no results found.
+
+
no results found
+
try a different search term
+
} else {
@SearchItems(query, animes, nextPage, hasNext) diff --git a/internal/templates/index_templ.go b/internal/templates/index_templ.go index 4fbed78..9f0ad6e 100644 --- a/internal/templates/index_templ.go +++ b/internal/templates/index_templ.go @@ -14,7 +14,7 @@ import ( "net/url" ) -func Index(q string) templ.Component { +func Search(q string) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { @@ -47,43 +47,26 @@ func Index(q string) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } if q != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "
> fetching from jikan...
searching
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\" hx-trigger=\"load\" hx-indicator=\"#loading\">
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "
no results yet.
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "
search for anime
use the search bar above to find anime to add to your watchlist
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -114,18 +97,18 @@ func SearchResultsWrapper(query string, animes []jikan.Anime, nextPage int, hasN }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var5 := templ.GetChildren(ctx) - if templ_7745c5c3_Var5 == nil { - templ_7745c5c3_Var5 = templ.NopComponent + templ_7745c5c3_Var4 := templ.GetChildren(ctx) + if templ_7745c5c3_Var4 == nil { + templ_7745c5c3_Var4 = templ.NopComponent } ctx = templ.ClearChildren(ctx) if len(animes) == 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "
no results found.
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
no results found
try a different search term
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -133,7 +116,7 @@ func SearchResultsWrapper(query string, animes []jikan.Anime, nextPage int, hasN if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -158,27 +141,40 @@ func SearchItems(query string, animes []jikan.Anime, nextPage int, hasNext bool) }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var6 := templ.GetChildren(ctx) - if templ_7745c5c3_Var6 == nil { - templ_7745c5c3_Var6 = templ.NopComponent + templ_7745c5c3_Var5 := templ.GetChildren(ctx) + if templ_7745c5c3_Var5 == nil { + templ_7745c5c3_Var5 = templ.NopComponent } ctx = templ.ClearChildren(ctx) for i, anime := range animes { if i == len(animes)-1 && hasNext { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\" hx-trigger=\"revealed\" hx-swap=\"afterend\">") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = CatalogItem(anime).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -190,19 +186,6 @@ func SearchItems(query string, animes []jikan.Anime, nextPage int, hasNext bool) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = CatalogItem(anime).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } } } return nil