diff --git a/public/pos/pos-app.js b/public/pos/pos-app.js
index e4907d4..ead06ef 100644
--- a/public/pos/pos-app.js
+++ b/public/pos/pos-app.js
@@ -19,9 +19,17 @@ const state = {
customer: null,
paymentMethod: null,
cashGiven: 0,
- letterhead: null
+ letterhead: null,
+ // How many rows of the current filter are rendered. The full catalog
+ // is several hundred items; painting them all makes the till sluggish
+ // and buries the stock staff actually reach for.
+ limit: 0
};
+// Rows rendered per chunk. The catalog arrives newest-first, so the
+// default view is effectively "recently added".
+const PAGE = 50;
+
// ---------------- IndexedDB ----------------
const DB_NAME='pos', DB_VER=1, STORE_PRODUCTS='products', STORE_QUEUE='queue';
let dbPromise = null;
@@ -148,6 +156,7 @@ function buildCategories(){
state.activeCat = v === '__uncat' ? '__uncat' : v;
closeCatMenu();
buildCategories();
+ resetPaging();
render();
});
});
@@ -190,6 +199,11 @@ function filteredProducts(){
});
}
+/** Call whenever the filter changes, so a new result set starts at the top. */
+function resetPaging(){
+ state.limit = PAGE;
+}
+
function render(){
const list = filteredProducts();
const cat = document.getElementById('catalog');
@@ -197,7 +211,19 @@ function render(){
cat.innerHTML = '
No matches
Try a different search or category.
';
return;
}
- cat.innerHTML = list.map(p=>{
+ if(!state.limit) state.limit = PAGE;
+ const shown = list.slice(0, state.limit);
+ const more = list.length - shown.length;
+ // Keep the scroll position across re-renders (adding to the cart calls
+ // render()), otherwise the till jumps back to the top on every tap.
+ const scrollTop = cat.scrollTop;
+
+ const browsing = !state.search.trim() && state.activeCat === 'all';
+ const heading = browsing ? 'Recently added' : 'Results';
+
+ cat.innerHTML =
+ `