diff --git a/app/main.py b/app/main.py index d1bc215..0ff51b1 100644 --- a/app/main.py +++ b/app/main.py @@ -107,6 +107,9 @@ for _stub in ("shop", "builder", "admin", "dash", "pos", "search", "records"): app.add_api_route(f"/{_stub}", _page(_stub + ".html"), methods=["GET"], include_in_schema=False) # public storefront release detail — release.html reads the id from the path app.add_api_route("/release/{release_id}", _page("release.html"), methods=["GET"], include_in_schema=False) +# entity browse pages — records.html reads the kind+value from the path (/artist/9, /genre/House…) +for _ent in ("artist", "label", "genre", "style"): + app.add_api_route(f"/{_ent}/{{val}}", _page("records.html"), methods=["GET"], include_in_schema=False) # the login landing too (no-cache), matched before the "/" static mount below app.add_api_route("/", _page("index.html"), methods=["GET"], include_in_schema=False) diff --git a/app/shop_routes.py b/app/shop_routes.py index 60b00f1..1bdf688 100644 --- a/app/shop_routes.py +++ b/app/shop_routes.py @@ -43,9 +43,24 @@ async def shop_catalog(q: str = Query(""), page: int = Query(1, ge=1), db=Depend return {"items": items, "page": page, "per": per, "total": total} +@router.get("/artist/{artist_id}") +async def shop_artist(artist_id: int, db=Depends(get_db)): + r = (await db.execute(text("SELECT id, name, realname FROM disc_artist WHERE id=:i"), + {"i": artist_id})).mappings().first() + return {"artist": dict(r) if r else {"id": artist_id, "name": f"Artist {artist_id}"}} + + +@router.get("/label/{label_id}") +async def shop_label(label_id: int, db=Depends(get_db)): + r = (await db.execute(text("SELECT id, name, profile FROM disc_label WHERE id=:i"), + {"i": label_id})).mappings().first() + return {"label": dict(r) if r else {"id": label_id, "name": f"Label {label_id}"}} + + @router.get("/browse") async def shop_browse(q: str = Query(""), genre: str = Query(""), style: str = Query(""), - fmt: str = Query(""), year_min: int | None = None, year_max: int | None = None, + fmt: str = Query(""), artist: int | None = None, label: int | None = None, + year_min: int | None = None, year_max: int | None = None, price_min: float | None = None, price_max: float | None = None, sort: str = Query("new"), page: int = Query(1, ge=1), db=Depends(get_db)): """Faceted, release-grouped catalog — the public Browse page. One row per release with its cheapest copy.""" @@ -60,6 +75,10 @@ async def shop_browse(q: str = Query(""), genre: str = Query(""), style: str = Q where.append("EXISTS (SELECT 1 FROM disc_release_style s WHERE s.release_id=i.release_id AND s.style_name=:style)"); params["style"] = style if fmt: where.append("EXISTS (SELECT 1 FROM disc_release_format f WHERE f.release_id=i.release_id AND f.name ILIKE :fmt)"); params["fmt"] = f"%{fmt}%" + if artist: + where.append("EXISTS (SELECT 1 FROM disc_release_artist ra WHERE ra.release_id=i.release_id AND ra.artist_id=:artist)"); params["artist"] = artist + if label: + where.append("EXISTS (SELECT 1 FROM disc_release_label rl WHERE rl.release_id=i.release_id AND rl.label_id=:label)"); params["label"] = label if year_min: where.append("dr.year >= :ymin"); params["ymin"] = year_min if year_max: @@ -75,6 +94,7 @@ async def shop_browse(q: str = Query(""), genre: str = Query(""), style: str = Q items = [dict(r) for r in (await db.execute(text(f""" SELECT i.release_id, coalesce(min(i.title), dr.title) AS title, dr.artists_sort AS artist, dr.year, dr.country, min(i.price)::float AS price, count(*) AS copies, + (SELECT artist_id FROM disc_release_artist ra WHERE ra.release_id=i.release_id ORDER BY ra.position LIMIT 1) AS artist_id, (SELECT string_agg(DISTINCT genre_name, ', ') FROM disc_release_genre g WHERE g.release_id=i.release_id) AS genre FROM inventory i JOIN disc_release dr ON dr.id = i.release_id WHERE {w} @@ -105,6 +125,7 @@ async def shop_release(release_id: int, db=Depends(get_db)): """Public release detail — metadata + tracklist + in-stock copies (with the Woo buy link).""" dr = (await db.execute(text(""" SELECT dr.id, dr.title, dr.artists_sort AS artist, dr.country, dr.year, dr.notes, dr.master_id, + (SELECT artist_id FROM disc_release_artist ra WHERE ra.release_id=dr.id ORDER BY ra.position LIMIT 1) AS artist_id, (SELECT string_agg(label_name || coalesce(' ('||catno||')',''), ', ') FROM disc_release_label WHERE release_id=dr.id) AS label, (SELECT string_agg(name || coalesce(' '||descriptions,''), ', ') FROM disc_release_format WHERE release_id=dr.id) AS format, (SELECT string_agg(DISTINCT genre_name, ', ') FROM disc_release_genre WHERE release_id=dr.id) AS genre, diff --git a/site/records.html b/site/records.html index 889d855..58bc319 100644 --- a/site/records.html +++ b/site/records.html @@ -55,6 +55,7 @@

Format

+
loading…
@@ -63,9 +64,20 @@