store: faceted product filters — kategori, merk, kendaraan, ketersediaan #46

Closed
opened 2026-08-27 06:35:53 +00:00 by yuris · 0 comments
Owner

Kendaraan facet blocked by #41 (needs fitment[]); the rest is buildable now.

produk.html is the biggest functional gap in the whole design. It specifies a sidebar of four facet groups with per-option counts, an active-filter chip row, a result count, and a collapse toggle on mobile:

  • Kategori — checkboxes with counts (Kaki-kaki 212, Oli 184, Filter 148, Body & lampu 167, Ban 96, Aki 42)
  • Merk — checkboxes with counts (KYB, Sakura, Denso, GS Astra, Dunlop, 555)
  • Kendaraan — checkboxes with counts (Avanza / Xenia, Innova, Brio / Mobilio, Ertiga, Pajero / Fortuner) — derived from fitment[]
  • Ketersediaan — Ready stok
  • Toolbar — active-filter chips that remove on click, plus a live 212 produk count

What exists today in apps/store/app/products/product-browser.tsx is a single-select category button row plus a text search, driven by q and kategori params. So: multi-select, three new facet dimensions, counts, and chips are all new.

Notes

  • Counts must come from the catalog the page already fetched — no second data source, and they should reflect the other active facets, not the unfiltered total, or they will lie.
  • brand is nullable and fitment free text, so facet options must be derived from the data rather than hardcoded, and items missing a value simply do not match that facet.
  • The store is a static export: keep filtering client-side and keep the URL params as the source of truth so a filtered view stays linkable. The spec notes client-side filtering is fine to roughly 500 items.
  • Mobile: the design collapses the whole sidebar behind one Filter & urutkan toggle. Keep every option at the 44px tap target already established in globals.css.

Acceptance

Multi-select across all four groups narrows the grid correctly, counts match what selecting the facet would actually yield, chips remove their own filter, the result count is accurate, and every state round-trips through the URL. Category and brand facets ship first; the Kendaraan group lands with #41. Cover the filter-reduction logic with a node:test unit test over a fixture catalog — pull the pure part out of the component so it is testable, since the app has no component test setup.

**Kendaraan facet blocked by #41** (needs `fitment[]`); the rest is buildable now. `produk.html` is the biggest functional gap in the whole design. It specifies a sidebar of four facet groups with per-option counts, an active-filter chip row, a result count, and a collapse toggle on mobile: - **Kategori** — checkboxes with counts (Kaki-kaki 212, Oli 184, Filter 148, Body & lampu 167, Ban 96, Aki 42) - **Merk** — checkboxes with counts (KYB, Sakura, Denso, GS Astra, Dunlop, 555) - **Kendaraan** — checkboxes with counts (Avanza / Xenia, Innova, Brio / Mobilio, Ertiga, Pajero / Fortuner) — derived from `fitment[]` - **Ketersediaan** — Ready stok - **Toolbar** — active-filter chips that remove on click, plus a live `212 produk` count What exists today in `apps/store/app/products/product-browser.tsx` is a *single-select* category button row plus a text search, driven by `q` and `kategori` params. So: multi-select, three new facet dimensions, counts, and chips are all new. ### Notes - Counts must come from the catalog the page already fetched — no second data source, and they should reflect the *other* active facets, not the unfiltered total, or they will lie. - `brand` is nullable and `fitment` free text, so facet options must be derived from the data rather than hardcoded, and items missing a value simply do not match that facet. - The store is a static export: keep filtering client-side and keep the URL params as the source of truth so a filtered view stays linkable. The spec notes client-side filtering is fine to roughly 500 items. - Mobile: the design collapses the whole sidebar behind one `Filter & urutkan` toggle. Keep every option at the 44px tap target already established in `globals.css`. ### Acceptance Multi-select across all four groups narrows the grid correctly, counts match what selecting the facet would actually yield, chips remove their own filter, the result count is accurate, and every state round-trips through the URL. Category and brand facets ship first; the Kendaraan group lands with #41. Cover the filter-reduction logic with a `node:test` unit test over a fixture catalog — pull the pure part out of the component so it is testable, since the app has no component test setup.
yuris closed this issue 2026-08-27 14:35:07 +00:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
yuris/garage#46
No description provided.