← back to Quadrille Showroom
public/admin/sample-requests.html
93 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Sample Requests — Quadrille House (Admin)</title>
<style>
:root { --gold:#c9a96e; --bg:#0e0e13; --card:#17171f; --line:rgba(201,169,110,0.15); --muted:#8a857a; }
* { box-sizing: border-box; }
body { margin:0; background:var(--bg); color:#e8e2d4; font:14px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif; padding:24px; }
header { display:flex; align-items:baseline; gap:14px; flex-wrap:wrap; margin-bottom:18px; }
h1 { font-size:20px; font-weight:600; margin:0; letter-spacing:0.02em; }
.count { color:var(--muted); font-size:13px; }
.controls { margin-left:auto; display:flex; gap:8px; align-items:center; }
select, button { background:var(--card); color:#e8e2d4; border:1px solid var(--line); border-radius:6px; padding:6px 10px; font-size:13px; cursor:pointer; }
#grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(300px,1fr)); gap:14px; }
.card { background:var(--card); border:1px solid var(--line); border-radius:10px; padding:14px; }
.when { display:inline-block; font-size:11px; color:var(--gold); background:rgba(201,169,110,0.08); border:1px solid var(--line); border-radius:999px; padding:2px 9px; margin-bottom:10px; }
.id { font-size:10px; color:#5c584f; float:right; }
.row { margin:5px 0; font-size:13px; }
.row .k { color:var(--muted); margin-right:6px; }
.samples { display:flex; flex-wrap:wrap; gap:6px; margin:8px 0; }
.chip { display:flex; align-items:center; gap:6px; background:rgba(0,0,0,0.3); border:1px solid var(--line); border-radius:6px; padding:3px 8px; font-size:12px; }
.dot { width:12px; height:12px; border-radius:3px; border:1px solid rgba(255,255,255,0.15); flex-shrink:0; }
.notes { margin-top:8px; padding-top:8px; border-top:1px solid var(--line); color:#c9c3b6; font-size:12px; white-space:pre-wrap; }
.empty { color:var(--muted); padding:40px; text-align:center; }
</style>
</head>
<body>
<header>
<h1>Sample Requests</h1>
<span class="count" id="count">—</span>
<div class="controls">
<select id="sort">
<option value="newest">Newest first</option>
<option value="oldest">Oldest first</option>
</select>
<button id="refresh">Refresh</button>
</div>
</header>
<div id="grid"></div>
<script>
const COLORS = {'Navy':'#1a2744','Sage':'#6b7f5e','Cream':'#f0ead6','Gold':'#c9a96e','Silver':'#b8b8c0','Blush':'#d4a0a0','Charcoal':'#3a3a42','Ivory':'#f5f0e8','Slate':'#5a6068','Teal':'#2a6b6b','Coral':'#cd6858','Burgundy':'#6b2040'};
let ALL = [];
// Standing admin-card rule: show created DATE + TIME in the admin's local timezone.
function fmtDate(iso) {
const d = new Date(iso);
if (isNaN(d)) return iso || '';
return d.toLocaleString(undefined, { year:'numeric', month:'short', day:'numeric', hour:'numeric', minute:'2-digit' });
}
const esc = s => String(s == null ? '' : s).replace(/[&<>"]/g, c => ({'&':'&','<':'<','>':'>','"':'"'}[c]));
function render() {
const grid = document.getElementById('grid');
const rows = ALL.slice();
if (document.getElementById('sort').value === 'oldest') rows.reverse();
document.getElementById('count').textContent = rows.length + (rows.length === 1 ? ' request' : ' requests');
if (!rows.length) { grid.innerHTML = '<div class="empty">No sample requests yet.</div>'; return; }
grid.innerHTML = rows.map(r => {
const c = r.contact || {};
const samples = (r.samples || []).map(s =>
`<span class="chip"><span class="dot" style="background:${COLORS[s.color] || '#d8d4cc'}"></span>${esc(s.pattern_name || s.sku)}${s.color ? ' · ' + esc(s.color) : ''}</span>`).join('');
const line = (k, v) => v ? `<div class="row"><span class="k">${k}</span>${esc(v)}</div>` : '';
return `<div class="card">
<span class="id">${esc(r.id || '')}</span>
<span class="when" title="${esc(r.created_at || '')}">🕓 ${esc(fmtDate(r.created_at))}</span>
<div class="samples">${samples || '<span class="k">no samples</span>'}</div>
${line('Age', r.age != null ? r.age : '')}
${line('Name', c.name)}
${line('Email', c.email)}
${line('Phone', c.phone)}
${r.notes ? `<div class="notes">${esc(r.notes)}</div>` : ''}
</div>`;
}).join('');
}
async function load() {
try {
const res = await fetch('/api/sample-requests');
const data = await res.json();
ALL = data.requests || []; // server returns newest-first
} catch (e) { ALL = []; }
render();
}
document.getElementById('sort').addEventListener('change', render);
document.getElementById('refresh').addEventListener('click', load);
load();
</script>
</body>
</html>