From bab0826fea4a1abdc97be0244bbc2a2f497b4b81 Mon Sep 17 00:00:00 2001 From: type-two Date: Tue, 23 Jun 2026 23:01:54 +1000 Subject: [PATCH] =?UTF-8?q?feat(shop):=20in-store=20kiosk=20page=20?= =?UTF-8?q?=E2=80=94=20touch=20browse,=20locate-in-store,=20scan-to-buy=20?= =?UTF-8?q?QR?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit site/kiosk.html: full-screen themed kiosk (idle attract cover-wall → tap → browse with big search + genre chips + record grid → detail with tracklist, in-store locator (crate · rack) and a QR to buy on the customer's phone). 75s idle returns to attract. /shop/release copies enriched with crate/rack location (public-safe). Route /kiosk. Better than WowPlatter's kiosk: locate + phone-QR front and centre. Audio previews deferred (no internal audio yet). Co-Authored-By: Claude Opus 4.8 --- app/main.py | 2 +- app/shop_routes.py | 8 +- site/kiosk.html | 188 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+), 3 deletions(-) create mode 100644 site/kiosk.html diff --git a/app/main.py b/app/main.py index 1518195..b2ff2ef 100644 --- a/app/main.py +++ b/app/main.py @@ -113,7 +113,7 @@ def _page(filename): return _serve -for _stub in ("shop", "builder", "admin", "dash", "pos", "search", "records", "wantlist"): +for _stub in ("shop", "builder", "admin", "dash", "pos", "search", "records", "wantlist", "kiosk"): 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) diff --git a/app/shop_routes.py b/app/shop_routes.py index 2cedd69..245101c 100644 --- a/app/shop_routes.py +++ b/app/shop_routes.py @@ -136,8 +136,12 @@ async def shop_release(release_id: int, db=Depends(get_db)): SELECT position, title, duration FROM disc_release_track WHERE release_id=:r ORDER BY sequence NULLS LAST, position """), {"r": release_id})).mappings()] copies = [dict(r) for r in (await db.execute(text(""" - SELECT sku, price::float AS price, condition, sleeve_cond, product_url - FROM inventory WHERE release_id=:r AND in_stock AND store_id=1 ORDER BY price + SELECT i.sku, i.price::float AS price, i.condition, i.sleeve_cond, i.product_url, + c.label_text AS crate, r.name AS rack + FROM inventory i + LEFT JOIN virtual_crate c ON c.id = i.crate_id + LEFT JOIN virtual_rack r ON r.id = c.rack_id + WHERE i.release_id=:r AND i.in_stock AND i.store_id=1 ORDER BY i.price """), {"r": release_id})).mappings()] return {"release": dict(dr) if dr else None, "tracks": tracks, "copies": copies} diff --git a/site/kiosk.html b/site/kiosk.html new file mode 100644 index 0000000..5713171 --- /dev/null +++ b/site/kiosk.html @@ -0,0 +1,188 @@ + + + + + +RecordGod — browse the crates + + + + + + +
+
+
+ +
Browse the crates · find it in store
+
▸ tap anywhere to start ◂
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+
+ + +
+
+

+
+
+
+
+
+
+ + + +