00804cb974
Wires recommendation.HomeData into handleGetHome; maps dbq row types to the five HomePayload wire-type slices (AlbumRef/ArtistRef/TrackRef). All slices are non-nil so the SPA never receives JSON null for empty sections. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
56 lines
2.3 KiB
Go
56 lines
2.3 KiB
Go
package api
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"git.fabledsword.com/bvandeusen/minstrel/internal/auth"
|
|
"git.fabledsword.com/bvandeusen/minstrel/internal/db/dbq"
|
|
"git.fabledsword.com/bvandeusen/minstrel/internal/recommendation"
|
|
)
|
|
|
|
// handleGetHome implements GET /api/home. Returns five sections in one
|
|
// payload; sections that have no rows render as []. 500 on any underlying
|
|
// DB failure — the SPA should render either empty states or full content,
|
|
// not a half-broken page.
|
|
func (h *handlers) handleGetHome(w http.ResponseWriter, r *http.Request) {
|
|
user, ok := auth.UserFromContext(r.Context())
|
|
if !ok {
|
|
writeErr(w, http.StatusUnauthorized, "unauthorized", "authentication required")
|
|
return
|
|
}
|
|
data, err := recommendation.HomeData(r.Context(), h.pool, user.ID)
|
|
if err != nil {
|
|
h.logger.Error("api: home data", "err", err)
|
|
writeErr(w, http.StatusInternalServerError, "server_error", "failed to load home")
|
|
return
|
|
}
|
|
|
|
out := HomePayload{
|
|
RecentlyAddedAlbums: make([]AlbumRef, 0, len(data.RecentlyAddedAlbums)),
|
|
RediscoverAlbums: make([]AlbumRef, 0, len(data.RediscoverAlbums)),
|
|
RediscoverArtists: make([]ArtistRef, 0, len(data.RediscoverArtists)),
|
|
MostPlayedTracks: make([]TrackRef, 0, len(data.MostPlayedTracks)),
|
|
LastPlayedArtists: make([]ArtistRef, 0, len(data.LastPlayedArtists)),
|
|
}
|
|
for _, row := range data.RecentlyAddedAlbums {
|
|
out.RecentlyAddedAlbums = append(out.RecentlyAddedAlbums, albumRefFrom(row.Album, row.ArtistName, 0, 0))
|
|
}
|
|
for _, row := range data.RediscoverAlbums {
|
|
out.RediscoverAlbums = append(out.RediscoverAlbums, albumRefFrom(row.Album, row.ArtistName, 0, 0))
|
|
}
|
|
for _, row := range data.RediscoverArtists {
|
|
out.RediscoverArtists = append(out.RediscoverArtists, artistRefFromCovered(row.Artist, int(row.AlbumCount), row.CoverAlbumID))
|
|
}
|
|
for _, row := range data.MostPlayedTracks {
|
|
out.MostPlayedTracks = append(out.MostPlayedTracks, trackRefFrom(row.Track, row.AlbumTitle, row.ArtistName))
|
|
}
|
|
for _, row := range data.LastPlayedArtists {
|
|
out.LastPlayedArtists = append(out.LastPlayedArtists, artistRefFromCovered(row.Artist, int(row.AlbumCount), row.CoverAlbumID))
|
|
}
|
|
writeJSON(w, http.StatusOK, out)
|
|
}
|
|
|
|
// Compile-time guard that dbq has the row types we need; if the SQL is
|
|
// regenerated with a different name, this fails fast at build time.
|
|
var _ = dbq.ListMostPlayedTracksForUserRow{}.Track
|