WFDASH-WEBAPP/public
Dave bcb0e1a7d0 feat(pos): tiered catalog search — word order, plurals, glued SKUs
The till filtered the catalog with one case-insensitive includes() over
sku + description, so word order decided whether you got anything:
"nuts m20" returned 0 hits while "m20 nuts" returned 1. The filter also
checked sku_normalised, brand and search_text — fields that exist on
price_list but not on a stock_items row — so three of its five clauses
could never fire, and name was never searched at all.

Search moves into public/pos/pos-search.js, unit-tested from
src/lib/pos-search.test.ts. Every tier is a strict superset of the old
filter, so nothing that used to match stops matching.

  exact      whole query as a run
  squish     punctuation/spacing removed, so M20NUT finds M20 Hex Nut
  tokens     every word present in any order
  plural     "nuts" also tries "nut"
  glued      "M20NUT" -> M20 AND NUT on letter/digit boundaries

Measured on the live 3,591-row catalog: "bolts" 0 -> 884 (884 real bolt
rows, and no row literally says "bolts"), "nuts m20" 0 -> 12, "nut hex"
0 -> 13, "washers flat" 0 -> 14, M20NUT 1 -> 12, zero lost matches.
A plural widens to exactly the union with its singular, asserted per pair.

Widening is safe because both step-2 features are shaped as supersets:
plural forms are alternatives inside one clause, while split parts are
separate required clauses. Making split parts alternatives instead
reduces "M20NUT" to "has M20" — 242 rows. Edit-distance fuzzy matching
was measured and rejected: "nuts" 15 -> 172, "m-20-n-u-t" -> 2,481.

Also fixes three defects the live data caught, all reachable from a code
review alone:
  - split kept the generic fragment, promoting "20" from "m20nut" to a
    required clause; a leading 1-2 letter run now merges into its digits
  - the split group dropped the other tokens, so "M20NUT WASHER" matched
    rows containing no washer; other tokens are now carried along
  - a punctuation-only query ("-", "---") tokenised to nothing and threw,
    which would have blanked the catalog at the till

The index is built once per catalog load on both paths (IndexedDB and
network), keeping derived strings off the items so the cache stays lean.
0.21-2.98 ms per keystroke, so no debounce is needed. filteredProducts()
falls back to the old substring filter if PosSearch is missing, since a
skewed service-worker cache would otherwise blank a shop's catalog.

sw.js v28 -> v30: the new script must be in the app shell, and the second
bump is required because pos-search.js is served cache-first and step 2
edited it in place.
2026-10-06 23:36:12 +02:00
..
icons feat: add picking slips, bulk print tracking, supplier map 2026-07-10 10:47:11 +02:00
letterhead feat: add branded quote PDF generation and in-app viewer 2026-06-23 08:30:38 +02:00
pos feat(pos): tiered catalog search — word order, plurals, glued SKUs 2026-10-06 23:36:12 +02:00
android-chrome-192x192.png feat(dashboard): add multi-theme system and supporting improvements 2026-06-26 17:59:40 +02:00
android-chrome-512x512.png feat(dashboard): add multi-theme system and supporting improvements 2026-06-26 17:59:40 +02:00
apple-touch-icon.png feat(dashboard): add multi-theme system and supporting improvements 2026-06-26 17:59:40 +02:00
favicon-16x16.png feat(dashboard): add multi-theme system and supporting improvements 2026-06-26 17:59:40 +02:00
favicon-32x32.png feat(dashboard): add multi-theme system and supporting improvements 2026-06-26 17:59:40 +02:00
favicon-96x96.png feat(dashboard): add multi-theme system and supporting improvements 2026-06-26 17:59:40 +02:00
favicon.ico feat(dashboard): add multi-theme system and supporting improvements 2026-06-26 17:59:40 +02:00
file.svg feat: add UI components for separator, sheet, sonner, switch, table, tabs, textarea, tooltip 2026-05-24 16:31:01 +02:00
globe.svg feat: add UI components for separator, sheet, sonner, switch, table, tabs, textarea, tooltip 2026-05-24 16:31:01 +02:00
manifest-counter.json feat(counter): add standalone counter order PWA 2026-08-13 09:27:20 +02:00
manifest-mobile.json fix(boss-dashboard): make /m installable as a PWA 2026-08-31 22:14:48 +02:00
manifest-rep.json feat(rep): visit check-in PWA — phone GPS, offline outbox 2026-09-06 21:09:27 +02:00
manifest-scan.json feat(scan): standalone delivery-note scanner PWA at /scan 2026-10-04 13:15:56 +02:00
manifest.json feat(dashboard): add multi-theme system and supporting improvements 2026-06-26 17:59:40 +02:00
next.svg feat: add UI components for separator, sheet, sonner, switch, table, tabs, textarea, tooltip 2026-05-24 16:31:01 +02:00
og-image.png feat(dashboard): add multi-theme system and supporting improvements 2026-06-26 17:59:40 +02:00
og-square.png feat(dashboard): add multi-theme system and supporting improvements 2026-06-26 17:59:40 +02:00
sw-counter.js feat(counter): add standalone counter order PWA 2026-08-13 09:27:20 +02:00
sw-mobile.js feat: implement per-route service worker selection 2026-09-02 07:49:38 +02:00
sw-rep.js feat(rep): visit check-in PWA — phone GPS, offline outbox 2026-09-06 21:09:27 +02:00
sw.js chore: standardize line endings and add full test + config scaffolding 2026-06-11 20:30:02 +02:00
twitter-image.png feat(dashboard): add multi-theme system and supporting improvements 2026-06-26 17:59:40 +02:00
vercel.svg feat: add UI components for separator, sheet, sonner, switch, table, tabs, textarea, tooltip 2026-05-24 16:31:01 +02:00
wfdash-logo-icon.png chore: add logos, opencode config and build assets 2026-07-27 08:21:20 +02:00
wfdash-logo-mark.png chore: add logos, opencode config and build assets 2026-07-27 08:21:20 +02:00
wfdash-logo.png chore: add logos, opencode config and build assets 2026-07-27 08:21:20 +02:00
window.svg feat: add UI components for separator, sheet, sonner, switch, table, tabs, textarea, tooltip 2026-05-24 16:31:01 +02:00