feat(shopping): Hide/Delete/Restore + Saved + Hidden tabs#103
Closed
Bogdan-ca wants to merge 4 commits into
Closed
feat(shopping): Hide/Delete/Restore + Saved + Hidden tabs#103Bogdan-ca wants to merge 4 commits into
Bogdan-ca wants to merge 4 commits into
Conversation
…rows; refresh button now clears all stale rows before regenerating
Replaces the single "X" dismiss button with two distinct actions on each recommendation card: - 🔖 Save — moves the item from Spotlight to a server-persisted history. Auto-fires a force-refresh when Spotlight thins below 6/8 so the user stays in a steady stream of fresh picks. Saved is what surfaces under the new Saved tab. - 🗑️ Delete — permanently dismisses the item. Removed from Spotlight, Saved, and added to a per-user dismissed list that subsequent AI generations filter out. Same Delete works from either tab. Server side: - New SavedRecommendation model (one row per user × stableKey, indexed by savedAt for the listing). - New DismissedRecommendation model used to filter AI results before they hit the cache. - New endpoints: POST /api/recommendations/save, GET /api/recommendations/saved, DELETE /api/recommendations/item, DELETE /api/recommendations/cache. - The existing GET handler now post-filters AI results against the dismissed list so dismissed items never re-surface, even on refresh. Frontend: - ShoppingPage gains a Spotlight | Saved tab strip with a count badge. - New saveRecommendation / deleteRecommendation actions in the store, optimistic with server roundtrip; failures revert Save but not Delete (delete-on-failure is a worse UX than leaving the item dismissed). - Refresh still wipes cache server-side before regenerating (already shipped) and now also implicitly survives the dismissed-filter step. Tests: 7 new backend integration cases cover save idempotency, history listing order, dismissed filtering, force-bypass, and cache wipe. Frontend Playwright spec passes against the new tab layout (heading + budget empty + reachability).
Splits dismissal into two distinct user actions across the four states: - Spotlight (auto) — 3 actions: Save, Hide, Delete - Saved — 2 actions: Hide, Delete - Hidden — 2 actions: Restore, Delete forever Hide is reversible (item goes to the Hidden tab and can be Restored). Delete is final (item is gone, AI filter still excludes it forever). Both flavors block the AI from re-surfacing the item; the difference is whether the user has a UI affordance to undo. Server side: - DismissedRecommendation grows a `permanent` boolean. - DELETE /api/recommendations/item accepts `permanent` in the body so Hide (false) and Delete (true) share the same endpoint. - GET /api/recommendations/hidden filters to permanent: false only. - POST /api/recommendations/hidden/:key/restore wipes the dismissed record so the AI may surface the item again. - POST /api/recommendations/hidden/:key/delete-forever upgrades a hidden item to permanent (drops from the Hidden tab, stays filtered). Frontend: - New hideRecommendation + deleteHiddenForever actions in the store, alongside the existing save/delete/restore. All optimistic. - RecommendationCard supports the new `hidden` variant and shows Restore + Delete-forever icons. Spotlight card renders 3 icons. - ShoppingPage tabs grew a Hidden entry with its own section and copy. - api.delete now accepts a body, used to send the item snapshot when dismissing so the Hidden tab can render the card later. 3 new backend integration cases cover Hide-vs-Delete visibility, restore semantics, and the delete-forever promotion path. Frontend Playwright shopping suite still 3/3.
Collaborator
Author
|
Closing — all 4 feature commits are already on main (HEAD 2d79c54...). GitHub silently did not fire workflows on the squashed commits; dispatching them manually now via gh workflow run. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #49 (already closed, references for context).
Builds on top of PR #100/#102 with the full lifecycle for recommendations.
What's new
?force=1Server-side
SavedRecommendationandDismissedRecommendation(with apermanentflag) collections, indexed per userPOST /save,GET /saved,DELETE /item,GET /hidden,POST /hidden/:key/restore,POST /hidden/:key/delete-forever,DELETE /cacheTest plan
tsc -b+ eslint: clean