RECORDGOD/site/shop.html

84 lines
5.0 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>RecordGod shop</title>
<style>
:root{--p:#ff5db1;--a:#46d18a;--bg:#0c0c0e;--pn:#141418;--tx:#f0f0f2;--r:12px}
*{box-sizing:border-box}
html,body{margin:0;min-height:100%;background:var(--bg);color:var(--tx);font:15px/1.5 var(--font,system-ui),sans-serif}
a{color:inherit;text-decoration:none}
.head{display:flex;align-items:center;gap:20px;padding:14px 24px;border-bottom:1px solid #ffffff14;position:sticky;top:0;background:var(--bg);z-index:5}
.logo{height:32px;max-width:170px;object-fit:contain}.logo.txt{font-weight:700;color:var(--p);font-size:21px}
nav{display:flex;gap:18px;flex:1;flex-wrap:wrap}nav a{opacity:.85;font-size:14px}
.srch{display:flex;gap:8px;padding:16px 24px}
.srch input{flex:1;max-width:420px;padding:10px;border:1px solid #ffffff22;border-radius:8px;background:#0e0e11;color:var(--tx)}
.srch button,.cartbtn{background:var(--p);color:#160a10;border:0;border-radius:8px;padding:9px 16px;font-weight:600;cursor:pointer}
.grid{display:grid;gap:16px;padding:8px 24px 40px}
.card{background:var(--pn);border-radius:var(--r);padding:10px;display:flex;flex-direction:column;gap:6px}
.cover{width:100%;aspect-ratio:1;border-radius:calc(var(--r) - 4px);object-fit:cover;background:#222}
.title{font-weight:600;font-size:14px;line-height:1.2}.artist{color:#ffffff99;font-size:13px}
.price{font-weight:600;color:var(--p)}
.pill{display:inline-block;padding:1px 8px;border-radius:14px;background:#ffffff1a;font-size:11px;width:fit-content}
.pill.ok{background:#46d18a22;color:var(--a)}
.cart{background:var(--p);color:#160a10;border:0;border-radius:8px;padding:7px;font-weight:600;cursor:pointer;margin-top:2px}
.pg{display:flex;gap:10px;align-items:center;justify-content:center;padding:0 0 40px}
.pg button{background:#1d1d22;color:#ccc;border:1px solid #ffffff22;border-radius:8px;padding:8px 14px;cursor:pointer}
.muted{color:#ffffff88}
</style>
</head>
<body>
<div class="head"><span id="logo"></span><nav id="nav"></nav><button class="cartbtn">Cart</button></div>
<div class="srch"><input id="q" placeholder="search the shop…"><button onclick="search()">Search</button></div>
<div id="grid" class="grid muted" style="padding:24px">loading…</div>
<div id="pg" class="pg"></div>
<script>
let cfg=null, page=1, q='';
const num=(v,d)=>v==null?d:v;
const el={
cover:r=>r.thumb?`<img class=cover src="${r.thumb}">`:`<div class=cover></div>`,
title:r=>`<div class="title">${esc(r.title||r.sku)}</div>`,
artist:r=>`<div class="artist">${esc(r.artist||'')}</div>`,
price:r=>`<div class="price">$${r.price==null?'—':r.price.toFixed(2)}</div>`,
condition:r=>r.condition?`<span class="pill">${esc(r.condition)}</span>`:'',
format:r=>`<span class="pill">${esc(r.kind||'vinyl')}</span>`,
genre:()=>'',year:()=>'',
stock_badge:()=>`<span class="pill ok">in stock</span>`,
wishlist:()=>`<button class="cart" style="background:#ffffff14;color:var(--tx)">♡ Wishlist</button>`,
cart:()=>`<button class="cart">Add to cart</button>`,
};
function esc(s){return (s||'').replace(/[&<>"]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[c]));}
async function boot(){
cfg=await fetch('/shop/config').then(r=>r.json());
const t=cfg.theme||{}, root=document.documentElement;
root.style.setProperty('--p',t.primary); root.style.setProperty('--a',t.accent);
root.style.setProperty('--bg',t.bg); root.style.setProperty('--pn',t.panel);
root.style.setProperty('--tx',t.text); root.style.setProperty('--r',(t.radius??12)+'px');
if(t.font) root.style.setProperty('--font',t.font);
document.getElementById('logo').innerHTML = t.logo
? `<img class="logo" src="${t.logo}" onerror="this.replaceWith(Object.assign(document.createElement('span'),{className:'logo txt',textContent:'RecordGod'}))">`
: `<span class="logo txt">RecordGod</span>`;
document.getElementById('nav').innerHTML=(cfg.menu||[]).map(m=>`<a href="${m.href}">${esc(m.label)}</a>`).join('');
load();
}
async function load(){
document.getElementById('grid').className='grid muted';
const d=await fetch(`/shop/catalog?q=${encodeURIComponent(q)}&page=${page}`).then(r=>r.json());
const cols=(cfg.theme&&cfg.theme.cardCols)||4;
const g=document.getElementById('grid');
g.className='grid'; g.style.gridTemplateColumns=`repeat(${cols},1fr)`;
g.innerHTML=d.items.map(r=>`<div class="card">${(cfg.card||[]).map(k=>el[k]?el[k](r):'').join('')}</div>`).join('')||'<div class="muted">nothing found</div>';
const pages=Math.max(1,Math.ceil(d.total/d.per));
document.getElementById('pg').innerHTML=`<button ${page<=1?'disabled':''} onclick="go(-1)"> prev</button><span class="muted">page ${page} / ${pages} · ${d.total} items</span><button ${page>=pages?'disabled':''} onclick="go(1)">next </button>`;
}
function search(){ q=document.getElementById('q').value.trim(); page=1; load(); }
function go(n){ page+=n; load(); window.scrollTo(0,0); }
document.getElementById('q').addEventListener('keydown',e=>{if(e.key==='Enter')search();});
boot();
</script>
</body>
</html>