The CSS lived at public/pos/fa/all.min.css but its url() references
used ../webfonts/..., which from that location resolves to
/pos/webfonts/... rather than /pos/fa/webfonts/. The woff2 was at
the latter, so the browser silently 404'd every font request and
the icons rendered as tofu boxes.
The original FA 6.5.2 CSS ships with ../webfonts/... because it
assumes the CSS sits in a sibling css/ subdirectory next to webfonts/.
Ours is one level deeper, so the path is now plain webfonts/....
Bump SW cache to v15 so installed tills pick up the corrected CSS.
Co-Authored-By: Claude <noreply@anthropic.com>
Each stock item now renders a Font Awesome icon in the catalog grid
in place of the generic '?' initials. The icon comes from the item's
category, set on the categories collection's new 'icon' field (e.g.
'fa-solid fa-bolt' for Fasteners). All 10 active categories seeded
with sensible defaults; can be edited per-row in PB admin.
Match logic lives in pos-service.listActiveStockCatalog: it pulls the
categories matcher table, then assigns each item by:
1. category.match_brands (against item text or supplier's supply_tags)
2. category.match_supplier_tags
3. category.match_keywords (longest first so 'hydraulic hose' beats 'hose')
4. the 'Unknown / Other' catch-all is excluded from matching — anything
with no match simply gets the initials fallback
The matcher table is in PB (the existing match_keywords/match_supplier_tags
/match_brands fields on categories), so admins can tune coverage without
a deploy. Two keyword additions to Fasteners (allen cap, set screw) and
Cutting Tools (tap, drill, chuck) lifted the live match rate from 67% to
71% (298/418 items across 8 categories).
FA 6.5.2 Free, solid only, bundled under public/pos/fa/ (256KB total:
100KB CSS + 156KB solid woff2). Both the CSS and the woff2 are in the
service worker APP_SHELL so icons render offline. No CDN dependency.
Co-Authored-By: Claude <noreply@anthropic.com>
The till was painting all 373 active stock items at once, which is slow
and buries the stock staff actually reach for. The catalog now comes back
newest-first (PosCatalogItem carries created) and renders 50 at a time,
with a Show-more button that also auto-loads as it scrolls into view.
Header reads 'Recently added' when browsing and 'Results' once a search
or category is applied; changing either resets paging to the first chunk.
Scroll position is preserved across re-renders so adding to the cart no
longer throws the operator back to the top of the list.
Co-Authored-By: Claude <noreply@anthropic.com>
The Include-prices toggle drives both the on-screen slip and the
Bluetooth thermal print, so what prints matches what the operator saw.
Co-Authored-By: Claude <noreply@anthropic.com>
Method split now reads pos_sales.payment_method directly. The four
method rows cashup already renders (cash/card/eft/account) would have
been permanently R0 for eft and account under a cash/card-only backend.
Co-Authored-By: Claude <noreply@anthropic.com>
Payment method now read from pos_sales.payment_method rather than
sniffed out of an order's notes with regexes.
Co-Authored-By: Claude <noreply@anthropic.com>
Sends client_ref (the till's localId) so the offline queue can retry a
sale that already landed without recording it twice. Customer search
moves to /api/v1/pos/customers and now carries the company name for the
delivery-note slip.
Co-Authored-By: Claude <noreply@anthropic.com>
pb-config.js deliberately not copied — it hardcoded a PocketBase
superuser email/password in client-shipped JS.
Co-Authored-By: Claude <noreply@anthropic.com>