v2: rules page — list, detail, create/edit form#1107
Merged
Conversation
Build the Rules page and its subpages for the v2 SPA. Mirrors the v1 admin UI structure (list with stage badges and hit counts, detail with conditions/ actions cards and a retroactive-apply action, form with visual condition + action builders, JSON escape hatch, live preview panel, pipeline-stage presets) on shadcn primitives + TanStack Router/Query + RHF/zod. Wires four routes: /rules (list, PAGE_OVERRIDE), /rules/new, /rules/$id (detail), /rules/$id/edit. All hit the public /api/v1/rules surface via the v2 session cookie. Rule conditions follow the canonical field grammar from docs/rule-dsl.md.
Resolves a conflict in main.tsx — keeps both the accounts route additions from main and the rules route additions from this branch. Also fixes a layout issue where the absolutely-positioned Edit + kebab buttons on each rule row overlapped the lg-only stats columns (stage / last active). The Link content now carries `pr-24` on sm+ so the stats columns end well clear of the action cluster.
Owner
Author
Merges main (api-keys + providers + accounts pages). Conflict in web/src/api/types.ts auto-resolved to keep both blocks. Simplify-pass on the rules code (from three review agents): - Extract `RuleAvatar` with size variant — shared between rule-row.tsx and rule-detail.tsx, dropping a parallel 4-branch avatar. - Extract `categoryTileStyle()` to rule-utils.ts — was inlined 3×. - Reuse the shadcn `Pagination` primitives via a new components/pagination-bar.tsx (TransactionsPagination now wraps it). - Use `AlertDialogAction variant="destructive"` instead of inlining the destructive class string in two places. - Reuse `flattenCategories` from queries/categories instead of a parallel tree walk inside condition-row. - Lift `useCategories` / `useTags` to RuleActionsDisplay once instead of per-row subscriptions in CategoryName / TagChip. - Drop the dead `useTags()` + `void tags` workaround in condition-row's ValueInput; move `isCategoryEq` derivation inside. - Replace `withMutationToast(() => Promise.reject/resolve)` abuse in rule-form route with direct `sonner` calls. - Type `getRowErrors` with `UseFormReturn<RuleFormValues>` instead of `any`; drop the eslint-disable. - Drop dead UUID-keyed `useRule` invalidation in update/toggle mutations. - Use the `isMatchAll()` helper in `comboWarnings` instead of inline `Object.keys(...).length === 0`. Add `watchedTrigger` so the memo dep list is honest. - Drop unused `RULES_PAGE_SIZE` export from rules.tsx; remove WHAT-narrating section comments inside the form.
Owner
Author
Merge activity
|
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
/api/v1/rules*via the v2 session cookie — no new backend code. Rule conditions follow the canonical field grammar indocs/rule-dsl.md(provider_name,provider_merchant_name, …).Files
web/src/api/types.ts—Condition,RuleAction,TransactionRule,RulesPage,RulePreviewResult, plus create/update inputs.web/src/api/queries/rules.ts—useRules,useRule,useRuleSyncHistory,useCreateRule,useUpdateRule,useToggleRule,useDeleteRule,useApplyRule,usePreviewRule.web/src/features/rules/—rule-utils.ts(field grammar, condition⇄form transforms, stage presets),rule-row.tsx,rule-form.tsx,condition-row.tsx,action-row.tsx,preview-panel.tsx,rule-display.tsx(read-only conditions/actions).web/src/routes/{rules,rule-detail,rule-form}.tsx— page shells.web/src/main.tsx— registers the four routes.Screenshots
Rules list (4 rules — system + user-created)
Rule detail ("Uber rides → Rideshare", with retroactive apply + delete rails)
New rule form
Edit rule form (round-tripped two-condition AND tree)
Mobile — list + new form
Test plan
bun run build(tsc + vite) green./api/v1/rules/{id}/apply) — wired but not run end-to-end this session.useDeleteRulebut not exercised in browser.🤖 Generated with Claude Code