Add category and tag management on a new Labels tab - #17
Merged
Conversation
Categories were already a table with an icon column but were read-only in the app — no create/rename/delete path, and expense rows rendered a hardcoded receipt icon regardless of category. Tags (a keyword that auto-assigns a category, e.g. "COSTCO" -> Groceries) are exactly the merchant_rules the statement importer already had, just missing a home outside the import flow. - Add a Labels tab to the group screen (Expenses/Balances/Members/Labels) with full category CRUD and tag CRUD, reusing merchant_rules as tag storage instead of introducing a parallel table. - Retire MerchantRulesScreen; /import/rules now redirects to Labels. - Migration 0012: category FKs go ON DELETE SET NULL so a category can be deleted without orphaning expenses; unique category names per group; re-seed the 10 global categories with Phosphor icon slugs. - Add lib/core/icons.dart: the app's Phosphor icon vocabulary (phosphor_flutter, MIT) — kCategoryIcons for the picker, legacy Material-name aliases, deterministic per-category tint colors, and AppIcons semantic constants. Every Icons.* call site in lib/ moved to it. - Expense rows now show the category's icon and name instead of a fixed receipt icon. - Add matchTagCategory: the Add-expense form autofills a category from tags as you type a description, the same precedence import review uses, and never overrides a category picked by hand. - Update statement-import.md, add categories-and-tags.md, update the README project-structure listing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EzXWJsUFffSSJAKGaRqUT4
LouisBenjamin
force-pushed
the
feature/categories-and-tags
branch
from
September 2, 2026 01:21
a363f81 to
729d60a
Compare
The `stable` channel moved to a Flutter release that marks `IconData` as a final class. phosphor_flutter 2.1.0 (last published two years ago) extends `IconData`, so dart2js and `flutter test` both fail to compile on the newer toolchain while everything still builds on the 3.41.9 used locally. Pin all three workflows to 3.41.9 to make CI reproducible and match local dev. Revisit the pin when phosphor_flutter is replaced with a maintained icon dependency. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EzXWJsUFffSSJAKGaRqUT4
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.
Summary
Categories already existed as a table (icon column + all) but were read-only in the app, and expense rows showed a hardcoded receipt icon regardless of category. Tags — a keyword that auto-assigns a category, e.g. "COSTCO" → Groceries — are exactly the
merchant_rulesthe statement importer already had, just without a home outside the import flow.MerchantRulesScreenis retired;/import/rulesnow redirects to Labels.0012_categories.sql: category FKs goON DELETE SET NULL(a category can now be deleted without an FK violation or orphaning data), unique category names per group, and the 10 global categories are re-seeded with Phosphor icon slugs.lib/core/icons.dart: the app's new icon vocabulary, built onphosphor_flutter(MIT).kCategoryIconsbacks the category picker,_legacyIconAliaseskeeps pre-migration Material icon names resolving,categoryTint/onCategoryTintgive each category a deterministic colour with no colour picker needed, andAppIconsholds semantic constants for app chrome. EveryIcons.*call site inlib/moved to it — confirmed viaflutter build web --tree-shake-icons.matchTagCategoryruns the same tag-matching precedence import review uses, live as you type a description, and never overrides a category you picked by hand.docs/statement-import.md, addeddocs/categories-and-tags.md, updated the README project-structure listing.Note: this branches off
main(commit 89f8693), independent of the in-flightdocs/readme-statement-importPR — the two touch overlapping README sections and whichever merges second will need a small rebase.Testing
flutter analyze— cleanflutter test— 175/175 passing (updatedscreens_smoke_test.dartfor the 4th tab, retargetedMerchantRulesScreentests toLabelsScreen, addedmatchTagCategoryunit tests and a newlabels_tab_test.dart)flutter build web --tree-shake-icons— succeeds, Phosphor + Material fonts tree-shake correctlyFollow-ups (out of scope here)
add_recurring_screen.dartdoesn't get the tag-autofill treatment yet, to keep this diff reviewable.🤖 Generated with Claude Code