← back to Dw Photo Capture

public/kid-simple/v10-todays-inbox.html

397 lines

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>v10 — Today's Inbox</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Newsreader:opsz,wght@6..72,500;6..72,600;6..72,700&family=Manrope:wght@500;600;700;800&display=swap" rel="stylesheet">
<style>
  :root{
    --bg:#F3EEE4; --card:#FFFFFF; --ink:#24211C; --muted:#8A8171;
    --brass:#A9772F; --brass-ink:#3A2A0E;
    --terracotta:#B85C38; --terracotta-bg:#F3E1D6;
    --teal:#4F7A73; --teal-bg:#DEEAE7;
    --plum:#6B4E71; --plum-bg:#E9E0EB;
    --green:#4C8C6B; --green-bg:#DCEEE3;
    --line:#E7DFCF;
  }
  *{box-sizing:border-box;}
  html,body{margin:0;padding:0;background:#ccc;font-family:'Manrope',sans-serif;color:var(--ink);}
  body{display:flex; align-items:flex-start; justify-content:center; min-height:100vh; padding:20px 0;}
  .phone{
    width:390px; min-height:780px; background:var(--bg); border-radius:36px; overflow:hidden;
    box-shadow:0 24px 60px rgba(0,0,0,.28); display:flex; flex-direction:column; position:relative;
  }
  .screen{ flex:1; display:flex; flex-direction:column; padding:26px 22px 30px; overflow-y:auto; }
  button{ font-family:'Manrope',sans-serif; cursor:pointer; }

  /* ---- Home / Inbox ---- */
  .inbox-header{ margin-bottom:18px; }
  .inbox-eyebrow{ font-size:14px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--muted); margin:0 0 2px; }
  .inbox-title{ font-family:'Newsreader',serif; font-weight:600; font-size:34px; line-height:1.1; margin:0; color:var(--ink); }
  .inbox-sub{ font-size:15px; color:var(--muted); margin:8px 0 0; }

  .rowlist{ display:flex; flex-direction:column; gap:12px; margin-top:20px; }
  .row{
    display:flex; align-items:center; gap:14px; width:100%; min-height:76px;
    background:var(--card); border:1px solid var(--line); border-radius:20px; padding:12px 16px;
    text-align:left; box-shadow:0 2px 6px rgba(36,33,28,.05);
  }
  .row:focus-visible, .bigbtn:focus-visible, .linktext:focus-visible, .fab:focus-visible, .brandrow:focus-visible{
    outline:3px solid #2B6CB0; outline-offset:2px;
  }
  .badge{
    flex:0 0 auto; width:52px; height:52px; border-radius:16px; display:flex; align-items:center;
    justify-content:center; font-size:24px;
  }
  .badge.terracotta{ background:var(--terracotta-bg); }
  .badge.teal{ background:var(--teal-bg); }
  .badge.plum{ background:var(--plum-bg); }
  .row-text{ flex:1; min-width:0; }
  .row-title{ font-size:17px; font-weight:800; margin:0; color:var(--ink); }
  .row-sub{ font-size:14px; color:var(--muted); margin:2px 0 0; }
  .chev{ font-size:20px; color:var(--muted); flex:0 0 auto; }

  .caughtup{
    display:flex; align-items:center; gap:14px; width:100%; min-height:76px;
    background:var(--green-bg); border:1px solid transparent; border-radius:20px; padding:12px 16px;
  }
  .caughtup .badge{ background:#fff; }
  .caughtup .row-title{ color:#2C5C42; }
  .caughtup .row-sub{ color:#4C8C6B; }

  .fab{
    position:absolute; right:20px; bottom:26px; z-index:20;
    width:68px; height:68px; border-radius:50%; background:var(--brass); border:4px solid #fff;
    color:#fff; font-size:26px; display:flex; align-items:center; justify-content:center;
    box-shadow:0 10px 22px rgba(169,119,47,.45);
  }
  .fab-label{
    position:absolute; right:20px; bottom:98px; z-index:20; background:var(--ink); color:#fff;
    font-size:12px; font-weight:700; padding:6px 10px; border-radius:10px; opacity:.88;
  }

  /* ---- Shared question / answer patterns ---- */
  .topbar{ display:flex; align-items:center; gap:10px; margin-bottom:10px; min-height:56px; }
  .backbtn{
    background:none; border:none; color:var(--muted); font-size:15px; font-weight:700;
    min-height:56px; padding:6px 4px; display:flex; align-items:center; gap:4px;
  }
  .question{
    font-family:'Newsreader',serif; font-weight:600; font-size:28px; line-height:1.2;
    margin:6px 0 20px; color:var(--ink);
  }
  .answers{ flex:1; display:flex; flex-direction:column; gap:14px; }
  .bigbtn{
    width:100%; min-height:64px; border-radius:18px; font-size:18px; font-weight:800;
    background:#fff; border:2px solid var(--line); color:var(--ink); padding:12px 18px;
  }
  .bigbtn-primary{ background:var(--brass); border:2px solid var(--brass); color:#fff; }
  .bigbtn-secondary{ background:#fff; border:2px solid var(--muted); color:var(--muted); }
  .linktext{
    background:none; border:none; color:var(--muted); font-size:16px; text-decoration:underline;
    text-align:center; min-height:56px; width:100%; font-weight:700;
  }

  /* ---- Queue lists (samples / photos) ---- */
  .queuelist{ display:flex; flex-direction:column; gap:12px; }
  .queuecard{
    display:flex; align-items:center; gap:14px; width:100%; min-height:76px;
    background:#fff; border:1px solid var(--line); border-radius:20px; padding:12px 14px; text-align:left;
  }
  .swatch{ flex:0 0 auto; width:52px; height:52px; border-radius:14px; }
  .sw1{background:repeating-linear-gradient(45deg,#8FAE8B 0 10px,#6f8f6b 10px 20px);}
  .sw2{background:repeating-linear-gradient(-45deg,#B85C38 0 10px,#96482a 10px 20px);}
  .sw3{background:radial-gradient(circle at 30% 30%, #A9772F 0 8px, #E9D9BD 9px 20px);}
  .sw4{background:repeating-linear-gradient(90deg,#6B4E71 0 9px,#54394f 9px 18px);}
  .sw5{background:radial-gradient(circle at 60% 40%, #4F7A73 0 9px, #DCEEE3 10px 22px);}
  .qc-text{ flex:1; min-width:0; }
  .qc-title{ font-size:16px; font-weight:800; margin:0; }
  .qc-sub{ font-size:13px; color:var(--muted); margin:2px 0 0; }

  .itemname{ font-size:21px; font-weight:800; margin:14px 0 0; text-align:center; }
  .itemmeta{ font-size:15px; color:var(--muted); margin:4px 0 0; text-align:center; }
  .swatch.big{ width:100%; height:170px; border-radius:20px; margin:0 auto; }

  /* ---- Camera ---- */
  .camwrap{ flex:1; display:flex; flex-direction:column; padding:0; margin:-26px -22px -30px; }
  .camview{
    flex:1; background:#1c1c1e; position:relative; display:flex; align-items:center; justify-content:center;
    color:#fff; min-height:520px;
  }
  .camview .hint{
    position:absolute; top:44px; left:20px; right:20px; text-align:center;
    font-family:'Newsreader',serif; font-size:25px; font-weight:600; color:#fdfbf7;
  }
  .camview .status{ font-size:17px; font-weight:700; color:#e9dfca; }
  .shutter{
    position:absolute; bottom:34px; left:50%; transform:translateX(-50%);
    width:88px; height:88px; border-radius:50%; background:var(--brass); border:6px solid #fff;
    font-size:32px; display:flex; align-items:center; justify-content:center;
  }
  .camback{
    position:absolute; top:16px; left:16px; z-index:5; min-width:56px; min-height:56px;
    background:rgba(255,255,255,.16); border:none; border-radius:12px; color:#fff; font-size:14px; font-weight:700;
  }

  .center{ display:flex; flex-direction:column; align-items:center; justify-content:center; flex:1; gap:10px; }

  /* ---- Brand list ---- */
  .brandlist{ display:flex; flex-direction:column; gap:12px; overflow-y:auto; }
  .brandrow{
    width:100%; min-height:60px; border-radius:16px; background:#fff; border:2px solid var(--line);
    font-size:17px; font-weight:700; color:var(--ink); padding:10px 16px; text-align:left;
  }
</style>
</head>
<body>
<div class="phone">
  <div class="screen" id="screen" role="main"></div>
</div>

<script>
const BRANDS = ['York Wallcoverings','Brewster Home','Kravet','Cole & Son','Thibaut','Ronald Redding'];

let samplesWaiting = [
  {name:'Trellis Weave', color:'Indigo', code:'DW-88214', sw:'sw4'},
  {name:'Palm Damask', color:'Sage', code:'DW-10423', sw:'sw1'},
  {name:'Harbor Stripe', color:'Rust', code:'DW-71190', sw:'sw2'},
];
let photosNeeded = [
  {name:'Linen Bloom', color:'Blush', code:'DW-55071', sw:'sw3'},
  {name:'Meadow Grid', color:'Moss', code:'DW-33982', sw:'sw5'},
];
const FIND_ITEMS = [
  {name:'Trellis Weave', color:'Indigo', code:'DW-88214', sw:'sw4'},
  {name:'Palm Damask', color:'Sage', code:'DW-10423', sw:'sw1'},
  {name:'Linen Bloom', color:'Blush', code:'DW-55071', sw:'sw3'},
];

const state = { screen:'home', brand:null, newItemSw:'sw1', sampleIdx:0, photoIdx:0, findIdx:0, activeItem:null };

function go(screen){ state.screen = screen; render(); }

function cameraScreen(hint, onShoot, backTo){
  return `<div class="camwrap"><div class="camview">
    ${backTo ? `<button class="camback" onclick="go('${backTo}')">‹ Inbox</button>` : ''}
    <div class="hint">${hint}</div>
    <div class="status" id="camStatus">Tap the shutter</div>
    <button class="shutter" aria-label="Take photo" onclick="${onShoot}">📸</button>
  </div></div>`;
}
function shoot(cb){
  const st = document.getElementById('camStatus');
  const btn = document.querySelector('.shutter');
  if(btn) btn.disabled = true;
  if(st) st.textContent = 'Snapping…';
  setTimeout(()=>{ cb(); }, 650);
}

function render(){
  const s = document.getElementById('screen');
  let html = '';

  // ---------------- HOME ----------------
  if(state.screen==='home'){
    const today = new Date();
    const dateStr = today.toLocaleDateString(undefined,{weekday:'long', month:'long', day:'numeric'});
    html += `<div class="inbox-header">
        <p class="inbox-eyebrow">DW · Today's Inbox</p>
        <h1 class="inbox-title">${dateStr}</h1>
        <p class="inbox-sub">Here's what's waiting on you.</p>
      </div>
      <div class="rowlist">`;

    if(samplesWaiting.length){
      html += `<button class="row" onclick="go('sample-queue')">
        <div class="badge terracotta">📦</div>
        <div class="row-text">
          <p class="row-title">${samplesWaiting.length} sample${samplesWaiting.length>1?'s':''} came in</p>
          <p class="row-sub">Tap to check ${samplesWaiting.length>1?'them':'it'} in</p>
        </div>
        <div class="chev">›</div>
      </button>`;
    }
    if(photosNeeded.length){
      html += `<button class="row" onclick="go('update-queue')">
        <div class="badge teal">🔄</div>
        <div class="row-text">
          <p class="row-title">${photosNeeded.length} item${photosNeeded.length>1?'s':''} need${photosNeeded.length>1?'':'s'} new photos</p>
          <p class="row-sub">Tap to update ${photosNeeded.length>1?'them':'it'}</p>
        </div>
        <div class="chev">›</div>
      </button>`;
    }
    if(!samplesWaiting.length && !photosNeeded.length){
      html += `<div class="caughtup">
        <div class="badge">🎉</div>
        <div class="row-text">
          <p class="row-title">All caught up!</p>
          <p class="row-sub">Nothing waiting right now</p>
        </div>
      </div>`;
    }
    html += `<button class="row" onclick="state.findIdx=0; go('find-method')">
        <div class="badge plum">🔍</div>
        <div class="row-text">
          <p class="row-title">Find an item</p>
          <p class="row-sub">Scan, talk, or type</p>
        </div>
        <div class="chev">›</div>
      </button>`;
    html += `</div>`;
    html += `<div class="fab-label">Add new</div>
      <button class="fab" aria-label="Add a new item" onclick="go('new-cam')">📸</button>`;
  }

  // ---------------- ADD NEW ITEM (via FAB) ----------------
  else if(state.screen==='new-cam'){
    html += cameraScreen('Take a photo of it.', "shoot(()=>go('new-brand'))", 'home');
  }
  else if(state.screen==='new-brand'){
    html += `<h1 class="question">Which brand is it?</h1><div class="brandlist">`;
    BRANDS.forEach(b=>{ html += `<button class="brandrow" onclick="state.brand='${b}'; go('new-save')">${b}</button>`; });
    html += `</div>`;
  }
  else if(state.screen==='new-save'){
    html += `<h1 class="question">Save it?</h1>
      <div class="swatch big ${state.newItemSw}"></div>
      <p class="itemmeta">${state.brand}</p>
      <div class="answers" style="margin-top:20px;">
        <button class="bigbtn bigbtn-primary" onclick="go('new-done')">Save as Draft</button>
        <button class="linktext" onclick="go('new-cam')">Retake Photo</button>
      </div>`;
  }
  else if(state.screen==='new-done'){
    html += `<div class="center"><h1 class="question">Saved! 🎉</h1></div>
      <div class="answers">
        <button class="bigbtn bigbtn-primary" onclick="go('new-cam')">Add Another</button>
        <button class="linktext" onclick="go('home')">Back to Inbox</button>
      </div>`;
  }

  // ---------------- SAMPLE QUEUE (row 1) ----------------
  else if(state.screen==='sample-queue'){
    html += `<div class="topbar"><button class="backbtn" onclick="go('home')">‹ Inbox</button></div>
      <h1 class="question">Samples waiting (${samplesWaiting.length})</h1>
      <div class="queuelist">`;
    samplesWaiting.forEach((it,i)=>{
      html += `<button class="queuecard" onclick="state.sampleIdx=${i}; go('sample-confirm')">
        <div class="swatch ${it.sw}"></div>
        <div class="qc-text"><p class="qc-title">${it.name} — ${it.color}</p><p class="qc-sub">code ${it.code}</p></div>
        <div class="chev">›</div>
      </button>`;
    });
    html += `</div>`;
  }
  else if(state.screen==='sample-confirm'){
    const it = samplesWaiting[state.sampleIdx];
    html += `<div class="topbar"><button class="backbtn" onclick="go('sample-queue')">‹ Back</button></div>
      <h1 class="question">Mark it received?</h1>
      <div class="swatch big ${it.sw}"></div>
      <p class="itemname">${it.name} — ${it.color}</p>
      <p class="itemmeta">code ${it.code}</p>
      <div class="answers" style="margin-top:20px;">
        <button class="bigbtn bigbtn-primary" onclick="go('sample-printing')">Yes, Mark Received</button>
      </div>`;
  }
  else if(state.screen==='sample-printing'){
    html += `<div class="center"><h1 class="question">Printing your sticker…</h1><p class="itemmeta">🖨️ One sec…</p></div>`;
    setTimeout(()=>{ if(state.screen==='sample-printing'){
      samplesWaiting.splice(state.sampleIdx,1);
      if(state.sampleIdx>=samplesWaiting.length) state.sampleIdx = 0;
      go('sample-done');
    } }, 1000);
  }
  else if(state.screen==='sample-done'){
    html += `<div class="center"><h1 class="question">Received! ✅</h1></div>
      <div class="answers">
        ${samplesWaiting.length ? `<button class="bigbtn bigbtn-primary" onclick="go('sample-queue')">Next Sample</button>` : ''}
        <button class="linktext" onclick="go('home')">Back to Inbox</button>
      </div>`;
  }

  // ---------------- UPDATE QUEUE (row 2) ----------------
  else if(state.screen==='update-queue'){
    html += `<div class="topbar"><button class="backbtn" onclick="go('home')">‹ Inbox</button></div>
      <h1 class="question">Items needing photos (${photosNeeded.length})</h1>
      <div class="queuelist">`;
    photosNeeded.forEach((it,i)=>{
      html += `<button class="queuecard" onclick="state.photoIdx=${i}; go('update-cam')">
        <div class="swatch ${it.sw}"></div>
        <div class="qc-text"><p class="qc-title">${it.name} — ${it.color}</p><p class="qc-sub">code ${it.code}</p></div>
        <div class="chev">›</div>
      </button>`;
    });
    html += `</div>`;
  }
  else if(state.screen==='update-cam'){
    const it = photosNeeded[state.photoIdx];
    html += cameraScreen(`Take a new photo of ${it.name}.`, "shoot(()=>go('update-done'))", 'update-queue');
  }
  else if(state.screen==='update-done'){
    html += `<div class="center"><h1 class="question">Updated! ✅</h1></div>`;
    photosNeeded.splice(state.photoIdx,1);
    if(state.photoIdx>=photosNeeded.length) state.photoIdx = 0;
    html += `<div class="answers">
        ${photosNeeded.length ? `<button class="bigbtn bigbtn-primary" onclick="go('update-queue')">Next Item</button>` : ''}
        <button class="linktext" onclick="go('home')">Back to Inbox</button>
      </div>`;
  }

  // ---------------- FIND AN ITEM (row 3) ----------------
  else if(state.screen==='find-method'){
    html += `<div class="topbar"><button class="backbtn" onclick="go('home')">‹ Inbox</button></div>
      <h1 class="question">How do you want to find it?</h1>
      <div class="answers">
        <button class="bigbtn" onclick="go('find-result')">📷 Scan</button>
        <button class="bigbtn" onclick="go('find-result')">🎤 Talk</button>
        <button class="bigbtn" onclick="go('find-result')">⌨️ Type</button>
      </div>`;
  }
  else if(state.screen==='find-result'){
    const it = FIND_ITEMS[state.findIdx];
    html += `<div class="topbar"><button class="backbtn" onclick="go('find-method')">‹ Back</button></div>
      <h1 class="question">Which one is it?</h1>
      <div class="swatch big ${it.sw}"></div>
      <p class="itemname">${it.name} — ${it.color}</p>
      <p class="itemmeta">code ${it.code}</p>
      <div class="answers" style="margin-top:20px;">
        <button class="bigbtn bigbtn-primary" onclick="pickResult()">Yes, This One</button>
        <button class="bigbtn bigbtn-secondary" onclick="nextResult()">Next Result</button>
      </div>`;
  }
  else if(state.screen==='find-detail'){
    html += `<div class="center">
        <h1 class="question" style="font-size:24px; margin-bottom:12px;">${state.activeItem.name}</h1>
        <div class="swatch big ${state.activeItem.sw}" style="max-width:240px;"></div>
        <p class="itemmeta">${state.activeItem.color} · code ${state.activeItem.code}</p>
      </div>
      <div class="answers">
        <button class="bigbtn bigbtn-primary" onclick="go('update-cam-fromfind')">Update This</button>
        <button class="bigbtn bigbtn-secondary" onclick="state.findIdx=0; go('find-method')">Search Again</button>
        <button class="linktext" onclick="go('home')">Back to Inbox</button>
      </div>`;
  }
  else if(state.screen==='update-cam-fromfind'){
    html += cameraScreen(`Take the new photo of ${state.activeItem.name}.`, "shoot(()=>go('find-updated'))", 'find-detail');
  }
  else if(state.screen==='find-updated'){
    html += `<div class="center"><h1 class="question">Updated! ✅</h1></div>
      <button class="bigbtn bigbtn-primary" onclick="go('home')">Back to Inbox</button>`;
  }

  s.innerHTML = html;
}
function pickResult(){ state.activeItem = FIND_ITEMS[state.findIdx]; go('find-detail'); }
function nextResult(){
  if(state.findIdx < FIND_ITEMS.length-1){ state.findIdx++; go('find-result'); }
  else { state.findIdx = 0; go('find-result'); }
}

render();
</script>
</body>
</html>