feat(grocery): name→aisle category override rules (Phase 1) - #448
Open
plusmobileapps wants to merge 6 commits into
Open
feat(grocery): name→aisle category override rules (Phase 1)#448plusmobileapps wants to merge 6 commits into
plusmobileapps wants to merge 6 commits into
Conversation
"Cold brew" wasn't in the IngredientParser vocabulary, so it fell through to OTHER. Add it as a BEVERAGES keyword; sorted longest-first, it also takes precedence over the generic "coffee" keyword. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds persistent "always file <name> under <aisle>" rules so users can retag items the built-in IngredientParser sends to the wrong aisle (or to OTHER). A new GroceryCategoryOverride table + GroceryCategoryOverrideRepository back the rules, mirroring the GroceryAutocompleteItem sync scaffolding so a later Supabase sync is data-only; the feature is local-only for now. GroceryRepositoryImpl resolves each item's aisle as: per-item stored aisle → user name rule → parser default, combining the rule map into the grocery list flows so rule changes re-emit. Sign-in/sign-out clear the rules alongside the other local repositories. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds a checkbox under the item detail aisle picker: "Always file <name> in <aisle>". Toggling it on writes a persistent name→aisle rule (and keeps it synced if the aisle is then changed); toggling off removes it. The box initializes checked when a rule for this item's name already points at the shown aisle. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds a Settings → Grocery → Category rules screen for reviewing and removing name→aisle rules (created here or via the item detail "always file here" hook). New grocery/category-rules feature module (bloc/impl/viewmodel/screen) mirrors the grocery autocomplete settings module; the create row pairs an item name with an aisle picker, and each rule row offers delete-with-confirm. Wires the screen into settings navigation (SettingsRoot child + app settings row) and registers the impl module in the DI graph. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds Compose previews and screenshot-test coverage for the new category rules screen (populated, empty, creating, dark) and the item detail "always file here" checked state. Re-records the grocery detail, app settings, and settings root references to include the new checkbox row and the "Category rules" settings entry. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds the grocery/category-rules impl-robots module and a runRootBlocTest flow that opens Settings → Category rules and asserts the management screen loads. Registers the new GroceryCategoryOverrideQueries in the test DI graph, which the grocery repository now depends on. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
What & why
The grocery list categorizes items by running the name through
IngredientParser, a static keyword→GroceryCategorymap. Anything it doesn't recognize falls to Other — which is exactly what happened with "cold brew". Keyword whack-a-mole doesn't scale: users buy products the built-in vocabulary will never cover, and sometimes the parser's guess is just wrong for how their store is laid out.This adds a persistent, name-keyed rule — "always file
<name>under<aisle>" — that retags every future item whose parsed name matches. Scope is limited to the 13 existing aisles; letting users create brand-new aisles (which means unwinding theGroceryCategoryenum used app-wide) is deferred to Phase 2.How it works
Resolution order when mapping a stored row to a grocery item:
per-item stored aisle → user name rule → parser default.
Two entry points for a rule:
Rules live in a new local
GroceryCategoryOverridetable that mirrors theGroceryAutocompleteItemsync scaffolding (remoteId/clientId/isDirty/ownerId), so wiring the imminent Supabase grocery sync is a data-only follow-up — no schema migration.categoryKeyis stored as a free-form string, so Phase 2 custom aisles slot in without an override-schema change. Sign-in/sign-out clear the rules alongside the other local repositories.Commits (one concern each, per repo convention)
fix(grocery)— categorize cold brew as a beverage (the original itch)feat(grocery)— override table + repository + resolution inGroceryRepositoryImplfeat(grocery)— "always file here" hook on item detailfeat(grocery)— category rules management screen (newgrocery/category-rulesmodule + settings nav wiring)test(grocery)— previews + recorded screenshotstest(grocery)— robot UI navigation testTesting
GroceryCategoryOverrideRepositoryImplTest(upsert, case-insensitive dedup, unrecognized-key drop) + 4 resolution tests inGroceryRepositoryImplTest(rule beats parser default; per-item aisle beats rule; removal reverts; case-insensitive parsed-name match).GroceryDetailBlocTest;GroceryCategoryRulesViewModelTest; settings-root + app-settings navigation tests.Reviewer notes
client/grocery/category-rules/{public,impl,impl-robots}mirrors the existinggrocery/autocompletemodule.GroceryRepositoryImplnow depends onGroceryCategoryOverrideRepository; the test DI graph (BaseTestApplicationComponent) provides the newGroceryCategoryOverrideQueriesaccordingly.GroceryCategoryusage with a merged aisle model across ~15 files.🤖 Generated with Claude Code