feat(ui): convert filters to interactive modal overlay in stock view
Build and Push Fridger Container / Build & Push Fridger Image (push) Successful in 1m17s
Build and Push Fridger Container / Build & Push Fridger Image (push) Successful in 1m17s
This commit is contained in:
+59
-56
@@ -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() {
|
||||
<button
|
||||
onclick="setCategoryFilter('All')"
|
||||
data-filter-cat="All"
|
||||
class="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"
|
||||
class="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"
|
||||
>
|
||||
<div class="w-10 h-10 rounded-xl bg-teal-500/20 text-teal-300 flex items-center justify-center shrink-0">
|
||||
<i data-lucide="layout-grid" class="w-5 h-5"></i>
|
||||
<div class="w-8 h-8 rounded-xl bg-teal-500/20 text-teal-300 flex items-center justify-center shrink-0">
|
||||
<i data-lucide="layout-grid" class="w-4 h-4"></i>
|
||||
</div>
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="flex items-center justify-between gap-1">
|
||||
<h4 class="text-xs sm:text-sm font-extrabold text-white truncate">All Categories</h4>
|
||||
<span id="cat-count-all" class="text-[11px] font-bold px-1.5 py-0.5 rounded-md bg-slate-800 text-slate-400">0</span>
|
||||
<h4 class="text-xs font-bold text-white truncate">All Categories</h4>
|
||||
<span id="cat-count-all" class="text-[10px] font-bold px-1.5 py-0.5 rounded-md bg-slate-800 text-slate-400">0</span>
|
||||
</div>
|
||||
<p class="text-[10px] text-slate-400 truncate">View everything</p>
|
||||
</div>
|
||||
</button>
|
||||
`;
|
||||
@@ -273,17 +273,16 @@ function renderCategoryFilterCards() {
|
||||
<button
|
||||
onclick="setCategoryFilter('${escapeHtml(cat.id)}')"
|
||||
data-filter-cat="${escapeHtml(cat.id)}"
|
||||
class="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"
|
||||
class="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"
|
||||
>
|
||||
<div class="w-10 h-10 rounded-xl bg-slate-800 text-teal-400 flex items-center justify-center shrink-0">
|
||||
<i data-lucide="${escapeHtml(cat.icon || 'package')}" class="w-5 h-5"></i>
|
||||
<div class="w-8 h-8 rounded-xl bg-slate-800 text-teal-400 flex items-center justify-center shrink-0">
|
||||
<i data-lucide="${escapeHtml(cat.icon || 'package')}" class="w-4 h-4"></i>
|
||||
</div>
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="flex items-center justify-between gap-1">
|
||||
<h4 class="text-xs sm:text-sm font-extrabold text-white truncate">${escapeHtml(cat.name)}</h4>
|
||||
<span id="cat-count-${escapeHtml(cat.id.replace(/[^a-zA-Z0-9]/g, ''))}" class="text-[11px] font-bold px-1.5 py-0.5 rounded-md bg-slate-800 text-slate-400">0</span>
|
||||
<h4 class="text-xs font-bold text-white truncate">${escapeHtml(cat.name)}</h4>
|
||||
<span id="cat-count-${escapeHtml(cat.id.replace(/[^a-zA-Z0-9]/g, ''))}" class="text-[10px] font-bold px-1.5 py-0.5 rounded-md bg-slate-800 text-slate-400">0</span>
|
||||
</div>
|
||||
<p class="text-[10px] text-slate-400 truncate">${escapeHtml(cat.id)}</p>
|
||||
</div>
|
||||
</button>
|
||||
`;
|
||||
@@ -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';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user