← back to Dw Photo Capture
public/themes/v6-one-thing.html
247 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>v6 — One Thing At A Time</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,500;9..144,700&family=Inter:wght@400;600;700;800&display=swap" rel="stylesheet">
<style>
:root{ --bg:#FBF9F6; --ink:#232323; --gold:#C9A24B; --taupe:#6B6258; --green:#3FA66B; }
*{box-sizing:border-box;}
html,body{margin:0;padding:0;background:#ddd;font-family:'Inter',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:36px 26px 30px; overflow-y:auto; }
.question{
font-family:'Fraunces',serif; font-weight:600; font-size:34px; line-height:1.18;
text-align:center; margin:6px 0 30px; color:var(--ink);
}
.answers{ flex:1; display:flex; flex-direction:column; gap:16px; }
button{ font-family:'Inter',sans-serif; cursor:pointer; }
.bigbtn{
width:100%; min-height:64px; border-radius:18px; font-size:19px; font-weight:700;
background:#fff; border:2px solid #e7e1d6; color:var(--ink); padding:12px 18px;
}
.bigbtn-primary{ background:var(--gold); border:2px solid var(--gold); color:#3a2a06; }
.bigbtn-secondary{ background:#fff; border:2px solid var(--taupe); color:var(--taupe); }
.bigbtn:focus-visible, .linktext:focus-visible{ outline:3px solid #2B6CB0; outline-offset:2px; }
.linktext{
background:none; border:none; color:var(--taupe); font-size:17px; text-decoration:underline;
text-align:center; min-height:44px; width:100%;
}
.brandlist{ display:flex; flex-direction:column; gap:12px; overflow-y:auto; max-height:520px; }
.swatch{ width:100%; height:170px; border-radius:18px; margin-bottom:8px; }
.swatch.small{ height:120px; }
.sw1{background:repeating-linear-gradient(45deg,#8FAE8B 0 18px,#7c9c78 18px 36px);}
.sw2{background:repeating-linear-gradient(-45deg,#7C93B0 0 16px,#617a99 16px 32px);}
.sw3{background:repeating-linear-gradient(90deg,#D9A441 0 14px,#c98f2c 14px 28px);}
.itemname{ font-size:20px; font-weight:800; margin:0; text-align:center; }
.itemmeta{ font-size:16px; color:#666; margin:4px 0 0; text-align:center; }
.camwrap{ flex:1; display:flex; flex-direction:column; padding:0; margin:-36px -26px -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:40px; left:20px; right:20px; text-align:center;
font-family:'Fraunces',serif; font-size:28px; font-weight:600; color:#fdfbf7;
}
.camview .status{ font-size:19px; font-weight:700; color:#f0e8d8; }
.shutter{
position:absolute; bottom:34px; left:50%; transform:translateX(-50%);
width:90px; height:90px; border-radius:50%; background:var(--gold); border:6px solid #fff;
font-size:34px; display:flex; align-items:center; justify-content:center;
}
.center{ display:flex; flex-direction:column; align-items:center; justify-content:center; flex:1; gap:10px; }
.homefab{
position:absolute; top:14px; left:14px; z-index:20; min-width:56px; min-height:56px;
border-radius:16px; background:rgba(255,255,255,.94); border:2px solid #e7e1d6; color:var(--ink);
font-size:15px; font-weight:700; display:none; align-items:center; justify-content:center; gap:4px;
padding:0 12px; box-shadow:0 4px 10px rgba(0,0,0,.12);
}
.homefab:focus-visible{ outline:3px solid #2B6CB0; outline-offset:2px; }
</style>
<style id="ux-baseline">/* TK-12343 UX baseline: full-bleed on real phones, visible focus everywhere */
@media (max-width:405px){ html,body{margin:0;padding:0} body{overflow-x:hidden} .stage,.phone{width:100% !important;max-width:100%;margin:0 !important;border:0 !important;border-radius:0 !important;box-shadow:none !important;height:100dvh;min-height:640px} }
button:focus-visible,a:focus-visible,[tabindex]:focus-visible,input:focus-visible{outline:3px solid #9C7A33 !important;outline-offset:2px}
</style>
</head>
<body>
<div class="phone">
<button class="homefab" id="homeFab" aria-label="Home" onclick="go('home')">⌂ Home</button>
<div class="screen" id="screen" role="main"></div>
</div>
<script>
const MOCK_ITEMS = [
{name:'Palm Damask', color:'Sage', code:'DW-10423', sw:'sw1'},
{name:'Trellis Weave', color:'Indigo', code:'DW-88214', sw:'sw2'},
{name:'Linen Bloom', color:'Blush', code:'DW-55071', sw:'sw3'},
];
const BRANDS = ['York Wallcoverings','Brewster Home','Kravet','Cole & Son','Thibaut','Ronald Redding'];
const state = { screen:'home', job:null, item:null, brand:null, resultIndex:0 };
function go(screen){ state.screen = screen; render(); }
function startJob(job){
state.job = job; state.item=null; state.brand=null; state.resultIndex=0;
const map = {new:'new-cam', update:'update-cam', find:'find-method', sample:'sample-cam'};
go(map[job]);
}
function randomItem(){ return MOCK_ITEMS[Math.floor(Math.random()*MOCK_ITEMS.length)]; }
function cameraScreen(hint, onShoot){
return `<div class="camwrap"><div class="camview">
<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…';
const from = state.screen; setTimeout(()=>{ if (state.screen !== from) return; state.item = randomItem(); cb(); }, 700);
}
function render(){
const s = document.getElementById('screen');
const fab = document.getElementById('homeFab');
fab.style.display = state.screen==='home' ? 'none' : 'flex';
let html = '';
if(state.screen==='home'){
html += `<h1 class="question">What do you need to do?</h1>
<div class="answers">
<button class="bigbtn" onclick="startJob('new')">Add a New Item</button>
<button class="bigbtn" onclick="startJob('update')">Update an Item</button>
<button class="bigbtn" onclick="startJob('find')">Find an Item</button>
<button class="bigbtn" onclick="startJob('sample')">A Sample Came In</button>
</div>`;
}
else if(state.screen==='new-cam'){
html += cameraScreen('Take a photo of it.', "shoot(()=>go('new-brand'))");
}
else if(state.screen==='new-brand'){
html += `<h1 class="question">Which brand is it?</h1><div class="brandlist">`;
BRANDS.forEach(b=>{ html += `<button class="bigbtn" 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 small ${state.item.sw}"></div>
<p class="itemmeta">${state.brand} · code ${state.item.code}</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 += `<h1 class="question">Saved! 🎉</h1>
<div class="answers">
<button class="bigbtn bigbtn-primary" onclick="startJob('new')">Add Another</button>
<button class="linktext" onclick="go('home')">Home</button>
</div>`;
}
else if(state.screen==='update-cam'){
html += cameraScreen('Scan the label or pattern.', "shoot(()=>go('update-match'))");
}
else if(state.screen==='update-match'){
html += `<h1 class="question">Is this it?</h1>
<div class="swatch ${state.item.sw}"></div>
<p class="itemname">${state.item.name} — ${state.item.color}</p>
<p class="itemmeta">code ${state.item.code}</p>
<div class="answers" style="margin-top:20px;">
<button class="bigbtn bigbtn-primary" onclick="go('update-cam2')">Yes</button>
<button class="bigbtn bigbtn-secondary" onclick="go('update-cam')">No, Let Me Search</button>
</div>`;
}
else if(state.screen==='update-cam2'){
html += cameraScreen('Take the new photo.', "shoot(()=>go('update-done'))");
}
else if(state.screen==='update-done'){
html += `<div class="center"><h1 class="question">Updated! ✅</h1></div>
<button class="bigbtn bigbtn-primary" onclick="go('home')">Back Home</button>`;
}
else if(state.screen==='find-method'){
html += `<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 = MOCK_ITEMS[state.resultIndex];
html += `<h1 class="question">Which one is it?</h1>
<div class="swatch ${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-exhausted'){
html += `<h1 class="question">That's all — try another way?</h1>
<div class="answers">
<button class="bigbtn" onclick="state.resultIndex=0; go('find-result')">Scan</button>
<button class="bigbtn" onclick="state.resultIndex=0; go('find-result')">Talk</button>
<button class="bigbtn" onclick="state.resultIndex=0; go('find-result')">Type</button>
</div>`;
}
else if(state.screen==='find-detail'){
html += `<div class="center">
<h1 class="question" style="font-size:26px; margin-bottom:14px;">${state.item.name}</h1>
<div class="swatch ${state.item.sw}" style="width:260px;"></div>
<p class="itemmeta">${state.item.color} · code ${state.item.code}</p>
</div>
<div class="answers">
<button class="bigbtn bigbtn-primary" onclick="go('update-cam2')">Update This</button>
<button class="bigbtn bigbtn-secondary" onclick="go('find-method')">Search Again</button>
<button class="linktext" onclick="go('home')">Home</button>
</div>`;
}
else if(state.screen==='sample-cam'){
html += cameraScreen('Scan the box label.', "shoot(()=>go('sample-match'))");
}
else if(state.screen==='sample-match'){
html += `<h1 class="question">Mark it received?</h1>
<div class="swatch ${state.item.sw}"></div>
<p class="itemname">${state.item.name} — ${state.item.color}</p>
<p class="itemmeta">code ${state.item.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') go('sample-done'); }, 1100);
}
else if(state.screen==='sample-done'){
html += `<div class="center"><h1 class="question">Done! ✅</h1></div>
<button class="bigbtn bigbtn-primary" onclick="go('home')">Back Home</button>`;
}
s.innerHTML = html;
}
function pickResult(){ state.item = MOCK_ITEMS[state.resultIndex]; go('find-detail'); }
function nextResult(){
if(state.resultIndex < MOCK_ITEMS.length-1){ state.resultIndex++; go('find-result'); }
else { go('find-exhausted'); }
}
render();
</script>
</body>
</html>