Document tonight's wishlist/search/filters/CustomSelect work in README
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2218,6 +2218,101 @@ here to pick it up.
|
||||
bridge → Coolify API → rebuild + restart. Full mechanics in
|
||||
`~/dev/README.md`.
|
||||
|
||||
## Wishlist, search, filters, feature toggles (2026-07-30 evening)
|
||||
|
||||
A cluster of new features, all gated behind new `CompanySettings`
|
||||
booleans (Payload admin → Company Settings → **Features** tab, all off
|
||||
by default — each feature stays entirely invisible in the frontend
|
||||
until explicitly switched on): `wishlistEnabled`, `searchEnabled`,
|
||||
`shopFilterEnabled`, `blogFilterEnabled`, `orderFilterEnabled`.
|
||||
|
||||
**Wishlist.** Backend `wishlist-items` collection (customer + product +
|
||||
optional variant, unique per combination, customer-scoped access — see
|
||||
the Payload backend's own README). Frontend: `useWishlist.ts` (a
|
||||
fetch-based hook with an optimistic toggle + a `window` event so every
|
||||
`WishlistButton`/the Navbar badge on a page stay in sync — not
|
||||
`localStorage`-backed like the cart, since a wishlist needs a logged-in
|
||||
customer to mean anything), `WishlistButton.tsx` (heart icon, redirects
|
||||
to login with `?redirect=` if logged out), the Navbar's heart icon +
|
||||
count badge (hidden below `sm:` — Account+Cart are the only
|
||||
always-visible icons on true mobile, a 3rd icon there risks the nav-
|
||||
overflow bug class documented in the `figma-to-nextjs` skill), and
|
||||
`/konto/merkliste` (a Client Component grid — `MerklisteGrid.tsx` — so
|
||||
removing an item disappears immediately, unlike a plain Server
|
||||
Component render which wouldn't react to the client-side toggle at all).
|
||||
`Product` gained a `numericId` field (the raw Payload id) alongside its
|
||||
existing slug `id`, since `wishlist-items.product` is a real numeric
|
||||
relationship, unlike the cart/checkout's slug-keyed "commerce id".
|
||||
|
||||
Found and fixed a real race condition in `useWishlist.ts`: the "refetch
|
||||
me" event used to fire immediately after the optimistic local update,
|
||||
before the POST request was even sent — another instance's resulting
|
||||
refetch could beat the actual server write, cache the pre-toggle list,
|
||||
and never get told to refetch again (the Navbar count stayed one
|
||||
behind). The event now only fires after the request settles.
|
||||
|
||||
**Standalone registration.** Until now an account only ever got created
|
||||
inline during checkout. That stopped making sense the moment a
|
||||
wishlist gave accounts a reason to exist independent of a purchase —
|
||||
new `/konto/registrieren` (+ `RegisterForm.tsx`, reusing the existing
|
||||
`/api/account/register` route). `LoginForm.tsx` now also honors a
|
||||
`?redirect=` param (previously ignored, always landing on
|
||||
`/konto/bestellungen`) and links to the new page instead of implying
|
||||
"only via checkout".
|
||||
|
||||
**Instant search.** New `/api/search` route — plain Payload
|
||||
`where[...][contains]` queries (Postgres `ILIKE`) against Products +
|
||||
Posts, not a real search index (Meilisearch/Algolia); fine at this
|
||||
catalog's current size, worth upgrading once it grows past ~20 products
|
||||
(see the e-commerce SOTA gaps memory note). `SearchOverlay.tsx`
|
||||
(debounced 250ms, grouped results) + a Navbar search icon (same
|
||||
`hidden sm:` reasoning as the wishlist icon).
|
||||
|
||||
**Filters, everywhere URL-search-param-driven** (shareable/bookmarkable,
|
||||
no client-side-only state):
|
||||
- `/konto/bestellungen` — status/paymentStatus/year, via 3
|
||||
`CustomSelect` dropdowns (`OrderFilters.tsx`). Went through two
|
||||
earlier UI iterations first: a wall of filter chips (too cluttered,
|
||||
too much vertical space) and then plain native `<select>`s (a native
|
||||
select's open options popup can't be styled at all — looked
|
||||
completely off-brand) before landing on `CustomSelect.tsx`.
|
||||
- `/blog` — category toggle chips (`buildCategoryHref()`), plain
|
||||
server-rendered `<Link>`s, no client component needed since the page
|
||||
already fetches every published post in one request.
|
||||
- `/shop` — a price min/max range (`PriceRangeFilter.tsx`) — preset
|
||||
toggle buckets were tried first and reverted ("keine toggle badges").
|
||||
A fuller sidebar-with-drag-slider layout was requested as a follow-up,
|
||||
not yet built as of this writing.
|
||||
|
||||
**`CustomSelect.tsx`** (`app/components/`) — a fully custom-styled
|
||||
dropdown (own trigger + own `role="listbox"` options panel, keyboard
|
||||
nav, click-outside-to-close), built to replace native `<select>`s
|
||||
wherever their un-stylable options popup matters. Also used for
|
||||
checkout's two country pickers now (`includeAllOption={false}` — a
|
||||
country is always genuinely selected, no "clear" state like the
|
||||
filter-dropdown use case; `fullWidth` — matches the surrounding w-full
|
||||
form fields instead of the filter bar's shrink-to-fit sizing).
|
||||
|
||||
**Assorted same-evening bugfixes:**
|
||||
- Blog category filter bar was invisible (wrapped in `<Reveal>`, which
|
||||
sits right at the hero's bottom edge — exactly the
|
||||
`whileInView(margin:"-80px")` trap `Reveal.tsx`'s own comment
|
||||
documents: an element already visible without scrolling can
|
||||
permanently never register as "entered view"). Now a plain `div`.
|
||||
- Then found rendering *behind* the featured-post card instead (that
|
||||
card pulls itself up `-mt-8`/`z-10` to overlap the *hero's* bottom
|
||||
edge — its original design — but the filter bar now sat where that
|
||||
pull landed). Given `relative z-20` to stay above it.
|
||||
- `AddToCartInlineButton`'s `className` prop *replaces* its whole
|
||||
default styling (`?? default`, not a merge) — `/konto/merkliste`
|
||||
passed `className="w-full"` and lost all the button's actual styling
|
||||
as a result. Removed the override (the default is already `w-full`).
|
||||
|
||||
**How to apply if you're reading this cold:** every one of these
|
||||
features requires the matching `CompanySettings` toggle to actually be
|
||||
switched on before it shows up anywhere in the frontend — if a feature
|
||||
"isn't showing," check that first.
|
||||
|
||||
## Related design source
|
||||
|
||||
- `~/dev/einfach-produktiv/mockups/` — Figma-stage mockup PNGs
|
||||
|
||||
Reference in New Issue
Block a user