Skip to content

Cart

Your cart is empty

Picker Scan

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=no">
<title>LeveLux Order Scan</title>
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="Picker Scan">
<meta name="theme-color" content="#16140f">
<meta name="robots" content="noindex, nofollow, noarchive">
<style>
  :root {
    --gold: #c9a24b;
    --gold-dark: #a8842f;
    --black: #16140f;
    --bg: #f7f5f0;
    --card: #ffffff;
    --text: #1c1c1c;
    --muted: #74705f;
    --good: #2e7d32;
    --bad: #b3261e;
  }
  * { box-sizing: border-box; }
  html, body { margin: 0; padding: 0; background: var(--bg); color: var(--text);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; }
  body { min-height: 100vh; display: flex; flex-direction: column; }
  header { background: var(--black); color: #fff; padding: 18px 20px; display: flex; align-items: center; gap: 12px; }
  header .logo { font-weight: 700; letter-spacing: 0.08em; color: var(--gold); font-size: 18px; text-transform: uppercase; }
  header .sub { font-size: 12px; color: #cfc7ae; margin-top: 2px; }
  main { flex: 1; padding: 20px; max-width: 640px; margin: 0 auto; width: 100%; }

  /* Passcode gate */
  #gate { display: flex; flex-direction: column; align-items: center; justify-content: center; flex: 1; padding: 40px 20px; text-align: center; }
  #gate h1 { font-size: 22px; margin-bottom: 6px; }
  #gate p { color: var(--muted); margin-bottom: 20px; }
  #gate input { font-size: 22px; letter-spacing: 4px; text-align: center; padding: 14px; width: 100%; max-width: 260px;
    border: 2px solid #ddd; border-radius: 10px; margin-bottom: 14px; }
  #gate button, .btn { background: var(--gold); color: var(--black); border: none; border-radius: 10px;
    font-size: 16px; font-weight: 700; padding: 14px 22px; cursor: pointer; }
  #gate button:active, .btn:active { background: var(--gold-dark); }
  .btn:disabled { background: #ddd; color: #999; cursor: not-allowed; }
  #gateError { color: var(--bad); font-size: 14px; min-height: 18px; }

  [hidden] { display: none !important; }

  /* Login (name + PIN) */
  #loginBar { display: flex; flex-wrap: wrap; align-items: center; background: var(--card);
    border-radius: 12px; padding: 14px 16px; margin-bottom: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.08); gap: 10px; }
  #loginBar .who { font-size: 14px; color: var(--muted); white-space: nowrap; }
  #nameSelect { flex: 1 1 160px; font-size: 16px; font-weight: 700; padding: 10px 12px; border-radius: 8px; border: 2px solid #ddd;
    background: #fafafa; }
  #pinInput { flex: 0 1 100px; font-size: 16px; padding: 10px 12px; border-radius: 8px; border: 2px solid #ddd; text-align: center; letter-spacing: 2px; }
  #loginBtn { flex: 0 0 auto; padding: 10px 18px; font-size: 15px; }
  #loginError { color: var(--bad); font-size: 13px; min-height: 16px; margin-bottom: 8px; }

  /* Logged-in state / pace */
  #loggedInBar { background: var(--card); border-radius: 12px; padding: 12px 16px; margin-bottom: 8px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.08); display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 8px; }
  .whoLoggedIn { font-size: 14px; color: var(--muted); }
  .whoLoggedIn b { color: var(--text); }
  .linkBtn { background: none; border: none; color: var(--gold-dark); font-weight: 700; font-size: 13px;
    text-decoration: underline; cursor: pointer; padding: 0; margin-left: 8px; }
  .pace { font-size: 13px; color: var(--muted); font-weight: 600; }
  .paceWarning { background: var(--bad); color: #fff; border-radius: 10px; padding: 10px 14px; font-size: 14px;
    font-weight: 700; margin-bottom: 16px; text-align: center; }

  /* Tabs */
  .tabBar { display: flex; gap: 8px; margin-bottom: 16px; }
  .tabBtn { flex: 1; padding: 10px; border-radius: 10px; border: 2px solid #ddd; background: #fff;
    font-weight: 700; font-size: 14px; cursor: pointer; color: var(--text); }
  .tabBtn.active { background: var(--black); color: var(--gold); border-color: var(--black); }
  .tabBadge { display: inline-block; background: var(--bad); color: #fff; border-radius: 999px;
    padding: 1px 8px; font-size: 12px; margin-left: 6px; }

  /* Problem Rack */
  .problemCard { background: var(--card); border-radius: 12px; padding: 14px 16px; margin-bottom: 12px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.08); }
  .problemCard .pmeta { font-size: 13px; color: var(--muted); margin-bottom: 10px; }
  .problemCard .pmeta b { color: var(--text); }
  .resolveBtn { width: 100%; padding: 12px; font-size: 15px; }
  #problemEmpty { text-align: center; color: var(--muted); padding: 30px 20px; }
  .flagBadge { display: inline-block; background: var(--bad); color: #fff; font-weight: 700; font-size: 12px;
    border-radius: 999px; padding: 3px 10px; margin-left: 8px; }
  #skipBtn { width: 100%; margin-top: 8px; background: #fff; border: 2px solid var(--bad); color: var(--bad);
    font-weight: 700; border-radius: 10px; padding: 12px; cursor: pointer; font-size: 15px; }
  #skipBtn:active { background: #fbeceb; }

  /* Scan box */
  #scanBox { background: var(--card); border-radius: 14px; padding: 18px; box-shadow: 0 1px 3px rgba(0,0,0,0.08); margin-bottom: 18px; }
  #scanBox label { font-size: 13px; color: var(--muted); display: block; margin-bottom: 8px; }
  #scanInput { width: 100%; font-size: 22px; padding: 16px; border: 2px solid var(--gold); border-radius: 10px; text-align: center; }
  #scanInput:focus { outline: none; box-shadow: 0 0 0 3px rgba(201,162,75,0.35); }
  #scanHint { text-align: center; color: var(--muted); font-size: 13px; margin-top: 20px; }

  /* Result card */
  #result { display: none; }
  #result.show { display: block; }
  .orderCard { background: var(--card); border-radius: 14px; padding: 18px; box-shadow: 0 1px 3px rgba(0,0,0,0.08); }
  .orderCard h2 { margin: 0 0 4px 0; font-size: 20px; }
  .orderMeta { color: var(--muted); font-size: 14px; margin-bottom: 14px; }
  .orderMeta b { color: var(--text); }
  .itemsCountBadge { display: inline-block; background: var(--black); color: var(--gold); font-weight: 700;
    border-radius: 999px; padding: 4px 12px; font-size: 13px; margin-left: 6px; }
  .itemsCountBadge.mismatch { background: var(--bad); color: #fff; }

  .item { display: flex; gap: 12px; padding: 12px 0; border-top: 1px solid #eee; }
  .item img { width: 72px; height: 72px; object-fit: cover; border-radius: 8px; background: #eee; flex-shrink: 0; }
  .item .noPhoto { width: 72px; height: 72px; border-radius: 8px; background: #eee; display: flex; align-items: center;
    justify-content: center; color: #aaa; font-size: 11px; text-align: center; flex-shrink: 0; }
  .item .desc { font-size: 14px; font-weight: 600; }
  .item .subline { font-size: 13px; color: var(--muted); margin-top: 2px; }

  .verifyBar { margin-top: 16px; padding-top: 16px; border-top: 2px solid #eee; }
  .verifiedBadge { display: flex; align-items: center; gap: 10px; background: #eaf5ea; color: var(--good);
    border-radius: 10px; padding: 12px 14px; font-size: 14px; font-weight: 600; }
  .verifiedBadge.no { background: #fbeceb; color: var(--bad); }
  .photoCheck { display: flex; align-items: center; gap: 8px; font-size: 14px; margin-top: 12px; color: var(--text); }
  .photoCheck input { width: 20px; height: 20px; }
  #verifyBtn { width: 100%; font-size: 18px; padding: 16px; margin-top: 10px; }
  #notFound { text-align: center; padding: 40px 20px; color: var(--bad); }
  #notFound .tn { color: var(--muted); font-family: monospace; margin-top: 6px; }
  #loading { text-align: center; padding: 30px; color: var(--muted); }

  footer { text-align: center; color: var(--muted); font-size: 12px; padding: 16px; }
</style>
</head>
<body>

  <div id="gate">
    <div class="logo" style="color:var(--black); font-size:22px;">LEVELUX</div>
    <h1>Order Scan</h1>
    <p>Enter the shop passcode to continue</p>
    <input id="gateInput" type="password" inputmode="numeric" placeholder="Passcode" autocomplete="off">
    <div id="gateError"></div>
    <button id="gateBtn" class="btn">Enter</button>
  </div>

  <div id="app" hidden style="display:flex; flex-direction:column; flex:1;">
    <header>
      <div>
        <div class="logo">LEVELUX</div>
        <div class="sub">Picker Scan</div>
      </div>
    </header>
    <main>
      <div id="loginBar">
        <label class="who" for="nameSelect">I am</label>
        <select id="nameSelect"></select>
        <input id="pinInput" type="password" inputmode="numeric" placeholder="PIN" maxlength="6" autocomplete="off">
        <button id="loginBtn" class="btn">Log in</button>
      </div>
      <div id="loginError"></div>

      <div id="loggedInBar" hidden>
        <div class="whoLoggedIn">Picking as <b id="loggedInName"></b><button id="switchUserBtn" class="linkBtn">switch</button></div>
        <div id="paceDisplay" class="pace"></div>
      </div>
      <div id="paceWarning" class="paceWarning" hidden></div>

      <div class="tabBar" id="tabBar" hidden>
        <button class="tabBtn active" id="tabScanBtn">Scan</button>
        <button class="tabBtn" id="tabProblemBtn">Problem Rack<span class="tabBadge" id="problemBadge" hidden>0</span></button>
      </div>

      <div id="scanView">
        <div id="scanBox">
          <label for="scanInput">Scan or type a tracking number</label>
          <input id="scanInput" type="text" inputmode="text" autocomplete="off" placeholder="Tracking number">
        </div>

        <div id="loading" hidden>Looking up order…</div>
        <div id="notFound" hidden>
          <div style="font-size:40px;">✕</div>
          <div>No order found for</div>
          <div class="tn" id="notFoundTn"></div>
        </div>

        <div id="result">
          <div class="orderCard">
            <h2 id="ordBuyer">—</h2>
            <div class="orderMeta">
              Tracking: <b id="ordTn"></b><br>
              Items required: <b id="ordCount"></b><span id="mismatchBadge" class="itemsCountBadge" hidden></span>
              <span id="problemFlagBadge" class="flagBadge" hidden>🚩 Problem Rack</span>
            </div>
            <div id="itemsList"></div>
            <div class="verifyBar">
              <div id="verifiedStatus"></div>
              <label class="photoCheck" id="photoCheckRow" hidden>
                <input type="checkbox" id="photoCheckbox"> I checked this matches the photo(s)
              </label>
              <button id="verifyBtn" class="btn" hidden disabled>Mark Verified</button>
              <button id="skipBtn" hidden>Can't find it — Problem Rack</button>
            </div>
          </div>
        </div>

        <div id="scanHint">Scan the next order any time — no need to clear this one first.</div>
      </div>

      <div id="problemView" hidden>
        <div id="problemList"></div>
        <div id="problemEmpty" hidden>Nothing in the Problem Rack right now.</div>
      </div>
    </main>
    <footer>LeveLux · Internal use only</footer>
  </div>

<script>
(function(){
  // ---- CONFIG ----
  var AIRTABLE_TOKEN = "patvgfKRgkTjGpkwQ.0712b5f7904923d0b32046f25d9ac23767d16546628bbcb4ba3fcf7ecb37c07a";
  var BASE_ID = "apppTgdA1jhJ26E6R";
  var TABLE_ID = "tblhZBUPpmAtt3eue"; // Order Photos
  var PASSCODE = "8425";
  var STAFF_NAMES = ["Carolina Leyva","Jason Long","Megan Wilson","Vanessa Ramirez-Salazar","Mariel","Other"];
  var STAFF_PINS = {
    "Carolina Leyva": "1234",
    "Jason Long": "2345",
    "Megan Wilson": "3456",
    "Vanessa Ramirez-Salazar": "4567",
    "Mariel": "5678",
    "Other": "0000"
  };
  var PACE_TARGET_PER_HOUR = 100; // picking target — packing tool uses 55
  var PACE_GRACE_MINUTES = 10;    // don't flag pace until this many minutes into the login session

  var API_BASE = "https://api.airtable.com/v0/" + BASE_ID + "/" + TABLE_ID;

  function authHeaders(){
    return {"Authorization": "Bearer " + AIRTABLE_TOKEN, "Content-Type": "application/json"};
  }

  // ---- Gate (shop-wide passcode) ----
  var gate = document.getElementById('gate');
  var app = document.getElementById('app');
  var gateInput = document.getElementById('gateInput');
  var gateBtn = document.getElementById('gateBtn');
  var gateError = document.getElementById('gateError');

  function tryUnlock(){
    if (gateInput.value === PASSCODE) {
      sessionStorage.setItem('llx_unlocked', '1');
      gate.hidden = true;
      app.hidden = false;
      initApp();
    } else {
      gateError.textContent = "That's not it — try again.";
      gateInput.value = '';
      gateInput.focus();
    }
  }
  gateBtn.addEventListener('click', tryUnlock);
  gateInput.addEventListener('keydown', function(e){ if (e.key === 'Enter') tryUnlock(); });

  try {
    if (sessionStorage.getItem('llx_unlocked') === '1') {
      gate.hidden = true;
      app.hidden = false;
      initApp();
    }
  } catch(e) {}

  // ---- Login (name + personal PIN) ----
  var nameSelect = document.getElementById('nameSelect');
  var pinInput = document.getElementById('pinInput');
  var loginBtn = document.getElementById('loginBtn');
  var loginError = document.getElementById('loginError');
  var loginBar = document.getElementById('loginBar');
  var loggedInBar = document.getElementById('loggedInBar');
  var loggedInName = document.getElementById('loggedInName');
  var switchUserBtn = document.getElementById('switchUserBtn');
  var paceDisplay = document.getElementById('paceDisplay');
  var paceWarning = document.getElementById('paceWarning');

  var currentUser = null;
  var loginTime = null;

  function todayKey(){
    var d = new Date();
    return d.getFullYear() + '-' + (d.getMonth()+1) + '-' + d.getDate();
  }
  function logKey(name){ return 'llx_pickLog_' + name + '_' + todayKey(); }

  function getLog(name){
    try { return JSON.parse(localStorage.getItem(logKey(name)) || '[]'); } catch(e){ return []; }
  }
  function addLogEntry(name){
    var log = getLog(name);
    log.push(Date.now());
    try { localStorage.setItem(logKey(name), JSON.stringify(log)); } catch(e){}
    return log;
  }

  function renderNameSelect(){
    nameSelect.innerHTML = '';
    var placeholder = document.createElement('option');
    placeholder.value = '';
    placeholder.textContent = 'Select your name…';
    nameSelect.appendChild(placeholder);
    STAFF_NAMES.forEach(function(n){
      var o = document.createElement('option');
      o.value = n;
      o.textContent = n;
      nameSelect.appendChild(o);
    });
  }

  function doLogin(){
    var name = nameSelect.value;
    var pin = pinInput.value.trim();
    if (!name) { loginError.textContent = 'Select your name first.'; return; }
    if (!pin || pin !== STAFF_PINS[name]) {
      loginError.textContent = "That PIN doesn't match — try again.";
      pinInput.value = '';
      pinInput.focus();
      return;
    }
    loginError.textContent = '';
    currentUser = name;
    loginTime = Date.now();
    try {
      sessionStorage.setItem('llx_current_user', name);
      sessionStorage.setItem('llx_login_time', String(loginTime));
    } catch(e){}
    showLoggedIn();
  }

  function showLoggedIn(){
    loginBar.hidden = true;
    loginError.textContent = '';
    loggedInBar.hidden = false;
    loggedInName.textContent = currentUser;
    pinInput.value = '';
    tabBar.hidden = false;
    updatePaceDisplay();
    refreshProblemBadge();
    if (scanInput) scanInput.focus();
  }

  function doLogout(){
    currentUser = null;
    loginTime = null;
    try {
      sessionStorage.removeItem('llx_current_user');
      sessionStorage.removeItem('llx_login_time');
    } catch(e){}
    loggedInBar.hidden = true;
    paceWarning.hidden = true;
    tabBar.hidden = true;
    loginBar.hidden = false;
    nameSelect.value = '';
    pinInput.value = '';
    showTab('scan');
    nameSelect.focus();
  }

  loginBtn.addEventListener('click', doLogin);
  pinInput.addEventListener('keydown', function(e){ if (e.key === 'Enter') doLogin(); });
  switchUserBtn.addEventListener('click', doLogout);

  function computeRate(name){
    var log = getLog(name);
    var now = Date.now();
    var oneHourAgo = now - 60*60*1000;
    return log.filter(function(t){ return t >= oneHourAgo; }).length;
  }

  function updatePaceDisplay(){
    if (!currentUser) return;
    var rate = computeRate(currentUser);
    var minutesLoggedIn = loginTime ? (Date.now() - loginTime) / 60000 : 999;
    paceDisplay.textContent = 'Last hour: ' + rate + ' picked · target ' + PACE_TARGET_PER_HOUR + '/hr';
    if (minutesLoggedIn >= PACE_GRACE_MINUTES && rate < PACE_TARGET_PER_HOUR) {
      paceWarning.hidden = false;
      paceWarning.textContent = '⚠️ Pace check — you\'re at ' + rate + '/hr, target is ' + PACE_TARGET_PER_HOUR + '/hr. Pick up the pace!';
    } else {
      paceWarning.hidden = true;
    }
  }

  setInterval(function(){ if (currentUser) updatePaceDisplay(); }, 30000);

  try {
    var savedUser = sessionStorage.getItem('llx_current_user');
    var savedTime = sessionStorage.getItem('llx_login_time');
    if (savedUser && STAFF_NAMES.indexOf(savedUser) !== -1) {
      currentUser = savedUser;
      loginTime = savedTime ? parseInt(savedTime, 10) : Date.now();
    }
  } catch(e){}

  // ---- App init ----
  var scanInput, itemsList, resultEl, notFoundEl, notFoundTn, loadingEl;
  var ordBuyer, ordTn, ordCount, mismatchBadge, problemFlagBadge, verifiedStatus, verifyBtn, skipBtn, photoCheckRow, photoCheckbox;
  var tabBar, tabScanBtn, tabProblemBtn, problemBadge, scanView, problemView, problemList, problemEmpty;
  var currentOrderRecords = []; // raw airtable records for the currently displayed order

  function initApp(){
    scanInput = document.getElementById('scanInput');
    itemsList = document.getElementById('itemsList');
    resultEl = document.getElementById('result');
    notFoundEl = document.getElementById('notFound');
    notFoundTn = document.getElementById('notFoundTn');
    loadingEl = document.getElementById('loading');
    ordBuyer = document.getElementById('ordBuyer');
    ordTn = document.getElementById('ordTn');
    ordCount = document.getElementById('ordCount');
    mismatchBadge = document.getElementById('mismatchBadge');
    problemFlagBadge = document.getElementById('problemFlagBadge');
    verifiedStatus = document.getElementById('verifiedStatus');
    verifyBtn = document.getElementById('verifyBtn');
    skipBtn = document.getElementById('skipBtn');
    photoCheckRow = document.getElementById('photoCheckRow');
    photoCheckbox = document.getElementById('photoCheckbox');
    tabBar = document.getElementById('tabBar');
    tabScanBtn = document.getElementById('tabScanBtn');
    tabProblemBtn = document.getElementById('tabProblemBtn');
    problemBadge = document.getElementById('problemBadge');
    scanView = document.getElementById('scanView');
    problemView = document.getElementById('problemView');
    problemList = document.getElementById('problemList');
    problemEmpty = document.getElementById('problemEmpty');

    renderNameSelect();

    if (currentUser) {
      showLoggedIn();
    } else {
      loginBar.hidden = false;
    }

    scanInput.addEventListener('keydown', function(e){
      if (e.key === 'Enter') {
        e.preventDefault();
        var v = scanInput.value.trim();
        if (v) lookupOrder(v);
      }
    });

    photoCheckbox.addEventListener('change', function(){
      verifyBtn.disabled = !photoCheckbox.checked;
    });

    verifyBtn.addEventListener('click', markVerified);
    skipBtn.addEventListener('click', markSkipped);
    tabScanBtn.addEventListener('click', function(){ showTab('scan'); });
    tabProblemBtn.addEventListener('click', function(){ showTab('problem'); });
  }

  function showTab(which){
    if (which === 'problem') {
      tabScanBtn.classList.remove('active');
      tabProblemBtn.classList.add('active');
      scanView.hidden = true;
      problemView.hidden = false;
      loadProblemRack();
    } else {
      tabProblemBtn.classList.remove('active');
      tabScanBtn.classList.add('active');
      problemView.hidden = true;
      scanView.hidden = false;
    }
  }

  function refreshProblemBadge(){
    var formula = "{Problem Rack}=1";
    var url = API_BASE + "?filterByFormula=" + encodeURIComponent(formula) + "&fields%5B%5D=Tracking%20Number";
    fetch(url, {headers: authHeaders()})
      .then(function(r){ return r.json(); })
      .then(function(data){
        var recs = data.records || [];
        var uniq = {};
        recs.forEach(function(r){ uniq[r.fields['Tracking Number']] = true; });
        var n = Object.keys(uniq).length;
        if (n > 0) { problemBadge.hidden = false; problemBadge.textContent = n; }
        else { problemBadge.hidden = true; }
      })
      .catch(function(){ /* silent — badge just won't update */ });
  }

  function esc(s){ return String(s).replace(/'/g, "\\'"); }

  function lookupOrder(tn){
    resultEl.classList.remove('show');
    notFoundEl.hidden = true;
    loadingEl.hidden = false;
    var formula = "AND({Tracking Number}='" + esc(tn) + "')";
    var url = API_BASE + "?filterByFormula=" + encodeURIComponent(formula);
    fetch(url, {headers: authHeaders()})
      .then(function(r){ return r.json(); })
      .then(function(data){
        loadingEl.hidden = true;
        if (!data.records || data.records.length === 0) {
          notFoundTn.textContent = tn;
          notFoundEl.hidden = false;
          return;
        }
        showOrder(tn, data.records);
      })
      .catch(function(err){
        loadingEl.hidden = true;
        notFoundTn.textContent = tn + " (network error — try again)";
        notFoundEl.hidden = false;
      });
  }

  function showOrder(tn, records){
    currentOrderRecords = records.slice().sort(function(a,b){
      return (a.fields['Item #']||0) - (b.fields['Item #']||0);
    });
    var first = currentOrderRecords[0].fields;
    ordBuyer.textContent = first['Buyer'] || 'Unknown buyer';
    ordTn.textContent = tn;
    var required = first['Order Item Count'];
    ordCount.textContent = (required != null ? required : '—');

    if (required != null && required !== currentOrderRecords.length) {
      mismatchBadge.hidden = false;
      mismatchBadge.classList.add('mismatch');
      mismatchBadge.textContent = currentOrderRecords.length + " on file";
    } else {
      mismatchBadge.hidden = true;
    }

    itemsList.innerHTML = '';
    currentOrderRecords.forEach(function(r){
      var f = r.fields;
      var div = document.createElement('div');
      div.className = 'item';
      var photo = (f['Photo'] && f['Photo'][0]) ? f['Photo'][0].url : null;
      var imgHtml = photo
        ? '<img src="' + photo + '" alt="item photo">'
        : '<div class="noPhoto">No photo</div>';
      div.innerHTML = imgHtml +
        '<div><div class="desc">' + (f['Description']||'Item ' + (f['Item #']||'')) + '</div>' +
        '<div class="subline">' + (f['Brand'] ? f['Brand'] + ' · ' : '') + '$' + (f['Price']!=null?f['Price']:'0') + '</div></div>';
      itemsList.appendChild(div);
    });

    var isVerified = currentOrderRecords.some(function(r){ return !!r.fields['Verified']; });
    var packerName = '';
    currentOrderRecords.forEach(function(r){ if (r.fields['Packer']) packerName = r.fields['Packer']; });
    var isProblem = currentOrderRecords.some(function(r){ return !!r.fields['Problem Rack']; });

    problemFlagBadge.hidden = !isProblem;

    photoCheckbox.checked = false;
    verifyBtn.disabled = true;

    if (isVerified) {
      verifiedStatus.innerHTML = '<div class="verifiedBadge">✓ Verified by ' + (packerName || 'someone') + '</div>';
      verifyBtn.hidden = true;
      photoCheckRow.hidden = true;
      skipBtn.hidden = true;
    } else {
      verifiedStatus.innerHTML = '<div class="verifiedBadge no">Not yet verified</div>';
      photoCheckRow.hidden = !currentUser;
      verifyBtn.hidden = false;
      verifyBtn.textContent = currentUser ? ('Confirm Picked — ' + currentUser) : 'Log in above first';
      if (!currentUser) verifyBtn.disabled = true;
      skipBtn.hidden = !currentUser;
    }

    resultEl.classList.add('show');

    // ready for next scan immediately
    scanInput.value = '';
    scanInput.focus();
  }

  function markVerified(){
    var name = currentUser;
    if (!name) {
      nameSelect.focus();
      return;
    }
    verifyBtn.disabled = true;
    verifyBtn.textContent = 'Saving…';
    var updates = currentOrderRecords.map(function(r){
      return { id: r.id, fields: { "Packer": name, "Verified": true } };
    });
    // Airtable allows up to 10 records per PATCH call
    var batches = [];
    for (var i = 0; i < updates.length; i += 10) batches.push(updates.slice(i, i+10));

    function runBatch(idx){
      if (idx >= batches.length) {
        verifiedStatus.innerHTML = '<div class="verifiedBadge">✓ Verified by ' + name + '</div>';
        verifyBtn.hidden = true;
        photoCheckRow.hidden = true;
        skipBtn.hidden = true;
        addLogEntry(name);
        updatePaceDisplay();
        return;
      }
      fetch(API_BASE, {
        method: 'PATCH',
        headers: authHeaders(),
        body: JSON.stringify({records: batches[idx]})
      }).then(function(r){ return r.json(); })
        .then(function(){ runBatch(idx+1); })
        .catch(function(){
          verifyBtn.disabled = false;
          verifyBtn.textContent = 'Save failed — tap to retry';
        });
    }
    runBatch(0);
  }

  function markSkipped(){
    var name = currentUser;
    if (!name) { nameSelect.focus(); return; }
    skipBtn.disabled = true;
    skipBtn.textContent = 'Saving…';
    var updates = currentOrderRecords.map(function(r){
      return { id: r.id, fields: { "Problem Rack": true, "Problem Flagged By": name } };
    });
    var batches = [];
    for (var i = 0; i < updates.length; i += 10) batches.push(updates.slice(i, i+10));

    function runBatch(idx){
      if (idx >= batches.length) {
        skipBtn.disabled = false;
        skipBtn.textContent = "Can't find it — Problem Rack";
        refreshProblemBadge();
        // move straight to the next scan
        resultEl.classList.remove('show');
        scanInput.value = '';
        scanInput.focus();
        return;
      }
      fetch(API_BASE, {
        method: 'PATCH',
        headers: authHeaders(),
        body: JSON.stringify({records: batches[idx]})
      }).then(function(r){ return r.json(); })
        .then(function(){ runBatch(idx+1); })
        .catch(function(){
          skipBtn.disabled = false;
          skipBtn.textContent = 'Save failed — tap to retry';
        });
    }
    runBatch(0);
  }

  // ---- Problem Rack (built into the same tool — any logged-in staff can resolve) ----
  function loadProblemRack(){
    problemList.innerHTML = '';
    problemEmpty.hidden = true;
    var formula = "{Problem Rack}=1";
    var url = API_BASE + "?filterByFormula=" + encodeURIComponent(formula);
    fetch(url, {headers: authHeaders()})
      .then(function(r){ return r.json(); })
      .then(function(data){
        var recs = data.records || [];
        if (recs.length === 0) {
          problemEmpty.hidden = false;
          problemBadge.hidden = true;
          return;
        }
        // group by tracking number
        var groups = {};
        recs.forEach(function(r){
          var tn = r.fields['Tracking Number'] || '(no tracking #)';
          if (!groups[tn]) groups[tn] = [];
          groups[tn].push(r);
        });
        var tns = Object.keys(groups);
        problemBadge.hidden = false;
        problemBadge.textContent = tns.length;

        tns.forEach(function(tn){
          var group = groups[tn];
          var f = group[0].fields;
          var flaggedBy = '';
          group.forEach(function(r){ if (r.fields['Problem Flagged By']) flaggedBy = r.fields['Problem Flagged By']; });
          var div = document.createElement('div');
          div.className = 'problemCard';
          div.innerHTML =
            '<div class="pmeta">' +
              '<b>' + (f['Buyer'] || 'Unknown buyer') + '</b><br>' +
              'Tracking: <b>' + tn + '</b> · ' + group.length + ' item(s)<br>' +
              'Flagged by: <b>' + (flaggedBy || 'unknown') + '</b>' +
            '</div>' +
            '<button class="btn resolveBtn">Found it — Resolve</button>';
          var btn = div.querySelector('.resolveBtn');
          btn.addEventListener('click', function(){ resolveProblem(tn, group, btn); });
          problemList.appendChild(div);
        });
      })
      .catch(function(){
        problemEmpty.hidden = false;
        problemEmpty.textContent = 'Could not load the Problem Rack — check your connection and try again.';
      });
  }

  function resolveProblem(tn, group, btn){
    var name = currentUser;
    btn.disabled = true;
    btn.textContent = 'Saving…';
    var updates = group.map(function(r){
      return { id: r.id, fields: { "Problem Rack": false, "Problem Resolved By": name } };
    });
    var batches = [];
    for (var i = 0; i < updates.length; i += 10) batches.push(updates.slice(i, i+10));

    function runBatch(idx){
      if (idx >= batches.length) {
        loadProblemRack();
        return;
      }
      fetch(API_BASE, {
        method: 'PATCH',
        headers: authHeaders(),
        body: JSON.stringify({records: batches[idx]})
      }).then(function(r){ return r.json(); })
        .then(function(){ runBatch(idx+1); })
        .catch(function(){
          btn.disabled = false;
          btn.textContent = 'Save failed — tap to retry';
        });
    }
    runBatch(0);
  }

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