From 7f9d58c3fd0467b2936599b53df412b9ee0287bf Mon Sep 17 00:00:00 2001 From: max Date: Sun, 11 Oct 2026 00:03:30 +0200 Subject: [PATCH] feat(ui): convert filters to interactive modal overlay in stock view --- public/app.js | 115 ++++++++++++++++--------------- public/index.html | 169 +++++++++++++++++++++++----------------------- 2 files changed, 142 insertions(+), 142 deletions(-) diff --git a/public/app.js b/public/app.js index 6c2c673..fbc7b27 100644 --- a/public/app.js +++ b/public/app.js @@ -59,8 +59,6 @@ function handleInitialRoute() { const path = window.location.pathname; if (path === '/manage' || path.startsWith('/manage')) { setRoute('/manage'); - } else if (path === '/filters' || path.startsWith('/filters')) { - setRoute('/filters'); } else { setRoute('/'); } @@ -72,48 +70,30 @@ function navigateTo(path) { } function setRoute(path) { - if (path === '/manage' || path.startsWith('/manage')) { - state.currentRoute = '/manage'; - } else if (path === '/filters' || path.startsWith('/filters')) { - state.currentRoute = '/filters'; - } else { - state.currentRoute = '/'; - } + state.currentRoute = path === '/manage' ? '/manage' : '/'; const stockBtn = document.getElementById('nav-stock-btn'); - const filtersBtn = document.getElementById('nav-filters-btn'); const manageBtn = document.getElementById('nav-manage-btn'); const stockPage = document.getElementById('stock-view-page'); - const filtersPage = document.getElementById('filters-view-page'); const managePage = document.getElementById('manage-view-page'); const subTitle = document.getElementById('page-subtitle'); - const activeClass = 'flex items-center justify-center gap-1.5 sm:gap-2 px-3 sm:px-5 py-2.5 sm:py-3 rounded-xl text-xs sm:text-sm font-bold transition-all bg-teal-500 text-white shadow-md active:scale-95 touch-manipulation min-h-[44px]'; - const inactiveClass = 'relative flex items-center justify-center gap-1.5 sm:gap-2 px-3 sm:px-5 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]'; - - // Hide all pages first - stockPage.classList.add('hidden'); - filtersPage.classList.add('hidden'); - managePage.classList.add('hidden'); - - stockBtn.className = inactiveClass; - filtersBtn.className = inactiveClass; - manageBtn.className = inactiveClass; + const activeClass = 'flex items-center justify-center gap-2 px-4 sm:px-6 py-2.5 sm:py-3 rounded-xl text-xs sm:text-sm font-bold transition-all bg-teal-500 text-white shadow-md active:scale-95 touch-manipulation min-h-[44px]'; + const inactiveClass = 'flex items-center justify-center gap-2 px-4 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]'; if (state.currentRoute === '/') { stockBtn.className = activeClass; + manageBtn.className = inactiveClass; stockPage.classList.remove('hidden'); + managePage.classList.add('hidden'); subTitle.textContent = 'Current Stock'; renderStockView(); - } else if (state.currentRoute === '/filters') { - filtersBtn.className = activeClass; - filtersPage.classList.remove('hidden'); - subTitle.textContent = 'Filter Stock'; - renderFilterTabView(); } else { manageBtn.className = activeClass; + stockBtn.className = inactiveClass; managePage.classList.remove('hidden'); + stockPage.classList.add('hidden'); subTitle.textContent = 'Manager'; resetTabletManageStation(); renderTabletProductPicker(''); @@ -123,6 +103,29 @@ function setRoute(path) { initLucide(); } +// ---------------------------------------------------- +// Filter Overlay Modal Handlers +// ---------------------------------------------------- + +function openFilterOverlay() { + const modal = document.getElementById('filter-modal'); + if (modal) { + modal.classList.remove('hidden'); + updateFilterUIState(); + initLucide(); + } +} + +function closeFilterOverlay() { + const modal = document.getElementById('filter-modal'); + if (modal) { + modal.classList.add('hidden'); + if (state.currentRoute === '/') { + renderStockView(); + } + } +} + // ---------------------------------------------------- // API Calls // ---------------------------------------------------- @@ -173,8 +176,6 @@ async function loadItems() { state.items = await res.json(); if (state.currentRoute === '/') { renderStockView(); - } else if (state.currentRoute === '/filters') { - renderFilterTabView(); } else { const query = document.getElementById('tablet-search-input')?.value || ''; renderTabletProductPicker(query); @@ -215,7 +216,7 @@ function clearSearch() { } // ---------------------------------------------------- -// ROUTE 2: /filters (DEDICATED FILTERS TAB) +// FILTER OVERLAY STATE & SELECTION // ---------------------------------------------------- function setStatusFilter(status) { @@ -253,17 +254,16 @@ function renderCategoryFilterCards() { `; @@ -273,17 +273,16 @@ function renderCategoryFilterCards() { `; @@ -293,10 +292,6 @@ function renderCategoryFilterCards() { initLucide(); } -function renderFilterTabView() { - updateFilterUIState(); -} - function updateFilterUIState() { // 1. Update Pack State cards highlight & counts const allItems = state.allItems || []; @@ -321,9 +316,9 @@ function updateFilterUIState() { const status = card.getAttribute('data-filter-status'); const isSelected = state.filters.status === status; if (isSelected) { - card.className = 'filter-status-card flex-1 min-w-[140px] sm:min-w-[160px] p-4 rounded-2xl border-2 text-left flex flex-col justify-between space-y-3 transition-all active:scale-95 touch-manipulation bg-teal-500/20 border-teal-500 text-white shadow-lg shadow-teal-500/20 ring-2 ring-teal-500/30'; + card.className = 'filter-status-card flex-1 min-w-[125px] p-3 rounded-2xl border-2 text-left flex flex-col justify-between space-y-2 transition-all active:scale-95 touch-manipulation bg-teal-500/20 border-teal-500 text-white shadow-lg shadow-teal-500/20 ring-2 ring-teal-500/30'; } else { - card.className = 'filter-status-card flex-1 min-w-[140px] sm:min-w-[160px] p-4 rounded-2xl border text-left flex flex-col justify-between space-y-3 transition-all active:scale-95 touch-manipulation bg-slate-900 border-slate-800 text-slate-300 hover:border-slate-700'; + card.className = 'filter-status-card flex-1 min-w-[125px] p-3 rounded-2xl border text-left flex flex-col justify-between space-y-2 transition-all active:scale-95 touch-manipulation bg-slate-950 border-slate-800 text-slate-300 hover:border-slate-700'; } }); @@ -346,24 +341,32 @@ function updateFilterUIState() { const cat = card.getAttribute('data-filter-cat'); const isSelected = state.filters.category === cat; if (isSelected) { - card.className = 'filter-cat-card p-3 sm:p-4 rounded-2xl border-2 text-left flex items-center gap-3 transition-all active:scale-95 touch-manipulation min-h-[64px] bg-teal-500/20 border-teal-500 text-white shadow-lg shadow-teal-500/20 ring-2 ring-teal-500/30'; + card.className = 'filter-cat-card p-3 rounded-2xl border-2 text-left flex items-center gap-2.5 transition-all active:scale-95 touch-manipulation min-h-[56px] bg-teal-500/20 border-teal-500 text-white shadow-lg shadow-teal-500/20 ring-2 ring-teal-500/30'; } else { - card.className = 'filter-cat-card p-3 sm:p-4 rounded-2xl border text-left flex items-center gap-3 transition-all active:scale-95 touch-manipulation min-h-[64px] bg-slate-900 border-slate-800 text-slate-300 hover:border-slate-700'; + card.className = 'filter-cat-card p-3 rounded-2xl border text-left flex items-center gap-2.5 transition-all active:scale-95 touch-manipulation min-h-[56px] bg-slate-950 border-slate-800 text-slate-300 hover:border-slate-700'; } }); - // 3. Top Navigation Badge - const navBadge = document.getElementById('nav-filter-badge'); + // 3. Filter Trigger Button Badge on Stock Page let activeFilterCount = 0; if (state.filters.category !== 'All') activeFilterCount++; if (state.filters.status !== 'all') activeFilterCount++; - if (navBadge) { + const triggerBtn = document.getElementById('filter-trigger-btn'); + const stockFilterBadge = document.getElementById('stock-filter-badge'); + + if (stockFilterBadge) { if (activeFilterCount > 0) { - navBadge.textContent = activeFilterCount; - navBadge.classList.remove('hidden'); + stockFilterBadge.textContent = activeFilterCount; + stockFilterBadge.classList.remove('hidden'); + if (triggerBtn) { + triggerBtn.className = 'px-4 py-2.5 rounded-xl bg-teal-500/20 hover:bg-teal-500/30 text-teal-300 border border-teal-500/50 text-xs sm:text-sm font-bold flex items-center gap-2 shrink-0 min-h-[42px] touch-manipulation transition shadow-sm active:scale-95'; + } } else { - navBadge.classList.add('hidden'); + stockFilterBadge.classList.add('hidden'); + if (triggerBtn) { + triggerBtn.className = 'px-4 py-2.5 rounded-xl bg-slate-900 hover:bg-slate-800 text-slate-300 border border-slate-800 text-xs sm:text-sm font-bold flex items-center gap-2 shrink-0 min-h-[42px] touch-manipulation transition shadow-sm active:scale-95'; + } } } diff --git a/public/index.html b/public/index.html index bc96319..737581e 100644 --- a/public/index.html +++ b/public/index.html @@ -56,28 +56,17 @@ - - - - + - - @@ -162,8 +164,8 @@
🧊
-

No items in stock

-

No matching items found with the current filters.

+

No items match your filter

+

Try resetting filters or adding items via Manager.

- + -