feat(ui): update manager interface and remove full stock display from /manage
Build and Push Fridger Container / Build & Push Fridger Image (push) Successful in 1m21s

This commit is contained in:
2026-10-10 23:57:24 +02:00
parent 56eed473c7
commit 0cebd9ff75
2 changed files with 55 additions and 42 deletions
+29 -13
View File
@@ -92,9 +92,9 @@ function setRoute(path) {
stockBtn.className = inactiveClass; stockBtn.className = inactiveClass;
managePage.classList.remove('hidden'); managePage.classList.remove('hidden');
stockPage.classList.add('hidden'); stockPage.classList.add('hidden');
subTitle.textContent = 'Tablet Station'; subTitle.textContent = 'Manager';
resetTabletManageStation(); resetTabletManageStation();
renderTabletProductPicker(); renderTabletProductPicker('');
} }
initLucide(); initLucide();
@@ -145,7 +145,8 @@ async function loadItems() {
if (state.currentRoute === '/') { if (state.currentRoute === '/') {
renderStockView(); renderStockView();
} else { } else {
renderTabletProductPicker(); const query = document.getElementById('tablet-search-input')?.value || '';
renderTabletProductPicker(query);
} }
} }
} catch (err) { } catch (err) {
@@ -307,7 +308,8 @@ function renderStockView() {
} }
// ---------------------------------------------------- // ----------------------------------------------------
// ROUTE 2: /manage (TABLET STATION WORKFLOW) // ----------------------------------------------------
// ROUTE 2: /manage (MANAGER WORKFLOW)
// ---------------------------------------------------- // ----------------------------------------------------
function resetTabletManageStation() { function resetTabletManageStation() {
@@ -315,7 +317,12 @@ function resetTabletManageStation() {
state.manage.action = null; state.manage.action = null;
document.getElementById('tablet-step-select').classList.remove('hidden'); document.getElementById('tablet-step-select').classList.remove('hidden');
document.getElementById('tablet-step-action').classList.add('hidden'); document.getElementById('tablet-step-action').classList.add('hidden');
document.getElementById('tablet-search-input').value = ''; const searchInput = document.getElementById('tablet-search-input');
if (searchInput) searchInput.value = '';
const resultsContainer = document.getElementById('tablet-search-results-container');
if (resultsContainer) resultsContainer.classList.add('hidden');
const picker = document.getElementById('tablet-product-picker');
if (picker) picker.innerHTML = '';
} }
function handleTabletSearch(val) { function handleTabletSearch(val) {
@@ -331,27 +338,37 @@ function handleTabletSearch(val) {
} }
function renderTabletProductPicker(filterQuery = '') { function renderTabletProductPicker(filterQuery = '') {
const container = document.getElementById('tablet-product-picker'); const picker = document.getElementById('tablet-product-picker');
if (!container) return; const resultsContainer = document.getElementById('tablet-search-results-container');
if (!picker || !resultsContainer) return;
const query = filterQuery.toLowerCase().trim(); const query = filterQuery.toLowerCase().trim();
// Only display search results if user has entered a search query
if (!query) {
resultsContainer.classList.add('hidden');
picker.innerHTML = '';
return;
}
resultsContainer.classList.remove('hidden');
const matched = state.items.filter(i => { const matched = state.items.filter(i => {
if (!query) return true;
return (i.name && i.name.toLowerCase().includes(query)) || return (i.name && i.name.toLowerCase().includes(query)) ||
(i.brand && i.brand.toLowerCase().includes(query)) || (i.brand && i.brand.toLowerCase().includes(query)) ||
(i.barcode && i.barcode.includes(query)); (i.barcode && i.barcode.includes(query));
}); });
if (matched.length === 0) { if (matched.length === 0) {
container.innerHTML = ` picker.innerHTML = `
<div class="col-span-full py-4 text-center text-xs text-slate-500"> <div class="col-span-full py-4 text-center text-xs sm:text-sm text-slate-400">
No matching product found. Scan barcode or tap "Add Manually"! No matching product found. Use "Scan Barcode" or tap "Add Manually".
</div> </div>
`; `;
return; return;
} }
container.innerHTML = matched.map(item => ` picker.innerHTML = matched.map(item => `
<button <button
onclick="forwardToProductActionById(${item.id})" onclick="forwardToProductActionById(${item.id})"
class="p-3 rounded-2xl bg-slate-950 hover:bg-slate-800/80 border border-slate-800/90 text-left flex items-center gap-3 transition active:scale-95 touch-manipulation min-h-[52px]" class="p-3 rounded-2xl bg-slate-950 hover:bg-slate-800/80 border border-slate-800/90 text-left flex items-center gap-3 transition active:scale-95 touch-manipulation min-h-[52px]"
@@ -419,7 +436,6 @@ function forwardToProductAction(item) {
function cancelActionAndReturnToManage() { function cancelActionAndReturnToManage() {
resetTabletManageStation(); resetTabletManageStation();
renderTabletProductPicker();
} }
function setActionType(action) { function setActionType(action) {
+25 -28
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Fridger - Current Stock & Tablet Manager</title> <title>Fridger - Current Stock & Manager</title>
<!-- Tailwind CSS --> <!-- Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script> <script src="https://cdn.tailwindcss.com"></script>
@@ -62,14 +62,14 @@
<span>Current Stock</span> <span>Current Stock</span>
</button> </button>
<!-- 2. Tablet Manage (/manage) --> <!-- 2. Manager (/manage) -->
<button <button
id="nav-manage-btn" id="nav-manage-btn"
onclick="navigateTo('/manage')" onclick="navigateTo('/manage')"
class="flex items-center justify-center gap-2 px-3.5 sm:px-6 py-2.5 sm:py-3 rounded-xl text-xs sm:text-sm font-bold transition-all text-slate-300 hover:text-white hover:bg-slate-800/80 active:scale-95 touch-manipulation min-h-[44px]" class="flex items-center justify-center gap-2 px-3.5 sm:px-6 py-2.5 sm:py-3 rounded-xl text-xs sm:text-sm font-bold transition-all text-slate-300 hover:text-white hover:bg-slate-800/80 active:scale-95 touch-manipulation min-h-[44px]"
> >
<i data-lucide="tablet" class="w-4 h-4 sm:w-5 sm:h-5 text-teal-400"></i> <i data-lucide="sliders-horizontal" class="w-4 h-4 sm:w-5 sm:h-5 text-teal-400"></i>
<span>Tablet Manage</span> <span>Manager</span>
</button> </button>
</div> </div>
@@ -148,10 +148,10 @@
🧊 🧊
</div> </div>
<h3 class="text-lg font-bold text-white mb-1">No items in stock</h3> <h3 class="text-lg font-bold text-white mb-1">No items in stock</h3>
<p class="text-xs sm:text-sm text-slate-400 max-w-xs mx-auto mb-6">Use the tablet manage station to scan or add items.</p> <p class="text-xs sm:text-sm text-slate-400 max-w-xs mx-auto mb-6">Use Manager to scan or add items.</p>
<button onclick="navigateTo('/manage')" class="px-6 py-3 rounded-xl bg-teal-500 hover:bg-teal-400 text-white text-sm font-bold flex items-center gap-2 shadow-lg shadow-teal-500/20 active:scale-95 touch-manipulation mx-auto"> <button onclick="navigateTo('/manage')" class="px-6 py-3 rounded-xl bg-teal-500 hover:bg-teal-400 text-white text-sm font-bold flex items-center gap-2 shadow-lg shadow-teal-500/20 active:scale-95 touch-manipulation mx-auto">
<i data-lucide="tablet" class="w-5 h-5"></i> <i data-lucide="sliders-horizontal" class="w-5 h-5"></i>
<span>Go to Tablet Manage (/manage)</span> <span>Go to Manager (/manage)</span>
</button> </button>
</div> </div>
</main> </main>
@@ -160,28 +160,25 @@
<!-- ======================================================== --> <!-- ======================================================== -->
<!-- 2. TABLET STATION: /manage --> <!-- 2. MANAGER: /manage -->
<!-- ======================================================== --> <!-- ======================================================== -->
<div id="manage-view-page" class="hidden flex-1 flex flex-col"> <div id="manage-view-page" class="hidden flex-1 flex flex-col">
<main class="flex-1 max-w-4xl mx-auto px-3 sm:px-6 py-4 w-full space-y-4"> <main class="flex-1 max-w-3xl mx-auto px-3 sm:px-6 py-4 sm:py-6 w-full space-y-4">
<!-- STEP 1: SCAN / SEARCH / ADD MANUALLY --> <!-- STEP 1: SCAN / SEARCH / ADD MANUALLY -->
<div id="tablet-step-select" class="bg-slate-900 border border-slate-800 rounded-3xl p-4 sm:p-6 shadow-xl space-y-4"> <div id="tablet-step-select" class="bg-slate-900 border border-slate-800 rounded-3xl p-5 sm:p-7 shadow-xl space-y-5">
<div class="flex items-center justify-between"> <div class="flex items-center justify-between gap-2">
<div class="flex items-center gap-2">
<div class="w-8 h-8 rounded-xl bg-teal-500/20 text-teal-300 flex items-center justify-center text-sm font-black">1</div>
<div> <div>
<h2 class="text-base sm:text-lg font-extrabold text-white">Tablet Scanner & Product Finder</h2> <h2 class="text-lg sm:text-xl font-extrabold text-white">Manager</h2>
<p class="text-xs text-slate-400">Scan product barcode, search display, or add manually</p> <p class="text-xs sm:text-sm text-slate-400">Scan barcode, search product, or add manually</p>
</div>
</div> </div>
<!-- Add Manually Button (Prominent when scan or search don't work) --> <!-- Add Manually Button -->
<button <button
onclick="openItemModal()" onclick="openItemModal()"
class="px-3.5 sm:px-4 py-2 rounded-xl bg-slate-800 hover:bg-slate-700 text-teal-300 border border-teal-500/30 text-xs sm:text-sm font-bold flex items-center gap-1.5 active:scale-95 touch-manipulation shadow-sm shrink-0" class="px-4 py-2.5 rounded-xl bg-slate-800 hover:bg-slate-700 text-teal-300 border border-teal-500/30 text-xs sm:text-sm font-bold flex items-center gap-1.5 active:scale-95 touch-manipulation shadow-sm shrink-0"
> >
<i data-lucide="plus" class="w-4 h-4"></i> <i data-lucide="plus" class="w-4 h-4"></i>
<span>Add Manually</span> <span>Add Manually</span>
@@ -193,7 +190,7 @@
<!-- Big Camera Scanner Touch Launch --> <!-- Big Camera Scanner Touch Launch -->
<button <button
onclick="openScannerModal()" onclick="openScannerModal()"
class="sm:col-span-1 p-4 rounded-2xl bg-gradient-to-r from-teal-500 to-emerald-600 hover:from-teal-400 hover:to-emerald-500 text-white font-extrabold flex items-center justify-center gap-3 shadow-lg shadow-teal-500/25 active:scale-95 touch-manipulation min-h-[58px]" class="sm:col-span-1 p-4 rounded-2xl bg-gradient-to-r from-teal-500 to-emerald-600 hover:from-teal-400 hover:to-emerald-500 text-white font-extrabold flex items-center justify-center gap-3 shadow-lg shadow-teal-500/25 active:scale-95 touch-manipulation min-h-[60px]"
> >
<i data-lucide="scan-barcode" class="w-6 h-6"></i> <i data-lucide="scan-barcode" class="w-6 h-6"></i>
<span class="text-sm sm:text-base">Scan Barcode</span> <span class="text-sm sm:text-base">Scan Barcode</span>
@@ -205,18 +202,18 @@
<input <input
type="text" type="text"
id="tablet-search-input" id="tablet-search-input"
placeholder="Type product name, brand, or barcode..." placeholder="Search product name, brand, or barcode..."
oninput="handleTabletSearch(this.value)" oninput="handleTabletSearch(this.value)"
class="w-full bg-slate-950 border border-slate-800 focus:border-teal-500 rounded-2xl pl-12 pr-4 py-3.5 text-sm sm:text-base text-white placeholder-slate-500 outline-none transition min-h-[58px]" class="w-full bg-slate-950 border border-slate-800 focus:border-teal-500 rounded-2xl pl-12 pr-4 py-3.5 text-sm sm:text-base text-white placeholder-slate-500 outline-none transition min-h-[60px]"
> >
</div> </div>
</div> </div>
<!-- Touch Display Product Picker --> <!-- Matching Search Results Container (Only shows when searching) -->
<div class="space-y-1.5 pt-2"> <div id="tablet-search-results-container" class="hidden space-y-2 pt-3 border-t border-slate-800">
<label class="text-xs font-bold text-slate-400 uppercase tracking-wider block">Or tap a product from stock:</label> <label class="text-xs font-bold text-teal-400 uppercase tracking-wider block">Search Results:</label>
<div id="tablet-product-picker" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2.5 max-h-56 overflow-y-auto p-1 scrollbar-none"> <div id="tablet-product-picker" class="grid grid-cols-1 sm:grid-cols-2 gap-2.5 max-h-64 overflow-y-auto p-1 scrollbar-none">
<!-- Populated dynamically --> <!-- Populated dynamically when user searches -->
</div> </div>
</div> </div>
@@ -474,7 +471,7 @@
<div class="w-8 h-8 rounded-xl bg-teal-500/10 text-teal-400 flex items-center justify-center"> <div class="w-8 h-8 rounded-xl bg-teal-500/10 text-teal-400 flex items-center justify-center">
<i data-lucide="scan-barcode" class="w-5 h-5"></i> <i data-lucide="scan-barcode" class="w-5 h-5"></i>
</div> </div>
<span class="font-extrabold text-white text-base">Tablet Barcode Scanner</span> <span class="font-extrabold text-white text-base">Barcode Scanner</span>
</div> </div>
<button onclick="closeScannerModal()" class="text-slate-400 hover:text-white p-2 rounded-xl bg-slate-800/60 touch-manipulation"> <button onclick="closeScannerModal()" class="text-slate-400 hover:text-white p-2 rounded-xl bg-slate-800/60 touch-manipulation">
<i data-lucide="x" class="w-5 h-5"></i> <i data-lucide="x" class="w-5 h-5"></i>
@@ -492,7 +489,7 @@
<!-- Status & Manual fallback --> <!-- Status & Manual fallback -->
<div class="p-4 bg-slate-900 space-y-3"> <div class="p-4 bg-slate-900 space-y-3">
<div id="scanner-status" class="text-xs sm:text-sm text-center text-slate-400 font-medium"> <div id="scanner-status" class="text-xs sm:text-sm text-center text-slate-400 font-medium">
Hold product barcode in front of tablet camera Hold product barcode in front of camera
</div> </div>
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">