← 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 => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[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>