171 lines
7.0 KiB
HTML
171 lines
7.0 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
||
<title>Pantry</title>
|
||
<link rel="stylesheet" href="style.css">
|
||
</head>
|
||
<body>
|
||
<!--
|
||
pantry-vision's frontend (docs/project-plan.md Phase 17). A single static page, no
|
||
build step, no framework — same "vendored, dependency-free" choice as the digest/
|
||
admin canvas SDKs. Config (the pantry-vision API URL and its bearer token) arrives
|
||
as URL query params from the kitchen-display kiosk's own launch command
|
||
(hosts/kitchen-display/configs/sway/pantry-kiosk), never baked into this file, so
|
||
this stays a plain static asset with no secret in git — see app.js's top comment.
|
||
|
||
Four stock movements, four screens, all reached from Home and all camera-first
|
||
except the last: Unload groceries (book in), Consume article (book out), List
|
||
expired foods (throw away), Edit inventory (the keyboard fallback for when the
|
||
camera got it wrong). #scanner below is ONE camera element, moved into whichever
|
||
flow is running — see app.js's mountScanner(); a second getUserMedia stream on a
|
||
single-webcam kiosk is a black rectangle, not a second camera.
|
||
-->
|
||
<nav id="tabs">
|
||
<button class="tab active" data-tab="home">🏠<span>Home</span></button>
|
||
<button class="tab" data-tab="inventory">🧊<span>Inventory</span></button>
|
||
<button class="tab" data-tab="recipes">🍳<span>Recipes</span></button>
|
||
</nav>
|
||
|
||
<main>
|
||
<section id="home" class="panel active">
|
||
<div class="action-grid">
|
||
<button class="action-btn" data-goto="unload">🛍️<span>Unload groceries</span></button>
|
||
<button class="action-btn" data-goto="consume">🍽️<span>Consume article</span></button>
|
||
<button class="action-btn" data-goto="expired">🗑️<span>List expired foods</span></button>
|
||
<button class="action-btn" data-goto="edit">✏️<span>Edit inventory</span></button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- The camera, mounted into whichever flow is active. -->
|
||
<div id="scanner" hidden>
|
||
<video id="camera-preview" autoplay playsinline muted></video>
|
||
<p id="scan-status" class="hint">Starting camera…</p>
|
||
<p id="camera-error" class="error" hidden></p>
|
||
<button id="capture-now" class="big-btn secondary">Identify now</button>
|
||
<canvas id="captured-frame" hidden></canvas>
|
||
<canvas id="frame-sample" hidden></canvas>
|
||
</div>
|
||
|
||
<!-- ---------------------------------------------------------------- Unload -->
|
||
<section id="unload" class="panel flow">
|
||
<header class="flow-head">
|
||
<button class="back-btn" data-goto="home">‹ Home</button>
|
||
<h1>Unload groceries</h1>
|
||
<span id="unload-count" class="flow-badge"></span>
|
||
</header>
|
||
<div class="scanner-slot"></div>
|
||
|
||
<form id="confirm-form" hidden>
|
||
<p id="f-description" class="lead"></p>
|
||
<label>Article <input id="f-name" type="text" required></label>
|
||
<div class="field-row">
|
||
<label>Category
|
||
<select id="f-category">
|
||
<option value="produce">Produce</option>
|
||
<option value="dairy">Dairy</option>
|
||
<option value="meat">Meat</option>
|
||
<option value="frozen">Frozen</option>
|
||
<option value="pantry">Pantry</option>
|
||
<option value="bakery">Bakery</option>
|
||
<option value="beverage">Beverage</option>
|
||
<option value="other">Other</option>
|
||
</select>
|
||
</label>
|
||
<label>Put it in
|
||
<select id="f-placement">
|
||
<option value="fridge">🧊 Fridge</option>
|
||
<option value="freezer">❄️ Freezer</option>
|
||
<option value="cupboard">🚪 Cupboard</option>
|
||
<option value="counter">🧺 Counter</option>
|
||
</select>
|
||
</label>
|
||
</div>
|
||
<label>Best before <input id="f-date" type="date" required></label>
|
||
<p id="f-date-source" class="hint"></p>
|
||
<div class="field-row">
|
||
<label>Packs <input id="f-packages" type="number" min="1" step="1" value="1"></label>
|
||
<label>Per pack <input id="f-units" type="number" min="1" step="1" value="1"></label>
|
||
</div>
|
||
<p id="f-total" class="total-line"></p>
|
||
<p id="f-have" class="hint"></p>
|
||
<p id="f-confidence" class="hint"></p>
|
||
<div class="form-actions">
|
||
<button type="button" id="skip-btn" class="big-btn secondary">Skip</button>
|
||
<button type="submit" id="confirm-btn" class="big-btn primary">Confirm & next</button>
|
||
</div>
|
||
<p id="confirm-status" class="hint"></p>
|
||
</form>
|
||
</section>
|
||
|
||
<!-- --------------------------------------------------------------- Consume -->
|
||
<section id="consume" class="panel flow">
|
||
<header class="flow-head">
|
||
<button class="back-btn" data-goto="home">‹ Home</button>
|
||
<h1>Consume article</h1>
|
||
</header>
|
||
<div class="scanner-slot"></div>
|
||
|
||
<div id="consume-result" hidden>
|
||
<p id="consume-identified" class="lead"></p>
|
||
<div id="consume-candidates" class="card-list"></div>
|
||
<div id="consume-amount" hidden>
|
||
<p id="consume-chosen" class="lead"></p>
|
||
<div id="consume-quick" class="quick-row"></div>
|
||
<label>How many? <input id="consume-qty" type="number" min="1" step="1" value="1"></label>
|
||
<div class="form-actions">
|
||
<button type="button" id="consume-cancel" class="big-btn secondary">Cancel</button>
|
||
<button type="button" id="consume-confirm" class="big-btn primary">Book out</button>
|
||
</div>
|
||
</div>
|
||
<p id="consume-status" class="hint"></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- --------------------------------------------------------------- Expired -->
|
||
<section id="expired" class="panel flow">
|
||
<header class="flow-head">
|
||
<button class="back-btn" data-goto="home">‹ Home</button>
|
||
<h1>Expired foods</h1>
|
||
<button id="expired-scan-btn" class="flow-action">📷 Scan to remove</button>
|
||
</header>
|
||
<div class="scanner-slot"></div>
|
||
<p id="expired-status" class="hint"></p>
|
||
<div id="expired-list" class="card-list"><p class="hint">Loading…</p></div>
|
||
</section>
|
||
|
||
<!-- ------------------------------------------------------------------ Edit -->
|
||
<section id="edit" class="panel flow">
|
||
<header class="flow-head">
|
||
<button class="back-btn" data-goto="home">‹ Home</button>
|
||
<h1>Edit inventory</h1>
|
||
</header>
|
||
<p class="hint">
|
||
Everything booked in, same kind added up across brands. Open a line to correct one
|
||
brand exactly.
|
||
</p>
|
||
<p id="edit-status" class="hint"></p>
|
||
<div id="edit-list" class="card-list"><p class="hint">Loading…</p></div>
|
||
</section>
|
||
|
||
<!-- ------------------------------------------------------------- Reference -->
|
||
<section id="inventory" class="panel">
|
||
<div id="inventory-list" class="card-list">
|
||
<p class="hint">Loading…</p>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="recipes" class="panel">
|
||
<div id="recipes-list" class="card-list">
|
||
<p class="hint">Loading…</p>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
|
||
<p id="toast" hidden></p>
|
||
|
||
<script src="app.js"></script>
|
||
</body>
|
||
</html>
|