Rules improvements - #1087
Rules improvements#1087
Conversation
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (2)
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsx (1)
100-137: Add explicit React import for type references.The component uses
React.ReactNode(lines 100, 104, 112, 136, 137) without importing the React namespace. While the JSX transform handles createElement, theReactnamespace reference for types requires an explicit import.import { Button } from "@/components/ui/button"; import { TrashIcon, MoreHorizontalIcon, ClockIcon, SparklesIcon, PenLineIcon, } from "lucide-react"; +import type { ReactNode } from "react"; import { cn } from "@/utils";Then update the type references to use
ReactNodedirectly instead ofReact.ReactNode.apps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx (1)
150-160: First-condition enforcement overwrites user data when removing conditions.This
useEffectforcesconditions[0]to be a "prompt" type, which causes data loss when:
- User has
[prompt, from-filter]- User removes the first condition
useFieldArray.remove(0)shiftsfrom-filterto index 0- This effect then overwrites the
from-filterwith an empty prompt conditionConsider one of these fixes:
- Prevent removing the first condition entirely (always keep prompt row)
- Prepend a new prompt condition instead of overwriting index 0
- Check if the shifted condition should be preserved before overwriting
🧹 Nitpick comments (6)
apps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx (1)
351-358: Consider using theInputcomponent withautosizeTextareafor consistency.The coding guidelines recommend using the
Inputcomponent withautosizeTextareaprop for text areas. This provides consistent styling and error handling integration.-<TextareaAutosize - className="block w-full flex-1 whitespace-pre-wrap rounded-md border border-border bg-background shadow-sm focus:border-black focus:ring-black sm:text-sm" - minRows={3} - rows={3} - {...register(`conditions.${index}.instructions`)} - placeholder="e.g. Newsletters, regular content from publications, blogs, or services I've subscribed to" -/> +<Input + type="text" + autosizeTextarea + rows={3} + name={`conditions.${index}.instructions`} + registerProps={register(`conditions.${index}.instructions`)} + placeholder="e.g. Newsletters, regular content from publications, blogs, or services I've subscribed to" +/>apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx (2)
529-531: Consider using a proper confirmation dialog instead ofconfirm().The native
confirm()is blocking and doesn't match the app's UI style. Since this is inside a Dialog component already, consider using a nested AlertDialog from shadcn/ui for consistent UX.
614-619: Duplicate function:allowMultipleConditionsexists in both files.This function is also defined in
ConditionSteps.tsx(lines 55-60). Consider extracting it to a shared utility to avoid duplication.// In a shared file like apps/web/utils/rule/consts.ts or a new helper: +export function allowMultipleConditions(systemType: SystemType | null | undefined) { + return ( + systemType !== SystemType.COLD_EMAIL && + !isConversationStatusType(systemType) + ); +}Then import it in both
RuleForm.tsxandConditionSteps.tsx.apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx (3)
727-735: Singular/plural labels could be simplified.The current logic checks raw
delayInMinutesvalues (1, 60, 1440) to determine singular/plural, which works but is indirect. Consider using the computeddisplayValueinstead for clarity:<SelectItem value="minutes"> - {delayInMinutes === 1 ? "Minute" : "Minutes"} + {displayValue === "1" && unit === "minutes" ? "Minute" : "Minutes"} </SelectItem> <SelectItem value="hours"> - {delayInMinutes === 60 ? "Hour" : "Hours"} + {displayValue === "1" && unit === "hours" ? "Hour" : "Hours"} </SelectItem> <SelectItem value="days"> - {delayInMinutes === 1440 ? "Day" : "Days"} + {displayValue === "1" && unit === "days" ? "Day" : "Days"} </SelectItem>
269-471: Consider extractingrenderFieldinto a separate component.The
renderFieldfunction is ~200 lines and handles complex conditional rendering. While the closure access to form state is convenient, extracting it into a<FieldRenderer>component could improve readability and testability.This is a larger refactor that could be deferred, but would help with:
- Easier unit testing of individual field types
- Better code organization
- Reduced cognitive load when reading ActionCard
127-130: Use imported types consistently.
ActionCardusesReturnType<typeof useForm<CreateRuleBody>>["register"]while the imported types (UseFormRegister<CreateRuleBody>) would be cleaner and match the parent component's signature.-register: ReturnType<typeof useForm<CreateRuleBody>>["register"]; -watch: ReturnType<typeof useForm<CreateRuleBody>>["watch"]; -setValue: ReturnType<typeof useForm<CreateRuleBody>>["setValue"]; -control: ReturnType<typeof useForm<CreateRuleBody>>["control"]; +register: UseFormRegister<CreateRuleBody>; +watch: UseFormWatch<CreateRuleBody>; +setValue: UseFormSetValue<CreateRuleBody>; +control: Control<CreateRuleBody>;
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx(1 hunks)apps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx(1 hunks)apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx(7 hunks)apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsx(1 hunks)
🧰 Additional context used
📓 Path-based instructions (14)
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Use@/path aliases for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Follow consistent naming conventions using PascalCase for components
Centralize shared types in dedicated type filesImport specific lodash functions rather than entire lodash library to minimize bundle size (e.g.,
import groupBy from 'lodash/groupBy')
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
apps/web/app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
Follow NextJS app router structure with (app) directory
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
apps/web/**/*.tsx
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/**/*.tsx: Follow tailwindcss patterns with prettier-plugin-tailwindcss for class sorting
Prefer functional components with hooks over class components
Use shadcn/ui components when available
Ensure responsive design with mobile-first approach
Use LoadingContent component for async data with loading and error states
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/data-fetching.mdc)
**/*.{ts,tsx}: For API GET requests to server, use theswrpackage
Useresult?.serverErrorwithtoastErrorfrom@/components/Toastfor error handling in async operations
**/*.{ts,tsx}: Use wrapper functions for Gmail message operations (get, list, batch, etc.) from @/utils/gmail/message.ts instead of direct API calls
Use wrapper functions for Gmail thread operations from @/utils/gmail/thread.ts instead of direct API calls
Use wrapper functions for Gmail label operations from @/utils/gmail/label.ts instead of direct API calls
**/*.{ts,tsx}: For early access feature flags, create hooks using the naming conventionuse[FeatureName]Enabledthat return a boolean fromuseFeatureFlagEnabled("flag-key")
For A/B test variant flags, create hooks using the naming conventionuse[FeatureName]Variantthat define variant types, useuseFeatureFlagVariantKey()with type casting, and provide a default "control" fallback
Use kebab-case for PostHog feature flag keys (e.g.,inbox-cleaner,pricing-options-2)
Always define types for A/B test variant flags (e.g.,type PricingVariant = "control" | "variant-a" | "variant-b") and provide type safety through type casting
**/*.{ts,tsx}: Don't use primitive type aliases or misleading types
Don't use empty type parameters in type aliases and interfaces
Don't use this and super in static contexts
Don't use any or unknown as type constraints
Don't use the TypeScript directive @ts-ignore
Don't use TypeScript enums
Don't export imported variables
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions
Don't use TypeScript namespaces
Don't use non-null assertions with the!postfix operator
Don't use parameter properties in class constructors
Don't use user-defined types
Useas constinstead of literal types and type annotations
Use eitherT[]orArray<T>consistently
Initialize each enum member value explicitly
Useexport typefor types
Use `impo...
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
apps/web/app/(app)/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/page-structure.mdc)
apps/web/app/(app)/**/*.{ts,tsx}: Components for the page are either put inpage.tsx, or in theapps/web/app/(app)/PAGE_NAMEfolder
If we're in a deeply nested component we will useswrto fetch via API
If you need to useonClickin a component, that component is a client component and file must start withuse client
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/prisma-enum-imports.mdc)
Always import Prisma enums from
@/generated/prisma/enumsinstead of@/generated/prisma/clientto avoid Next.js bundling errors in client componentsImport Prisma using the project's centralized utility:
import prisma from '@/utils/prisma'
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
**/*.{tsx,ts}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
**/*.{tsx,ts}: Use Shadcn UI and Tailwind for components and styling
Usenext/imagepackage for images
For API GET requests to server, use theswrpackage with hooks likeuseSWRto fetch data
For text inputs, use theInputcomponent withregisterPropsfor form integration and error handling
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
**/*.{tsx,ts,css}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
Implement responsive design with Tailwind CSS using a mobile-first approach
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
**/*.tsx: Use theLoadingContentcomponent to handle loading states instead of manual loading state management
For text areas, use theInputcomponent withtype='text',autosizeTextareaprop set to true, andregisterPropsfor form integration
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{js,jsx,ts,tsx}: Don't useaccessKeyattribute on any HTML element
Don't setaria-hidden="true"on focusable elements
Don't add ARIA roles, states, and properties to elements that don't support them
Don't use distracting elements like<marquee>or<blink>
Only use thescopeprop on<th>elements
Don't assign non-interactive ARIA roles to interactive HTML elements
Make sure label elements have text content and are associated with an input
Don't assign interactive ARIA roles to non-interactive HTML elements
Don't assigntabIndexto non-interactive HTML elements
Don't use positive integers fortabIndexproperty
Don't include "image", "picture", or "photo" in img alt prop
Don't use explicit role property that's the same as the implicit/default role
Make static elements with click handlers use a valid role attribute
Always include atitleelement for SVG elements
Give all elements requiring alt text meaningful information for screen readers
Make sure anchors have content that's accessible to screen readers
AssigntabIndexto non-interactive HTML elements witharia-activedescendant
Include all required ARIA attributes for elements with ARIA roles
Make sure ARIA properties are valid for the element's supported roles
Always include atypeattribute for button elements
Make elements with interactive roles and handlers focusable
Give heading elements content that's accessible to screen readers (not hidden witharia-hidden)
Always include alangattribute on the html element
Always include atitleattribute for iframe elements
AccompanyonClickwith at least one of:onKeyUp,onKeyDown, oronKeyPress
AccompanyonMouseOver/onMouseOutwithonFocus/onBlur
Include caption tracks for audio and video elements
Use semantic elements instead of role attributes in JSX
Make sure all anchors are valid and navigable
Ensure all ARIA properties (aria-*) are valid
Use valid, non-abstract ARIA roles for elements with ARIA roles
Use valid AR...
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{jsx,tsx}: Don't use unnecessary fragments
Don't pass children as props
Don't use the return value of React.render
Make sure all dependencies are correctly specified in React hooks
Make sure all React hooks are called from the top level of component functions
Don't forget key props in iterators and collection literals
Don't define React components inside other components
Don't use event handlers on non-interactive elements
Don't assign to React component props
Don't use bothchildrenanddangerouslySetInnerHTMLprops on the same element
Don't use dangerous JSX props
Don't use Array index in keys
Don't insert comments as text nodes
Don't assign JSX properties multiple times
Don't add extra closing tags for components without children
Use<>...</>instead of<Fragment>...</Fragment>
Watch out for possible "wrong" semicolons inside JSX elements
Make sure void (self-closing) elements don't have children
Don't usetarget="_blank"withoutrel="noopener"
Don't use<img>elements in Next.js projects
Don't use<head>elements in Next.js projects
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
!(pages/_document).{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
Don't use the next/head module in pages/_document.js on Next.js projects
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
**/*.{js,ts,jsx,tsx}: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size (e.g.,import groupBy from 'lodash/groupBy')
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
**/*Form.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/form-handling.mdc)
**/*Form.{ts,tsx}: Use React Hook Form with Zod for validation in form components
Validate form inputs before submission
Show validation errors inline next to form fields
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
🧠 Learnings (30)
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : Use XML-like tags to structure data in prompts, remove excessive whitespace and truncate long inputs, and format data consistently across similar LLM functions
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use semantic elements instead of role attributes in JSX
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/**/*.tsx : Use shadcn/ui components when available
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2024-08-23T11:37:26.779Z
Learnt from: aryanprince
Repo: elie222/inbox-zero PR: 210
File: apps/web/app/(app)/stats/NewsletterModal.tsx:2-4
Timestamp: 2024-08-23T11:37:26.779Z
Learning: `MoreDropdown` is a React component and `useUnsubscribeButton` is a custom React hook, and they should not be imported using `import type`.
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{jsx,tsx} : Make sure all dependencies are correctly specified in React hooks
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{jsx,tsx} : Don't define React components inside other components
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsx
📚 Learning: 2025-11-25T14:40:13.649Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:13.649Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : For text areas in forms, use the `Input` component with `type='text'`, `autosizeTextarea` prop, `rows`, `name`, `placeholder`, `registerProps` from react-hook-form, and `error` props
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{jsx,tsx} : Use `<>...</>` instead of `<Fragment>...</Fragment>`
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsx
📚 Learning: 2025-11-25T14:40:13.649Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:13.649Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : Use Shadcn UI and Tailwind for components and styling
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Always include a `type` attribute for button elements
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsx
📚 Learning: 2025-11-25T14:38:56.992Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-11-25T14:38:56.992Z
Learning: Applies to apps/web/components/ui/**/*.tsx : Shadcn UI components are located in `components/ui` directory
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:40:15.063Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:15.063Z
Learning: Applies to **/*.{tsx,ts} : Use Shadcn UI and Tailwind for components and styling
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsx
📚 Learning: 2025-11-25T14:40:13.649Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:13.649Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : For text inputs in forms, use the `Input` component with `type='email'`, `name`, `label`, `registerProps` from react-hook-form, and `error` props
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
📚 Learning: 2025-11-25T14:36:51.389Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:51.389Z
Learning: Applies to **/*Form.{ts,tsx} : Show validation errors inline next to form fields in the UI
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : LLM feature functions must follow a standard structure: accept options with `inputData` and `emailAccount` parameters, implement input validation with early returns, define separate system and user prompts, create a Zod schema for response validation, and use `createGenerateObject` to execute the LLM call
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
📚 Learning: 2025-11-25T14:36:51.389Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:51.389Z
Learning: Applies to **/*Form.{ts,tsx} : Validate form inputs before submission using React Hook Form and Zod resolver
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/components/**/*Form*.tsx : Use React Hook Form with Zod validation (`zodResolver`) for form handling, with form components using `register`, `handleSubmit`, and error handling from the hook
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:51.389Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:51.389Z
Learning: Applies to **/*Form.{ts,tsx} : Use React Hook Form with Zod for form validation
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/components/**/*.tsx : Use React Hook Form with Zod validation for form components
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:53.147Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:53.147Z
Learning: Applies to **/*Form.{ts,tsx} : Use React Hook Form with Zod for validation in form components
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:53.147Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:53.147Z
Learning: Applies to **/*Form.{ts,tsx} : Validate form inputs before submission
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:53.147Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:53.147Z
Learning: Applies to **/*Form.{ts,tsx} : Show validation errors inline next to form fields
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:11.919Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-25T14:42:11.919Z
Learning: Applies to utils/**/*.{js,ts,jsx,tsx} : The `utils` folder contains core app logic such as Next.js Server Actions and Gmail API requests
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:40:00.833Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-25T14:40:00.833Z
Learning: Applies to **/*.test.{ts,tsx} : Use test helpers `getEmail`, `getEmailAccount`, and `getRule` from `@/__tests__/helpers` for mocking emails, accounts, and rules
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/components/**/*Form*.tsx : Handle form submission results using `result?.serverError` to show error toasts and `toastSuccess` to show success messages after server action completion
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/components/**/*.tsx : Use `result?.serverError` with `toastError` and `toastSuccess` for error handling in form submissions
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:40:15.063Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:15.063Z
Learning: Applies to **/*.{tsx,ts} : For text inputs, use the `Input` component with `registerProps` for form integration and error handling
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:40:15.063Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:15.063Z
Learning: Applies to **/*.tsx : For text areas, use the `Input` component with `type='text'`, `autosizeTextarea` prop set to true, and `registerProps` for form integration
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:39:49.448Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-11-25T14:39:49.448Z
Learning: Applies to apps/web/utils/actions/*.ts : Create corresponding server action implementation files using the naming convention `apps/web/utils/actions/NAME.ts` with 'use server' directive
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
📚 Learning: 2025-11-25T14:39:49.448Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-11-25T14:39:49.448Z
Learning: Applies to apps/web/utils/actions/*.ts : Add metadata with a meaningful action name using `.metadata({ name: "actionName" })` for Sentry instrumentation and monitoring
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
🧬 Code graph analysis (2)
apps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx (5)
apps/web/utils/actions/rule.validation.ts (2)
ZodCondition(62-62)CreateRuleBody(194-194)apps/web/utils/reply-tracker/conversation-status-config.ts (1)
isConversationStatusType(16-22)apps/web/app/(app)/[emailAccountId]/assistant/RuleSteps.tsx (1)
RuleSteps(7-40)apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsx (1)
RuleStep(120-172)apps/web/utils/rule/consts.ts (1)
getRuleConfig(112-116)
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx (7)
apps/web/utils/outlook/folders.ts (1)
OutlookFolder(12-17)apps/web/app/(app)/[emailAccountId]/assistant/RuleSteps.tsx (1)
RuleSteps(7-40)apps/web/utils/action-item.ts (1)
actionInputs(4-152)apps/web/utils/delayed-actions.ts (1)
canActionBeDelayed(14-16)apps/web/components/FolderSelector.tsx (1)
FolderSelector(90-287)apps/web/utils/template.ts (2)
hasVariables(5-6)TEMPLATE_VARIABLE_PATTERN(2-2)apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsx (1)
RuleStep(120-172)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: test
🔇 Additional comments (3)
apps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx (1)
47-52: Verify body-to-subject mapping behavior.The
bodyfield maps to"subject"UI type (line 50), but when the user modifies this condition,getConditionFromUIType("subject")creates a condition withsubject: ""andbody: null. This will silently lose any existingbodydata.Is this intentional? If rules can have
bodyconditions from elsewhere (e.g., API, migrations), they'll appear as "subject" in the UI and lose thebodyvalue on any edit.apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx (1)
386-425: Well-structured modular form layout.The refactor to
RuleSectionCardwithConditionStepsandActionStepscomponents creates a clean, maintainable structure. The separation of concerns and consistent card-based UI align well with the step-based editing goals.apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx (1)
46-107: Clean composition with RuleSteps container.The
ActionStepscomponent provides a well-structured wrapper that maps action fields toActionCardinstances. The integration withRuleStepsfor the add button and consistent prop passing is well-organized.
| onClick={async () => { | ||
| const yes = confirm( | ||
| "Are you sure you want to delete this rule?", | ||
| ); | ||
| if (yes) { | ||
| try { | ||
| setIsDeleting(true); | ||
| const result = await deleteRuleAction( | ||
| emailAccountId, | ||
| { | ||
| id: rule.id!, | ||
| }, | ||
| ); | ||
| if (result?.serverError) { | ||
| toastError({ | ||
| description: result.serverError, | ||
| }); | ||
| } else { | ||
| toastSuccess({ | ||
| description: "The rule has been deleted.", | ||
| }); | ||
|
|
||
| if (isDialog && onSuccess) { | ||
| onSuccess(); | ||
| } | ||
|
|
||
| router.push( | ||
| prefixPath( | ||
| emailAccountId, | ||
| "/automation?tab=rules", | ||
| ), | ||
| ); | ||
| } | ||
| } catch { | ||
| toastError({ description: "Failed to delete rule." }); | ||
| } finally { | ||
| setIsDeleting(false); | ||
| } | ||
| } | ||
| }} |
There was a problem hiding this comment.
Empty catch block loses error context.
The catch block at line 561 catches the error but doesn't log it, making debugging difficult if the delete operation fails for unexpected reasons.
-} catch {
+} catch (error) {
+ console.error("Failed to delete rule:", error);
toastError({ description: "Failed to delete rule." });
}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx around lines 528
to 567, the catch block for delete action swallows the thrown error; update the
catch to accept the error (e.g., catch (err)) and log the error (console.error
or a project logger) and include the error message in the toastError description
or log so you retain error context for debugging, then keep the existing finally
block that resets setIsDeleting(false).
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (3)
apps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx (1)
165-176: Previous concern about data loss has been addressed.The
useEffectnow checks ifuiType === undefinedbefore setting a default prompt condition. This prevents overwriting existing static conditions when they shift to index 0 after removal of the first condition. The fix correctly addresses the data-loss issue flagged in previous reviews.apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx (1)
74-74: Add missingElementTypeimport.The code references
React.ElementTypewithout importing the React namespace orElementTypetype. This will cause a TypeScript error.Apply this diff:
-import { useCallback, useMemo, useState } from "react"; +import { useCallback, useMemo, useState, type ElementType } from "react";Then update lines 74 and 137 to use
ElementTypedirectly:- typeOptions: { label: string; value: ActionType; icon: React.ElementType }[]; + typeOptions: { label: string; value: ActionType; icon: ElementType }[];apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx (1)
561-565: Log error in catch block for debugging.The catch block doesn't capture the error, losing valuable debugging information when deletion fails.
Apply this diff:
- } catch { + } catch (error) { + console.error("Failed to delete rule:", error); toastError({ description: "Failed to delete rule." });
🧹 Nitpick comments (2)
apps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx (2)
70-73: Remove redundant| neverfrom return type.The
| neverunion in the return type is unnecessary. A function that can throw (line 126) or returnZodConditiondoesn't need| neverin its signature.Apply this diff:
-function getConditionFromUIType( - uiType: UIConditionType | undefined, -): ZodCondition | never { +function getConditionFromUIType( + uiType: UIConditionType | undefined, +): ZodCondition {
277-296: Consider simplifying the prompt reordering logic.The loop that reorders conditions when a prompt is selected at a non-first position could be more readable using array methods.
Consider this refactor:
- // If AI Prompt is selected at a non-first position, - // insert it at position 0 and shift other conditions if (value === "prompt" && index !== 0) { const currentConditionAtIndex = conditions[index]; const currentConditionType = getUIConditionType( currentConditionAtIndex, ); - // Build new conditions array with AI Prompt at position 0 - const newConditions = [newCondition]; - - // Add all existing conditions except the one being changed - for (let i = 0; i < conditions.length; i++) { - if (i !== index) { - newConditions.push(conditions[i]); - } else if (currentConditionType !== undefined) { - // If the condition being changed had data, keep it - newConditions.push(currentConditionAtIndex); - } - // If it was empty (undefined type), just skip it - } + // Build new conditions array with AI Prompt at position 0 + const otherConditions = conditions.filter((_, i) => i !== index); + const newConditions = [newCondition]; + + // If the condition being changed had data, keep it + if (currentConditionType !== undefined) { + newConditions.push(currentConditionAtIndex); + } + newConditions.push(...otherConditions); setValue("conditions", newConditions);
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx(1 hunks)apps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx(1 hunks)apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx(7 hunks)apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsx
🧰 Additional context used
📓 Path-based instructions (14)
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Use@/path aliases for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Follow consistent naming conventions using PascalCase for components
Centralize shared types in dedicated type filesImport specific lodash functions rather than entire lodash library to minimize bundle size (e.g.,
import groupBy from 'lodash/groupBy')
Files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx
apps/web/app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
Follow NextJS app router structure with (app) directory
Files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx
apps/web/**/*.tsx
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/**/*.tsx: Follow tailwindcss patterns with prettier-plugin-tailwindcss for class sorting
Prefer functional components with hooks over class components
Use shadcn/ui components when available
Ensure responsive design with mobile-first approach
Use LoadingContent component for async data with loading and error states
Files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/data-fetching.mdc)
**/*.{ts,tsx}: For API GET requests to server, use theswrpackage
Useresult?.serverErrorwithtoastErrorfrom@/components/Toastfor error handling in async operations
**/*.{ts,tsx}: Use wrapper functions for Gmail message operations (get, list, batch, etc.) from @/utils/gmail/message.ts instead of direct API calls
Use wrapper functions for Gmail thread operations from @/utils/gmail/thread.ts instead of direct API calls
Use wrapper functions for Gmail label operations from @/utils/gmail/label.ts instead of direct API calls
**/*.{ts,tsx}: For early access feature flags, create hooks using the naming conventionuse[FeatureName]Enabledthat return a boolean fromuseFeatureFlagEnabled("flag-key")
For A/B test variant flags, create hooks using the naming conventionuse[FeatureName]Variantthat define variant types, useuseFeatureFlagVariantKey()with type casting, and provide a default "control" fallback
Use kebab-case for PostHog feature flag keys (e.g.,inbox-cleaner,pricing-options-2)
Always define types for A/B test variant flags (e.g.,type PricingVariant = "control" | "variant-a" | "variant-b") and provide type safety through type casting
**/*.{ts,tsx}: Don't use primitive type aliases or misleading types
Don't use empty type parameters in type aliases and interfaces
Don't use this and super in static contexts
Don't use any or unknown as type constraints
Don't use the TypeScript directive @ts-ignore
Don't use TypeScript enums
Don't export imported variables
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions
Don't use TypeScript namespaces
Don't use non-null assertions with the!postfix operator
Don't use parameter properties in class constructors
Don't use user-defined types
Useas constinstead of literal types and type annotations
Use eitherT[]orArray<T>consistently
Initialize each enum member value explicitly
Useexport typefor types
Use `impo...
Files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx
apps/web/app/(app)/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/page-structure.mdc)
apps/web/app/(app)/**/*.{ts,tsx}: Components for the page are either put inpage.tsx, or in theapps/web/app/(app)/PAGE_NAMEfolder
If we're in a deeply nested component we will useswrto fetch via API
If you need to useonClickin a component, that component is a client component and file must start withuse client
Files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/prisma-enum-imports.mdc)
Always import Prisma enums from
@/generated/prisma/enumsinstead of@/generated/prisma/clientto avoid Next.js bundling errors in client componentsImport Prisma using the project's centralized utility:
import prisma from '@/utils/prisma'
Files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx
**/*.{tsx,ts}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
**/*.{tsx,ts}: Use Shadcn UI and Tailwind for components and styling
Usenext/imagepackage for images
For API GET requests to server, use theswrpackage with hooks likeuseSWRto fetch data
For text inputs, use theInputcomponent withregisterPropsfor form integration and error handling
Files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx
**/*.{tsx,ts,css}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
Implement responsive design with Tailwind CSS using a mobile-first approach
Files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
**/*.tsx: Use theLoadingContentcomponent to handle loading states instead of manual loading state management
For text areas, use theInputcomponent withtype='text',autosizeTextareaprop set to true, andregisterPropsfor form integration
Files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{js,jsx,ts,tsx}: Don't useaccessKeyattribute on any HTML element
Don't setaria-hidden="true"on focusable elements
Don't add ARIA roles, states, and properties to elements that don't support them
Don't use distracting elements like<marquee>or<blink>
Only use thescopeprop on<th>elements
Don't assign non-interactive ARIA roles to interactive HTML elements
Make sure label elements have text content and are associated with an input
Don't assign interactive ARIA roles to non-interactive HTML elements
Don't assigntabIndexto non-interactive HTML elements
Don't use positive integers fortabIndexproperty
Don't include "image", "picture", or "photo" in img alt prop
Don't use explicit role property that's the same as the implicit/default role
Make static elements with click handlers use a valid role attribute
Always include atitleelement for SVG elements
Give all elements requiring alt text meaningful information for screen readers
Make sure anchors have content that's accessible to screen readers
AssigntabIndexto non-interactive HTML elements witharia-activedescendant
Include all required ARIA attributes for elements with ARIA roles
Make sure ARIA properties are valid for the element's supported roles
Always include atypeattribute for button elements
Make elements with interactive roles and handlers focusable
Give heading elements content that's accessible to screen readers (not hidden witharia-hidden)
Always include alangattribute on the html element
Always include atitleattribute for iframe elements
AccompanyonClickwith at least one of:onKeyUp,onKeyDown, oronKeyPress
AccompanyonMouseOver/onMouseOutwithonFocus/onBlur
Include caption tracks for audio and video elements
Use semantic elements instead of role attributes in JSX
Make sure all anchors are valid and navigable
Ensure all ARIA properties (aria-*) are valid
Use valid, non-abstract ARIA roles for elements with ARIA roles
Use valid AR...
Files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{jsx,tsx}: Don't use unnecessary fragments
Don't pass children as props
Don't use the return value of React.render
Make sure all dependencies are correctly specified in React hooks
Make sure all React hooks are called from the top level of component functions
Don't forget key props in iterators and collection literals
Don't define React components inside other components
Don't use event handlers on non-interactive elements
Don't assign to React component props
Don't use bothchildrenanddangerouslySetInnerHTMLprops on the same element
Don't use dangerous JSX props
Don't use Array index in keys
Don't insert comments as text nodes
Don't assign JSX properties multiple times
Don't add extra closing tags for components without children
Use<>...</>instead of<Fragment>...</Fragment>
Watch out for possible "wrong" semicolons inside JSX elements
Make sure void (self-closing) elements don't have children
Don't usetarget="_blank"withoutrel="noopener"
Don't use<img>elements in Next.js projects
Don't use<head>elements in Next.js projects
Files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx
!(pages/_document).{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
Don't use the next/head module in pages/_document.js on Next.js projects
Files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
**/*.{js,ts,jsx,tsx}: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size (e.g.,import groupBy from 'lodash/groupBy')
Files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx
**/*Form.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/form-handling.mdc)
**/*Form.{ts,tsx}: Use React Hook Form with Zod for validation in form components
Validate form inputs before submission
Show validation errors inline next to form fields
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
🧠 Learnings (37)
📚 Learning: 2025-11-25T14:39:49.448Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-11-25T14:39:49.448Z
Learning: Applies to apps/web/utils/actions/*.ts : Create corresponding server action implementation files using the naming convention `apps/web/utils/actions/NAME.ts` with 'use server' directive
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
📚 Learning: 2025-11-25T14:39:49.448Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-11-25T14:39:49.448Z
Learning: Applies to apps/web/utils/actions/*.validation.ts : Create separate validation files for server actions using the naming convention `apps/web/utils/actions/NAME.validation.ts` containing Zod schemas and inferred types
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
📚 Learning: 2025-11-25T14:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/utils/actions/*.ts : Use `next-safe-action` with Zod schemas for all server actions (create/update/delete mutations), storing validation schemas in `apps/web/utils/actions/*.validation.ts`
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use semantic elements instead of role attributes in JSX
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Always include a `type` attribute for button elements
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use valid, non-abstract ARIA roles for elements with ARIA roles
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{jsx,tsx} : Make sure all dependencies are correctly specified in React hooks
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
📚 Learning: 2025-11-25T14:40:13.649Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:13.649Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : For text areas in forms, use the `Input` component with `type='text'`, `autosizeTextarea` prop, `rows`, `name`, `placeholder`, `registerProps` from react-hook-form, and `error` props
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{ts,tsx} : Use `import type` for types
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Make sure ARIA properties are valid for the element's supported roles
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Make static elements with click handlers use a valid role attribute
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
📚 Learning: 2024-08-23T11:37:26.779Z
Learnt from: aryanprince
Repo: elie222/inbox-zero PR: 210
File: apps/web/app/(app)/stats/NewsletterModal.tsx:2-4
Timestamp: 2024-08-23T11:37:26.779Z
Learning: `MoreDropdown` is a React component and `useUnsubscribeButton` is a custom React hook, and they should not be imported using `import type`.
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{jsx,tsx} : Watch out for possible "wrong" semicolons inside JSX elements
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx
📚 Learning: 2025-11-25T14:40:13.649Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:13.649Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : For text inputs in forms, use the `Input` component with `type='email'`, `name`, `label`, `registerProps` from react-hook-form, and `error` props
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : Use XML-like tags to structure data in prompts, remove excessive whitespace and truncate long inputs, and format data consistently across similar LLM functions
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/**/*.{ts,tsx} : Use proper error handling with try/catch blocks
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:39:23.326Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-11-25T14:39:23.326Z
Learning: Applies to app/api/**/*.ts : Use `SafeError` for error responses to prevent information disclosure - provide generic messages (e.g., 'Rule not found' not 'Rule {id} does not exist for user {userId}') without revealing internal IDs or ownership details
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't use unnecessary catch clauses
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't reassign exceptions in catch clauses
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:40.146Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/data-fetching.mdc:0-0
Timestamp: 2025-11-25T14:36:40.146Z
Learning: Applies to **/*.{ts,tsx} : Use `result?.serverError` with `toastError` from `@/components/Toast` for error handling in async operations
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:36.276Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/data-fetching.mdc:0-0
Timestamp: 2025-11-25T14:36:36.276Z
Learning: Applies to **/*.{ts,tsx} : Use `result?.serverError` with `toastError` and `toastSuccess` for error handling in server actions
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/components/**/*.tsx : Use `result?.serverError` with `toastError` and `toastSuccess` for error handling in form submissions
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:51.389Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:51.389Z
Learning: Applies to **/*Form.{ts,tsx} : Validate form inputs before submission using React Hook Form and Zod resolver
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/components/**/*Form*.tsx : Use React Hook Form with Zod validation (`zodResolver`) for form handling, with form components using `register`, `handleSubmit`, and error handling from the hook
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:51.389Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:51.389Z
Learning: Applies to **/*Form.{ts,tsx} : Use React Hook Form with Zod for form validation
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/components/**/*.tsx : Use React Hook Form with Zod validation for form components
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:53.147Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:53.147Z
Learning: Applies to **/*Form.{ts,tsx} : Use React Hook Form with Zod for validation in form components
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:51.389Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:51.389Z
Learning: Applies to **/*Form.{ts,tsx} : Show validation errors inline next to form fields in the UI
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:53.147Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:53.147Z
Learning: Applies to **/*Form.{ts,tsx} : Validate form inputs before submission
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:53.147Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:53.147Z
Learning: Applies to **/*Form.{ts,tsx} : Show validation errors inline next to form fields
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:38:56.992Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-11-25T14:38:56.992Z
Learning: Applies to apps/web/components/ui/**/*.tsx : Shadcn UI components are located in `components/ui` directory
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/**/*.tsx : Use shadcn/ui components when available
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:11.919Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-25T14:42:11.919Z
Learning: Applies to utils/**/*.{js,ts,jsx,tsx} : The `utils` folder contains core app logic such as Next.js Server Actions and Gmail API requests
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:40:00.833Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-25T14:40:00.833Z
Learning: Applies to **/*.test.{ts,tsx} : Use test helpers `getEmail`, `getEmailAccount`, and `getRule` from `@/__tests__/helpers` for mocking emails, accounts, and rules
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/components/**/*Form*.tsx : Handle form submission results using `result?.serverError` to show error toasts and `toastSuccess` to show success messages after server action completion
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:40:15.063Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:15.063Z
Learning: Applies to **/*.{tsx,ts} : For text inputs, use the `Input` component with `registerProps` for form integration and error handling
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:40:15.063Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:15.063Z
Learning: Applies to **/*.tsx : For text areas, use the `Input` component with `type='text'`, `autosizeTextarea` prop set to true, and `registerProps` for form integration
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
🧬 Code graph analysis (1)
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx (8)
apps/web/utils/action-display.tsx (1)
getActionIcon(86-115)apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsx (1)
RuleSectionCard(5-58)apps/web/utils/reply-tracker/conversation-status-config.ts (1)
isConversationStatusType(16-22)apps/web/utils/rule/consts.ts (1)
getRuleConfig(112-116)apps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx (1)
ConditionSteps(129-544)apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx (1)
ActionSteps(46-107)apps/web/components/Toggle.tsx (1)
Toggle(18-50)apps/web/app/(app)/[emailAccountId]/assistant/group/LearnedPatterns.tsx (1)
LearnedPatternsDialog(21-96)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: test
🔇 Additional comments (4)
apps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx (1)
129-544: Well-structured condition management component.The component follows best practices:
- Proper form integration with react-hook-form via
register,setValue, andwatch- Error handling with inline
ErrorMessagedisplay- Accessibility through labeled inputs and tooltips
- Modular design with clear separation of UI condition types and backend conditions
apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx (1)
46-615: Well-structured action management with good UX patterns.The component demonstrates several strengths:
- Proper form integration with react-hook-form
- Good use of
useCallbackanduseMemofor performance- Nice UX features like variable highlighting and expandable fields
- Correct usage of Input component with
registerPropsper coding guidelinesapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx (2)
386-466: Excellent refactoring to modular components.The refactoring successfully:
- Separates concerns with
RuleSectionCard,ConditionSteps, andActionSteps- Maintains proper form integration throughout
- Provides clear visual hierarchy with icons and colors
- Preserves error handling and validation
468-598: Well-executed Advanced Settings dialog.Moving advanced settings to a dialog improves the UX by:
- Reducing visual clutter in the main form
- Grouping related settings logically
- Maintaining accessibility with proper dialog structure
- Preserving all functionality including delete action
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (3)
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsx (1)
1-3: Add missing ComponentType import.The component uses
React.ComponentTypeon line 12 without importing it. Add a type-only import and update the reference.Apply this diff:
import { Card } from "@/components/ui/card"; import { TypographyH3 } from "@/components/Typography"; import { cn } from "@/utils"; +import type { ComponentType, ReactNode } from "react";Then update line 12:
- icon: React.ComponentType<{ className?: string }>; + icon: ComponentType<{ className?: string }>;As per coding guidelines: Use
import typefor types.Also applies to: 12-12
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx (2)
3-3: Add missing ElementType import.The code uses
React.ElementTypeon line 277 without importing it. Add a type-only import and update the reference.Apply this diff:
-import { useCallback, useEffect, useMemo, useState } from "react"; +import { useCallback, useEffect, useMemo, useState, type ElementType } from "react";Then update line 277:
- icon: React.ElementType; + icon: ElementType;As per coding guidelines: Use
import typefor types.Also applies to: 273-278
555-556: Empty catch block loses error context.The catch block doesn't capture or log the error, making debugging difficult if deletion fails unexpectedly.
Apply this diff:
- } catch { + } catch (error) { + console.error("Failed to delete rule:", error); toastError({ description: "Failed to delete rule." });As per coding guidelines: Use proper error handling with try/catch blocks.
🧹 Nitpick comments (2)
apps/web/providers/SWRProvider.tsx (1)
38-51: Consider usingcaptureExceptionfor production logging consistency.The try/catch approach for handling non-JSON responses is solid. However, using
console.errorin production (line 45) doesn't align with the project's structured error logging pattern viacaptureException.Apply this diff to use structured error reporting:
} catch { // Response wasn't JSON - common during dev HMR, unexpected in production if (process.env.NODE_ENV !== "development") { - console.error("Failed to parse error response as JSON", { + captureException(new Error("Failed to parse error response as JSON"), { + extra: { - url, - status: res.status, - statusText: res.statusText, + url, + status: res.status, + statusText: res.statusText, + }, }); } }apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx (1)
608-613: Consider extracting duplicated utility function.The
allowMultipleConditionsfunction is duplicated inConditionSteps.tsx(lines 63-68). Consider extracting it to a shared utility file like@/utils/rule/helpers.tsto avoid code duplication and ensure consistency.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
apps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx(1 hunks)apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx(7 hunks)apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsx(1 hunks)apps/web/providers/SWRProvider.tsx(2 hunks)
🧰 Additional context used
📓 Path-based instructions (14)
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Use@/path aliases for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Follow consistent naming conventions using PascalCase for components
Centralize shared types in dedicated type filesImport specific lodash functions rather than entire lodash library to minimize bundle size (e.g.,
import groupBy from 'lodash/groupBy')
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/providers/SWRProvider.tsx
apps/web/app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
Follow NextJS app router structure with (app) directory
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
apps/web/**/*.tsx
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/**/*.tsx: Follow tailwindcss patterns with prettier-plugin-tailwindcss for class sorting
Prefer functional components with hooks over class components
Use shadcn/ui components when available
Ensure responsive design with mobile-first approach
Use LoadingContent component for async data with loading and error states
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/providers/SWRProvider.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/data-fetching.mdc)
**/*.{ts,tsx}: For API GET requests to server, use theswrpackage
Useresult?.serverErrorwithtoastErrorfrom@/components/Toastfor error handling in async operations
**/*.{ts,tsx}: Use wrapper functions for Gmail message operations (get, list, batch, etc.) from @/utils/gmail/message.ts instead of direct API calls
Use wrapper functions for Gmail thread operations from @/utils/gmail/thread.ts instead of direct API calls
Use wrapper functions for Gmail label operations from @/utils/gmail/label.ts instead of direct API calls
**/*.{ts,tsx}: For early access feature flags, create hooks using the naming conventionuse[FeatureName]Enabledthat return a boolean fromuseFeatureFlagEnabled("flag-key")
For A/B test variant flags, create hooks using the naming conventionuse[FeatureName]Variantthat define variant types, useuseFeatureFlagVariantKey()with type casting, and provide a default "control" fallback
Use kebab-case for PostHog feature flag keys (e.g.,inbox-cleaner,pricing-options-2)
Always define types for A/B test variant flags (e.g.,type PricingVariant = "control" | "variant-a" | "variant-b") and provide type safety through type casting
**/*.{ts,tsx}: Don't use primitive type aliases or misleading types
Don't use empty type parameters in type aliases and interfaces
Don't use this and super in static contexts
Don't use any or unknown as type constraints
Don't use the TypeScript directive @ts-ignore
Don't use TypeScript enums
Don't export imported variables
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions
Don't use TypeScript namespaces
Don't use non-null assertions with the!postfix operator
Don't use parameter properties in class constructors
Don't use user-defined types
Useas constinstead of literal types and type annotations
Use eitherT[]orArray<T>consistently
Initialize each enum member value explicitly
Useexport typefor types
Use `impo...
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/providers/SWRProvider.tsx
apps/web/app/(app)/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/page-structure.mdc)
apps/web/app/(app)/**/*.{ts,tsx}: Components for the page are either put inpage.tsx, or in theapps/web/app/(app)/PAGE_NAMEfolder
If we're in a deeply nested component we will useswrto fetch via API
If you need to useonClickin a component, that component is a client component and file must start withuse client
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/prisma-enum-imports.mdc)
Always import Prisma enums from
@/generated/prisma/enumsinstead of@/generated/prisma/clientto avoid Next.js bundling errors in client componentsImport Prisma using the project's centralized utility:
import prisma from '@/utils/prisma'
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/providers/SWRProvider.tsx
**/*.{tsx,ts}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
**/*.{tsx,ts}: Use Shadcn UI and Tailwind for components and styling
Usenext/imagepackage for images
For API GET requests to server, use theswrpackage with hooks likeuseSWRto fetch data
For text inputs, use theInputcomponent withregisterPropsfor form integration and error handling
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/providers/SWRProvider.tsx
**/*.{tsx,ts,css}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
Implement responsive design with Tailwind CSS using a mobile-first approach
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/providers/SWRProvider.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
**/*.tsx: Use theLoadingContentcomponent to handle loading states instead of manual loading state management
For text areas, use theInputcomponent withtype='text',autosizeTextareaprop set to true, andregisterPropsfor form integration
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/providers/SWRProvider.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{js,jsx,ts,tsx}: Don't useaccessKeyattribute on any HTML element
Don't setaria-hidden="true"on focusable elements
Don't add ARIA roles, states, and properties to elements that don't support them
Don't use distracting elements like<marquee>or<blink>
Only use thescopeprop on<th>elements
Don't assign non-interactive ARIA roles to interactive HTML elements
Make sure label elements have text content and are associated with an input
Don't assign interactive ARIA roles to non-interactive HTML elements
Don't assigntabIndexto non-interactive HTML elements
Don't use positive integers fortabIndexproperty
Don't include "image", "picture", or "photo" in img alt prop
Don't use explicit role property that's the same as the implicit/default role
Make static elements with click handlers use a valid role attribute
Always include atitleelement for SVG elements
Give all elements requiring alt text meaningful information for screen readers
Make sure anchors have content that's accessible to screen readers
AssigntabIndexto non-interactive HTML elements witharia-activedescendant
Include all required ARIA attributes for elements with ARIA roles
Make sure ARIA properties are valid for the element's supported roles
Always include atypeattribute for button elements
Make elements with interactive roles and handlers focusable
Give heading elements content that's accessible to screen readers (not hidden witharia-hidden)
Always include alangattribute on the html element
Always include atitleattribute for iframe elements
AccompanyonClickwith at least one of:onKeyUp,onKeyDown, oronKeyPress
AccompanyonMouseOver/onMouseOutwithonFocus/onBlur
Include caption tracks for audio and video elements
Use semantic elements instead of role attributes in JSX
Make sure all anchors are valid and navigable
Ensure all ARIA properties (aria-*) are valid
Use valid, non-abstract ARIA roles for elements with ARIA roles
Use valid AR...
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/providers/SWRProvider.tsx
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{jsx,tsx}: Don't use unnecessary fragments
Don't pass children as props
Don't use the return value of React.render
Make sure all dependencies are correctly specified in React hooks
Make sure all React hooks are called from the top level of component functions
Don't forget key props in iterators and collection literals
Don't define React components inside other components
Don't use event handlers on non-interactive elements
Don't assign to React component props
Don't use bothchildrenanddangerouslySetInnerHTMLprops on the same element
Don't use dangerous JSX props
Don't use Array index in keys
Don't insert comments as text nodes
Don't assign JSX properties multiple times
Don't add extra closing tags for components without children
Use<>...</>instead of<Fragment>...</Fragment>
Watch out for possible "wrong" semicolons inside JSX elements
Make sure void (self-closing) elements don't have children
Don't usetarget="_blank"withoutrel="noopener"
Don't use<img>elements in Next.js projects
Don't use<head>elements in Next.js projects
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/providers/SWRProvider.tsx
!(pages/_document).{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
Don't use the next/head module in pages/_document.js on Next.js projects
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/providers/SWRProvider.tsx
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
**/*.{js,ts,jsx,tsx}: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size (e.g.,import groupBy from 'lodash/groupBy')
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsxapps/web/providers/SWRProvider.tsx
**/*Form.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/form-handling.mdc)
**/*Form.{ts,tsx}: Use React Hook Form with Zod for validation in form components
Validate form inputs before submission
Show validation errors inline next to form fields
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
🧠 Learnings (47)
📚 Learning: 2025-11-25T14:38:56.992Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-11-25T14:38:56.992Z
Learning: Applies to apps/web/components/ui/**/*.tsx : Shadcn UI components are located in `components/ui` directory
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:38:56.992Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-11-25T14:38:56.992Z
Learning: Applies to apps/web/components/**/*.tsx : Use PascalCase for component file names (e.g., `components/Button.tsx`)
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/**/*.tsx : Use shadcn/ui components when available
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{ts,tsx} : Use `import type` for types
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsx
📚 Learning: 2024-08-23T11:37:26.779Z
Learnt from: aryanprince
Repo: elie222/inbox-zero PR: 210
File: apps/web/app/(app)/stats/NewsletterModal.tsx:2-4
Timestamp: 2024-08-23T11:37:26.779Z
Learning: `MoreDropdown` is a React component and `useUnsubscribeButton` is a custom React hook, and they should not be imported using `import type`.
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use semantic elements instead of role attributes in JSX
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:40:13.649Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:13.649Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : For text areas in forms, use the `Input` component with `type='text'`, `autosizeTextarea` prop, `rows`, `name`, `placeholder`, `registerProps` from react-hook-form, and `error` props
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Always include a `type` attribute for button elements
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{jsx,tsx} : Make sure all dependencies are correctly specified in React hooks
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{jsx,tsx} : Don't define React components inside other components
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsx
📚 Learning: 2025-11-25T14:40:13.649Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:13.649Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : For text inputs in forms, use the `Input` component with `type='email'`, `name`, `label`, `registerProps` from react-hook-form, and `error` props
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/**/*.tsx : Prefer functional components with hooks over class components
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsx
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : Use XML-like tags to structure data in prompts, remove excessive whitespace and truncate long inputs, and format data consistently across similar LLM functions
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/**/*.{ts,tsx} : Use proper error handling with try/catch blocks
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:39:23.326Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-11-25T14:39:23.326Z
Learning: Applies to app/api/**/*.ts : Use `SafeError` for error responses to prevent information disclosure - provide generic messages (e.g., 'Rule not found' not 'Rule {id} does not exist for user {userId}') without revealing internal IDs or ownership details
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't use unnecessary catch clauses
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't reassign exceptions in catch clauses
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:40.146Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/data-fetching.mdc:0-0
Timestamp: 2025-11-25T14:36:40.146Z
Learning: Applies to **/*.{ts,tsx} : Use `result?.serverError` with `toastError` from `@/components/Toast` for error handling in async operations
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:36.276Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/data-fetching.mdc:0-0
Timestamp: 2025-11-25T14:36:36.276Z
Learning: Applies to **/*.{ts,tsx} : Use `result?.serverError` with `toastError` and `toastSuccess` for error handling in server actions
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/components/**/*.tsx : Use `result?.serverError` with `toastError` and `toastSuccess` for error handling in form submissions
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use valid, non-abstract ARIA roles for elements with ARIA roles
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Make static elements with click handlers use a valid role attribute
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Make sure label elements have text content and are associated with an input
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Make sure ARIA properties are valid for the element's supported roles
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{jsx,tsx} : Watch out for possible "wrong" semicolons inside JSX elements
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:51.389Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:51.389Z
Learning: Applies to **/*Form.{ts,tsx} : Validate form inputs before submission using React Hook Form and Zod resolver
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/components/**/*Form*.tsx : Use React Hook Form with Zod validation (`zodResolver`) for form handling, with form components using `register`, `handleSubmit`, and error handling from the hook
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:51.389Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:51.389Z
Learning: Applies to **/*Form.{ts,tsx} : Use React Hook Form with Zod for form validation
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/components/**/*.tsx : Use React Hook Form with Zod validation for form components
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:53.147Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:53.147Z
Learning: Applies to **/*Form.{ts,tsx} : Use React Hook Form with Zod for validation in form components
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:51.389Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:51.389Z
Learning: Applies to **/*Form.{ts,tsx} : Show validation errors inline next to form fields in the UI
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:53.147Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:53.147Z
Learning: Applies to **/*Form.{ts,tsx} : Validate form inputs before submission
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:53.147Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:53.147Z
Learning: Applies to **/*Form.{ts,tsx} : Show validation errors inline next to form fields
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:11.919Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-25T14:42:11.919Z
Learning: Applies to utils/**/*.{js,ts,jsx,tsx} : The `utils` folder contains core app logic such as Next.js Server Actions and Gmail API requests
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:40:00.833Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-25T14:40:00.833Z
Learning: Applies to **/*.test.{ts,tsx} : Use test helpers `getEmail`, `getEmailAccount`, and `getRule` from `@/__tests__/helpers` for mocking emails, accounts, and rules
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/components/**/*Form*.tsx : Handle form submission results using `result?.serverError` to show error toasts and `toastSuccess` to show success messages after server action completion
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:40:15.063Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:15.063Z
Learning: Applies to **/*.{tsx,ts} : For text inputs, use the `Input` component with `registerProps` for form integration and error handling
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:40:15.063Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:15.063Z
Learning: Applies to **/*.tsx : For text areas, use the `Input` component with `type='text'`, `autosizeTextarea` prop set to true, and `registerProps` for form integration
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/hooks/use*.ts : Use SWR for client-side data fetching with typed responses from GET API routes
Applied to files:
apps/web/providers/SWRProvider.tsx
📚 Learning: 2025-11-25T14:36:36.276Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/data-fetching.mdc:0-0
Timestamp: 2025-11-25T14:36:36.276Z
Learning: Applies to **/*.{ts,tsx} : For API GET requests to server, use the `swr` package
Applied to files:
apps/web/providers/SWRProvider.tsx
📚 Learning: 2025-11-25T14:38:23.265Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/page-structure.mdc:0-0
Timestamp: 2025-11-25T14:38:23.265Z
Learning: Applies to apps/web/app/(app)/**/*.{ts,tsx} : If we're in a deeply nested component we will use `swr` to fetch via API
Applied to files:
apps/web/providers/SWRProvider.tsx
📚 Learning: 2025-11-25T14:39:08.150Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-11-25T14:39:08.150Z
Learning: Applies to apps/web/app/api/**/*.{ts,tsx} : Use generic error messages instead of revealing internal details; throw `SafeError` instead of exposing user IDs, resource IDs, or system information
Applied to files:
apps/web/providers/SWRProvider.tsx
📚 Learning: 2025-11-25T14:40:15.063Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:15.063Z
Learning: Applies to **/*.{tsx,ts} : For API GET requests to server, use the `swr` package with hooks like `useSWR` to fetch data
Applied to files:
apps/web/providers/SWRProvider.tsx
📚 Learning: 2025-11-25T14:40:13.649Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:13.649Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : For API get requests to server, use the `swr` package with `useSWR` hook
Applied to files:
apps/web/providers/SWRProvider.tsx
📚 Learning: 2025-11-25T14:39:27.909Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-11-25T14:39:27.909Z
Learning: Applies to **/app/api/**/*.ts : Maintain consistent error response format across all API routes to avoid information disclosure while providing meaningful error feedback
Applied to files:
apps/web/providers/SWRProvider.tsx
📚 Learning: 2025-11-25T14:38:18.874Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/page-structure.mdc:0-0
Timestamp: 2025-11-25T14:38:18.874Z
Learning: Applies to apps/web/app/(app)/**/*.tsx : If nested deeply in components, use `swr` to fetch via API instead of loading data directly
Applied to files:
apps/web/providers/SWRProvider.tsx
📚 Learning: 2025-11-25T14:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/hooks/use*.ts : Use SWR hooks for client-side data fetching, with hooks stored in `apps/web/hooks/use*.ts` that return typed responses from GET API routes
Applied to files:
apps/web/providers/SWRProvider.tsx
🧬 Code graph analysis (1)
apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsx (2)
apps/web/components/new-landing/common/Card.tsx (1)
Card(67-105)apps/web/components/Typography.tsx (1)
TypographyH3(125-125)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: test
🔇 Additional comments (7)
apps/web/providers/SWRProvider.tsx (1)
81-84: LGTM! Improved error typing.The change from
anytoRecord<string, unknown>with explicit type casting provides better type safety while maintaining the existing error handling flow.apps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx (3)
165-176: LGTM! The first-condition enforcement now preserves existing data.The fix correctly checks if the first condition is empty (
uiType === undefined) before initializing it as a prompt. This prevents overwriting existing static conditions when loading a rule, addressing the data-loss issue flagged in previous reviews.
254-301: Complex but correct reordering logic for AI Prompt.The logic properly handles moving an AI Prompt to position 0 when selected at a later index, preserving configured conditions and skipping empty ones. The duplicate checking and user feedback are well-implemented.
449-533: Well-structured form inputs with proper error handling.The condition inputs follow the project's form patterns, using the
Inputcomponent withregisterPropsfor integration and displaying inline errors. The tooltips enhance usability.apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsx (1)
5-37: Clean and well-structured card component.The component provides a consistent layout for rule sections with proper conditional rendering and styling. The use of the
cnutility for dynamic classes is appropriate.apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx (2)
386-460: Excellent modular refactoring of the rule form.The refactor into
RuleSectionCard,ConditionSteps, andActionStepscomponents significantly improves code organization and reusability. The consistent use of section cards with icons and proper error handling enhances both maintainability and user experience.
463-568: Well-implemented Advanced Settings dialog.The dialog consolidates advanced options in a clean, accessible way. The use of toggles, tooltips, and proper button states provides a good user experience.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
apps/web/app/(app)/[emailAccountId]/assistant/RulesTabNew.tsx (1)
7-7: LGTM! UI alignment change looks good.The addition of
justify-endappropriately aligns the AddRuleDialog button to the right, consistent with the PR's UI refactoring goals.Optionally verify the mobile UX—the button will remain right-aligned on smaller screens. If centering or full-width alignment is preferred on mobile, consider adding responsive classes like
justify-center sm:justify-endor similar.apps/web/app/(app)/[emailAccountId]/setup/StatsCardGrid.tsx (2)
96-101: Prefer the wrapper Tooltip component for better mobile support.The code uses raw shadcn Tooltip components directly. The project has a wrapper component at
@/components/Tooltip.tsxthat adds mobile click-to-toggle functionality, improving UX on touch devices.Apply this diff to use the wrapper component:
import { Card } from "@/components/ui/card"; -import { - Tooltip, - TooltipContent, - TooltipTrigger, -} from "@/components/ui/tooltip"; +import { Tooltip } from "@/components/Tooltip"; import { formatStat } from "@/utils/stats"; // ... in the render: {item.tooltip && ( - <Tooltip> - <TooltipTrigger asChild> - <InfoIcon className="h-4 w-4 cursor-pointer text-gray-400 hover:text-gray-500" /> - </TooltipTrigger> - <TooltipContent>{item.tooltip}</TooltipContent> - </Tooltip> + <Tooltip content={item.tooltip}> + <InfoIcon className="h-4 w-4 cursor-pointer text-gray-400 hover:text-gray-500" /> + </Tooltip> )}
86-86: Consider using a stable key instead of array index.While using
indexas a key works for static arrays, using a stable identifier likeitem.titlewould be more maintainable if the items array becomes dynamic in the future.- <div key={index} className="flex-1 p-6"> + <div key={item.title} className="flex-1 p-6">
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
apps/web/app/(app)/[emailAccountId]/assistant/RulesTabNew.tsx(1 hunks)apps/web/app/(app)/[emailAccountId]/setup/SetupContent.tsx(1 hunks)apps/web/app/(app)/[emailAccountId]/setup/StatsCardGrid.tsx(1 hunks)apps/web/components/Combobox.tsx(0 hunks)apps/web/components/SideNav.tsx(2 hunks)
💤 Files with no reviewable changes (1)
- apps/web/components/Combobox.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/web/app/(app)/[emailAccountId]/setup/SetupContent.tsx
- apps/web/components/SideNav.tsx
🧰 Additional context used
📓 Path-based instructions (13)
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Use@/path aliases for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Follow consistent naming conventions using PascalCase for components
Centralize shared types in dedicated type filesImport specific lodash functions rather than entire lodash library to minimize bundle size (e.g.,
import groupBy from 'lodash/groupBy')
Files:
apps/web/app/(app)/[emailAccountId]/setup/StatsCardGrid.tsxapps/web/app/(app)/[emailAccountId]/assistant/RulesTabNew.tsx
apps/web/app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
Follow NextJS app router structure with (app) directory
Files:
apps/web/app/(app)/[emailAccountId]/setup/StatsCardGrid.tsxapps/web/app/(app)/[emailAccountId]/assistant/RulesTabNew.tsx
apps/web/**/*.tsx
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/**/*.tsx: Follow tailwindcss patterns with prettier-plugin-tailwindcss for class sorting
Prefer functional components with hooks over class components
Use shadcn/ui components when available
Ensure responsive design with mobile-first approach
Use LoadingContent component for async data with loading and error states
Files:
apps/web/app/(app)/[emailAccountId]/setup/StatsCardGrid.tsxapps/web/app/(app)/[emailAccountId]/assistant/RulesTabNew.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/data-fetching.mdc)
**/*.{ts,tsx}: For API GET requests to server, use theswrpackage
Useresult?.serverErrorwithtoastErrorfrom@/components/Toastfor error handling in async operations
**/*.{ts,tsx}: Use wrapper functions for Gmail message operations (get, list, batch, etc.) from @/utils/gmail/message.ts instead of direct API calls
Use wrapper functions for Gmail thread operations from @/utils/gmail/thread.ts instead of direct API calls
Use wrapper functions for Gmail label operations from @/utils/gmail/label.ts instead of direct API calls
**/*.{ts,tsx}: For early access feature flags, create hooks using the naming conventionuse[FeatureName]Enabledthat return a boolean fromuseFeatureFlagEnabled("flag-key")
For A/B test variant flags, create hooks using the naming conventionuse[FeatureName]Variantthat define variant types, useuseFeatureFlagVariantKey()with type casting, and provide a default "control" fallback
Use kebab-case for PostHog feature flag keys (e.g.,inbox-cleaner,pricing-options-2)
Always define types for A/B test variant flags (e.g.,type PricingVariant = "control" | "variant-a" | "variant-b") and provide type safety through type casting
**/*.{ts,tsx}: Don't use primitive type aliases or misleading types
Don't use empty type parameters in type aliases and interfaces
Don't use this and super in static contexts
Don't use any or unknown as type constraints
Don't use the TypeScript directive @ts-ignore
Don't use TypeScript enums
Don't export imported variables
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions
Don't use TypeScript namespaces
Don't use non-null assertions with the!postfix operator
Don't use parameter properties in class constructors
Don't use user-defined types
Useas constinstead of literal types and type annotations
Use eitherT[]orArray<T>consistently
Initialize each enum member value explicitly
Useexport typefor types
Use `impo...
Files:
apps/web/app/(app)/[emailAccountId]/setup/StatsCardGrid.tsxapps/web/app/(app)/[emailAccountId]/assistant/RulesTabNew.tsx
apps/web/app/(app)/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/page-structure.mdc)
apps/web/app/(app)/**/*.{ts,tsx}: Components for the page are either put inpage.tsx, or in theapps/web/app/(app)/PAGE_NAMEfolder
If we're in a deeply nested component we will useswrto fetch via API
If you need to useonClickin a component, that component is a client component and file must start withuse client
Files:
apps/web/app/(app)/[emailAccountId]/setup/StatsCardGrid.tsxapps/web/app/(app)/[emailAccountId]/assistant/RulesTabNew.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/prisma-enum-imports.mdc)
Always import Prisma enums from
@/generated/prisma/enumsinstead of@/generated/prisma/clientto avoid Next.js bundling errors in client componentsImport Prisma using the project's centralized utility:
import prisma from '@/utils/prisma'
Files:
apps/web/app/(app)/[emailAccountId]/setup/StatsCardGrid.tsxapps/web/app/(app)/[emailAccountId]/assistant/RulesTabNew.tsx
**/*.{tsx,ts}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
**/*.{tsx,ts}: Use Shadcn UI and Tailwind for components and styling
Usenext/imagepackage for images
For API GET requests to server, use theswrpackage with hooks likeuseSWRto fetch data
For text inputs, use theInputcomponent withregisterPropsfor form integration and error handling
Files:
apps/web/app/(app)/[emailAccountId]/setup/StatsCardGrid.tsxapps/web/app/(app)/[emailAccountId]/assistant/RulesTabNew.tsx
**/*.{tsx,ts,css}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
Implement responsive design with Tailwind CSS using a mobile-first approach
Files:
apps/web/app/(app)/[emailAccountId]/setup/StatsCardGrid.tsxapps/web/app/(app)/[emailAccountId]/assistant/RulesTabNew.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
**/*.tsx: Use theLoadingContentcomponent to handle loading states instead of manual loading state management
For text areas, use theInputcomponent withtype='text',autosizeTextareaprop set to true, andregisterPropsfor form integration
Files:
apps/web/app/(app)/[emailAccountId]/setup/StatsCardGrid.tsxapps/web/app/(app)/[emailAccountId]/assistant/RulesTabNew.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{js,jsx,ts,tsx}: Don't useaccessKeyattribute on any HTML element
Don't setaria-hidden="true"on focusable elements
Don't add ARIA roles, states, and properties to elements that don't support them
Don't use distracting elements like<marquee>or<blink>
Only use thescopeprop on<th>elements
Don't assign non-interactive ARIA roles to interactive HTML elements
Make sure label elements have text content and are associated with an input
Don't assign interactive ARIA roles to non-interactive HTML elements
Don't assigntabIndexto non-interactive HTML elements
Don't use positive integers fortabIndexproperty
Don't include "image", "picture", or "photo" in img alt prop
Don't use explicit role property that's the same as the implicit/default role
Make static elements with click handlers use a valid role attribute
Always include atitleelement for SVG elements
Give all elements requiring alt text meaningful information for screen readers
Make sure anchors have content that's accessible to screen readers
AssigntabIndexto non-interactive HTML elements witharia-activedescendant
Include all required ARIA attributes for elements with ARIA roles
Make sure ARIA properties are valid for the element's supported roles
Always include atypeattribute for button elements
Make elements with interactive roles and handlers focusable
Give heading elements content that's accessible to screen readers (not hidden witharia-hidden)
Always include alangattribute on the html element
Always include atitleattribute for iframe elements
AccompanyonClickwith at least one of:onKeyUp,onKeyDown, oronKeyPress
AccompanyonMouseOver/onMouseOutwithonFocus/onBlur
Include caption tracks for audio and video elements
Use semantic elements instead of role attributes in JSX
Make sure all anchors are valid and navigable
Ensure all ARIA properties (aria-*) are valid
Use valid, non-abstract ARIA roles for elements with ARIA roles
Use valid AR...
Files:
apps/web/app/(app)/[emailAccountId]/setup/StatsCardGrid.tsxapps/web/app/(app)/[emailAccountId]/assistant/RulesTabNew.tsx
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{jsx,tsx}: Don't use unnecessary fragments
Don't pass children as props
Don't use the return value of React.render
Make sure all dependencies are correctly specified in React hooks
Make sure all React hooks are called from the top level of component functions
Don't forget key props in iterators and collection literals
Don't define React components inside other components
Don't use event handlers on non-interactive elements
Don't assign to React component props
Don't use bothchildrenanddangerouslySetInnerHTMLprops on the same element
Don't use dangerous JSX props
Don't use Array index in keys
Don't insert comments as text nodes
Don't assign JSX properties multiple times
Don't add extra closing tags for components without children
Use<>...</>instead of<Fragment>...</Fragment>
Watch out for possible "wrong" semicolons inside JSX elements
Make sure void (self-closing) elements don't have children
Don't usetarget="_blank"withoutrel="noopener"
Don't use<img>elements in Next.js projects
Don't use<head>elements in Next.js projects
Files:
apps/web/app/(app)/[emailAccountId]/setup/StatsCardGrid.tsxapps/web/app/(app)/[emailAccountId]/assistant/RulesTabNew.tsx
!(pages/_document).{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
Don't use the next/head module in pages/_document.js on Next.js projects
Files:
apps/web/app/(app)/[emailAccountId]/setup/StatsCardGrid.tsxapps/web/app/(app)/[emailAccountId]/assistant/RulesTabNew.tsx
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
**/*.{js,ts,jsx,tsx}: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size (e.g.,import groupBy from 'lodash/groupBy')
Files:
apps/web/app/(app)/[emailAccountId]/setup/StatsCardGrid.tsxapps/web/app/(app)/[emailAccountId]/assistant/RulesTabNew.tsx
🧠 Learnings (2)
📚 Learning: 2025-11-25T14:38:56.992Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-11-25T14:38:56.992Z
Learning: Applies to apps/web/components/ui/**/*.tsx : Shadcn UI components are located in `components/ui` directory
Applied to files:
apps/web/app/(app)/[emailAccountId]/setup/StatsCardGrid.tsx
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : Use XML-like tags to structure data in prompts, remove excessive whitespace and truncate long inputs, and format data consistently across similar LLM functions
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RulesTabNew.tsx
🧬 Code graph analysis (1)
apps/web/app/(app)/[emailAccountId]/setup/StatsCardGrid.tsx (2)
apps/web/components/new-landing/common/Card.tsx (1)
Card(67-105)apps/web/components/Tooltip.tsx (1)
Tooltip(18-41)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: test
🔇 Additional comments (1)
apps/web/app/(app)/[emailAccountId]/setup/StatsCardGrid.tsx (1)
13-50: LGTM! Well-structured type definitions.The variants object and type definitions are clean, with good dark mode support and flexible design that allows either predefined variants or custom colors.
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (2)
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx (2)
279-284: MissingElementTypeimport causes potential runtime issuesThe code uses
React.ElementTypeat line 283, butElementTypeis not imported from React. While this works becauseReactis implicitly available through JSX transform, it's inconsistent with the project's import patterns and could fail in strict ESM environments.Apply this diff:
-import { useCallback, useEffect, useMemo, useState } from "react"; +import { useCallback, useEffect, useMemo, useState, type ElementType } from "react";Then update the type:
- icon: React.ElementType; + icon: ElementType;
561-565: Empty catch block loses error context for debuggingThe catch block swallows the error without logging, making it difficult to debug failed delete operations.
-} catch { +} catch (error) { + console.error("Failed to delete rule:", error); toastError({ description: "Failed to delete rule." }); }
🧹 Nitpick comments (7)
apps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx (3)
419-427: Consider using theInputcomponent withautosizeTextareapropPer coding guidelines, text areas should use the
Inputcomponent withautosizeTextareaprop for consistency and form integration. The currentTextareaAutosizeusage bypasses the project's standard form input patterns.-<TextareaAutosize - className="block w-full flex-1 whitespace-pre-wrap rounded-md border border-border bg-background shadow-sm focus:border-black focus:ring-black sm:text-sm" - minRows={3} - rows={3} - {...register(`conditions.${index}.instructions`)} - placeholder="e.g. Newsletters, regular content from publications, blogs, or services I've subscribed to" -/> +<Input + type="text" + autosizeTextarea + rows={3} + name={`conditions.${index}.instructions`} + registerProps={register(`conditions.${index}.instructions`)} + placeholder="e.g. Newsletters, regular content from publications, blogs, or services I've subscribed to" +/>
253-271: Duplicate type validation could be extracted into a reusable helperThe duplicate checking logic is inline and moderately complex. Consider extracting it for testability and reuse:
function hasDuplicateUITypes( conditions: ZodCondition[], index: number, newValue: UIConditionType ): boolean { const prospectiveUITypes = conditions.map((c, idx) => idx === index ? newValue : getUIConditionType(c) ); const configuredTypes = prospectiveUITypes.filter( (type): type is UIConditionType => type !== undefined ); return new Set(configuredTypes).size !== configuredTypes.length; }
277-300: Complex array reordering when selecting "prompt" at non-first positionThe logic to move an AI Prompt to position 0 when selected elsewhere is intricate. While functionally correct, consider:
- Adding a comment explaining why AI Prompt must be first
- The condition at line 290-293 may keep an empty condition in the array when
currentConditionType !== undefinedThe current behavior appears intentional but could be clearer.
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx (2)
528-567: Delete confirmation uses nativeconfirm()dialogThe delete flow uses
window.confirm()which is functional but inconsistent with the rest of the UI that uses shadcn/ui Dialog components. For a more polished UX, consider using a confirmation Dialog component.
440-442: Use stable keys instead of array index for error list itemsUsing array index as key (
action-${index}) can cause rendering issues if errors are reordered. Since error messages should be unique, consider using the message itself:-{actionErrors.map((error, index) => ( - <li key={`action-${index}`}>{error}</li> +{actionErrors.map((error) => ( + <li key={error}>{error}</li> ))}apps/web/utils/condition.ts (2)
117-139: Shape consistency improved betweengetConditionsandgetEmptyConditionThe
getEmptyConditionfor STATIC now includesinstructions: null(line 132), matching the shape produced bygetConditions. This addresses the shape inconsistency noted in previous reviews.However, the AI case at lines 120-123 still omits the
from,to,subject,bodyfields whilegetConditionsincludes them as null. Consider adding explicit null fields for full consistency:case ConditionType.AI: return { type: ConditionType.AI, instructions: "", + from: null, + to: null, + subject: null, + body: null, };
149-171:flattenConditionssilently overwrites duplicate field valuesWhen multiple STATIC conditions have the same field populated (e.g., two conditions with
fromvalues), only the last one is kept. With the new UI design where each STATIC condition has exactly one field, this shouldn't happen in practice—but the function doesn't guard against it.Consider adding validation or a warning:
case ConditionType.STATIC: - acc.to = condition.to; - acc.from = condition.from; - acc.subject = condition.subject; - acc.body = condition.body; + if (condition.to) { + if (acc.to) logger.warn("Overwriting existing 'to' condition"); + acc.to = condition.to; + } + if (condition.from) { + if (acc.from) logger.warn("Overwriting existing 'from' condition"); + acc.from = condition.from; + } + if (condition.subject) { + if (acc.subject) logger.warn("Overwriting existing 'subject' condition"); + acc.subject = condition.subject; + } + if (condition.body) { + if (acc.body) logger.warn("Overwriting existing 'body' condition"); + acc.body = condition.body; + } break;
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
apps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx(1 hunks)apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx(6 hunks)apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsx(1 hunks)apps/web/components/Input.tsx(1 hunks)apps/web/utils/actions/rule.validation.ts(1 hunks)apps/web/utils/condition.ts(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/web/utils/actions/rule.validation.ts
- apps/web/app/(app)/[emailAccountId]/assistant/RuleStep.tsx
🧰 Additional context used
📓 Path-based instructions (18)
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Use@/path aliases for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Follow consistent naming conventions using PascalCase for components
Centralize shared types in dedicated type filesImport specific lodash functions rather than entire lodash library to minimize bundle size (e.g.,
import groupBy from 'lodash/groupBy')
Files:
apps/web/components/Input.tsxapps/web/utils/condition.tsapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
apps/web/**/*.tsx
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/**/*.tsx: Follow tailwindcss patterns with prettier-plugin-tailwindcss for class sorting
Prefer functional components with hooks over class components
Use shadcn/ui components when available
Ensure responsive design with mobile-first approach
Use LoadingContent component for async data with loading and error states
Files:
apps/web/components/Input.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
apps/web/components/**/*.tsx
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/components/**/*.tsx: Use React Hook Form with Zod validation for form components
Useresult?.serverErrorwithtoastErrorandtoastSuccessfor error handling in form submissionsUse
LoadingContentcomponent to consistently handle loading and error states, passingloading,error, andchildrenpropsUse PascalCase for component file names (e.g.,
components/Button.tsx)
Files:
apps/web/components/Input.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/data-fetching.mdc)
**/*.{ts,tsx}: For API GET requests to server, use theswrpackage
Useresult?.serverErrorwithtoastErrorfrom@/components/Toastfor error handling in async operations
**/*.{ts,tsx}: Use wrapper functions for Gmail message operations (get, list, batch, etc.) from @/utils/gmail/message.ts instead of direct API calls
Use wrapper functions for Gmail thread operations from @/utils/gmail/thread.ts instead of direct API calls
Use wrapper functions for Gmail label operations from @/utils/gmail/label.ts instead of direct API calls
**/*.{ts,tsx}: For early access feature flags, create hooks using the naming conventionuse[FeatureName]Enabledthat return a boolean fromuseFeatureFlagEnabled("flag-key")
For A/B test variant flags, create hooks using the naming conventionuse[FeatureName]Variantthat define variant types, useuseFeatureFlagVariantKey()with type casting, and provide a default "control" fallback
Use kebab-case for PostHog feature flag keys (e.g.,inbox-cleaner,pricing-options-2)
Always define types for A/B test variant flags (e.g.,type PricingVariant = "control" | "variant-a" | "variant-b") and provide type safety through type casting
**/*.{ts,tsx}: Don't use primitive type aliases or misleading types
Don't use empty type parameters in type aliases and interfaces
Don't use this and super in static contexts
Don't use any or unknown as type constraints
Don't use the TypeScript directive @ts-ignore
Don't use TypeScript enums
Don't export imported variables
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions
Don't use TypeScript namespaces
Don't use non-null assertions with the!postfix operator
Don't use parameter properties in class constructors
Don't use user-defined types
Useas constinstead of literal types and type annotations
Use eitherT[]orArray<T>consistently
Initialize each enum member value explicitly
Useexport typefor types
Use `impo...
Files:
apps/web/components/Input.tsxapps/web/utils/condition.tsapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/{pages,routes,components}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/gmail-api.mdc)
Never call Gmail API directly from routes or components - always use wrapper functions from the utils folder
Files:
apps/web/components/Input.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/prisma-enum-imports.mdc)
Always import Prisma enums from
@/generated/prisma/enumsinstead of@/generated/prisma/clientto avoid Next.js bundling errors in client componentsImport Prisma using the project's centralized utility:
import prisma from '@/utils/prisma'
Files:
apps/web/components/Input.tsxapps/web/utils/condition.tsapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*.{tsx,ts}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
**/*.{tsx,ts}: Use Shadcn UI and Tailwind for components and styling
Usenext/imagepackage for images
For API GET requests to server, use theswrpackage with hooks likeuseSWRto fetch data
For text inputs, use theInputcomponent withregisterPropsfor form integration and error handling
Files:
apps/web/components/Input.tsxapps/web/utils/condition.tsapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*.{tsx,ts,css}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
Implement responsive design with Tailwind CSS using a mobile-first approach
Files:
apps/web/components/Input.tsxapps/web/utils/condition.tsapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
**/*.tsx: Use theLoadingContentcomponent to handle loading states instead of manual loading state management
For text areas, use theInputcomponent withtype='text',autosizeTextareaprop set to true, andregisterPropsfor form integration
Files:
apps/web/components/Input.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{js,jsx,ts,tsx}: Don't useaccessKeyattribute on any HTML element
Don't setaria-hidden="true"on focusable elements
Don't add ARIA roles, states, and properties to elements that don't support them
Don't use distracting elements like<marquee>or<blink>
Only use thescopeprop on<th>elements
Don't assign non-interactive ARIA roles to interactive HTML elements
Make sure label elements have text content and are associated with an input
Don't assign interactive ARIA roles to non-interactive HTML elements
Don't assigntabIndexto non-interactive HTML elements
Don't use positive integers fortabIndexproperty
Don't include "image", "picture", or "photo" in img alt prop
Don't use explicit role property that's the same as the implicit/default role
Make static elements with click handlers use a valid role attribute
Always include atitleelement for SVG elements
Give all elements requiring alt text meaningful information for screen readers
Make sure anchors have content that's accessible to screen readers
AssigntabIndexto non-interactive HTML elements witharia-activedescendant
Include all required ARIA attributes for elements with ARIA roles
Make sure ARIA properties are valid for the element's supported roles
Always include atypeattribute for button elements
Make elements with interactive roles and handlers focusable
Give heading elements content that's accessible to screen readers (not hidden witharia-hidden)
Always include alangattribute on the html element
Always include atitleattribute for iframe elements
AccompanyonClickwith at least one of:onKeyUp,onKeyDown, oronKeyPress
AccompanyonMouseOver/onMouseOutwithonFocus/onBlur
Include caption tracks for audio and video elements
Use semantic elements instead of role attributes in JSX
Make sure all anchors are valid and navigable
Ensure all ARIA properties (aria-*) are valid
Use valid, non-abstract ARIA roles for elements with ARIA roles
Use valid AR...
Files:
apps/web/components/Input.tsxapps/web/utils/condition.tsapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{jsx,tsx}: Don't use unnecessary fragments
Don't pass children as props
Don't use the return value of React.render
Make sure all dependencies are correctly specified in React hooks
Make sure all React hooks are called from the top level of component functions
Don't forget key props in iterators and collection literals
Don't define React components inside other components
Don't use event handlers on non-interactive elements
Don't assign to React component props
Don't use bothchildrenanddangerouslySetInnerHTMLprops on the same element
Don't use dangerous JSX props
Don't use Array index in keys
Don't insert comments as text nodes
Don't assign JSX properties multiple times
Don't add extra closing tags for components without children
Use<>...</>instead of<Fragment>...</Fragment>
Watch out for possible "wrong" semicolons inside JSX elements
Make sure void (self-closing) elements don't have children
Don't usetarget="_blank"withoutrel="noopener"
Don't use<img>elements in Next.js projects
Don't use<head>elements in Next.js projects
Files:
apps/web/components/Input.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
!(pages/_document).{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
Don't use the next/head module in pages/_document.js on Next.js projects
Files:
apps/web/components/Input.tsxapps/web/utils/condition.tsapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
**/*.{js,ts,jsx,tsx}: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size (e.g.,import groupBy from 'lodash/groupBy')
Files:
apps/web/components/Input.tsxapps/web/utils/condition.tsapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/{server,api,actions,utils}/**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/logging.mdc)
**/{server,api,actions,utils}/**/*.ts: UsecreateScopedLoggerfrom "@/utils/logger" for logging in backend code
Add thecreateScopedLoggerinstantiation at the top of the file with an appropriate scope name
Use.with()method to attach context variables only within specific functions, not on global loggers
For large functions with reused variables, usecreateScopedLogger().with()to attach context once and reuse the logger without passing variables repeatedly
Files:
apps/web/utils/condition.ts
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/security.mdc)
**/*.ts: ALL database queries MUST be scoped to the authenticated user/account by including user/account filtering in WHERE clauses to prevent unauthorized data access
Always validate that resources belong to the authenticated user before performing operations, using ownership checks in WHERE clauses or relationships
Always validate all input parameters for type, format, and length before using them in database queries
Use SafeError for error responses to prevent information disclosure. Generic error messages should not reveal internal IDs, logic, or resource ownership details
Only return necessary fields in API responses using Prisma'sselectoption. Never expose sensitive data such as password hashes, private keys, or system flags
Prevent Insecure Direct Object References (IDOR) by validating resource ownership before operations. AllfindUnique/findFirstcalls MUST include ownership filters
Prevent mass assignment vulnerabilities by explicitly whitelisting allowed fields in update operations instead of accepting all user-provided data
Prevent privilege escalation by never allowing users to modify system fields, ownership fields, or admin-only attributes through user input
AllfindManyqueries MUST be scoped to the user's data by including appropriate WHERE filters to prevent returning data from other users
Use Prisma relationships for access control by leveraging nested where clauses (e.g.,emailAccount: { id: emailAccountId }) to validate ownership
Files:
apps/web/utils/condition.ts
apps/web/app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
Follow NextJS app router structure with (app) directory
Files:
apps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
apps/web/app/(app)/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/page-structure.mdc)
apps/web/app/(app)/**/*.{ts,tsx}: Components for the page are either put inpage.tsx, or in theapps/web/app/(app)/PAGE_NAMEfolder
If we're in a deeply nested component we will useswrto fetch via API
If you need to useonClickin a component, that component is a client component and file must start withuse client
Files:
apps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*Form.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/form-handling.mdc)
**/*Form.{ts,tsx}: Use React Hook Form with Zod for validation in form components
Validate form inputs before submission
Show validation errors inline next to form fields
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
🧠 Learnings (37)
📚 Learning: 2025-11-25T14:40:15.063Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:15.063Z
Learning: Applies to **/*.{tsx,ts} : For text inputs, use the `Input` component with `registerProps` for form integration and error handling
Applied to files:
apps/web/components/Input.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:40:13.649Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:13.649Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : For text areas in forms, use the `Input` component with `type='text'`, `autosizeTextarea` prop, `rows`, `name`, `placeholder`, `registerProps` from react-hook-form, and `error` props
Applied to files:
apps/web/components/Input.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:40:13.649Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:13.649Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : For text inputs in forms, use the `Input` component with `type='email'`, `name`, `label`, `registerProps` from react-hook-form, and `error` props
Applied to files:
apps/web/components/Input.tsxapps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:40:15.063Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:15.063Z
Learning: Applies to **/*.tsx : For text areas, use the `Input` component with `type='text'`, `autosizeTextarea` prop set to true, and `registerProps` for form integration
Applied to files:
apps/web/components/Input.tsx
📚 Learning: 2025-11-25T14:36:51.389Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:51.389Z
Learning: Applies to **/*Form.{ts,tsx} : Show validation errors inline next to form fields in the UI
Applied to files:
apps/web/components/Input.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Make sure label elements have text content and are associated with an input
Applied to files:
apps/web/components/Input.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:53.147Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:53.147Z
Learning: Applies to **/*Form.{ts,tsx} : Show validation errors inline next to form fields
Applied to files:
apps/web/components/Input.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/components/**/*.tsx : Use `result?.serverError` with `toastError` and `toastSuccess` for error handling in form submissions
Applied to files:
apps/web/components/Input.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use semantic elements instead of role attributes in JSX
Applied to files:
apps/web/components/Input.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/components/**/*Form*.tsx : Handle form submission results using `result?.serverError` to show error toasts and `toastSuccess` to show success messages after server action completion
Applied to files:
apps/web/components/Input.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't use constant expressions in conditions
Applied to files:
apps/web/utils/condition.ts
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't use duplicate conditions in if-else-if chains
Applied to files:
apps/web/utils/condition.ts
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : Use XML-like tags to structure data in prompts, remove excessive whitespace and truncate long inputs, and format data consistently across similar LLM functions
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : LLM feature functions must follow a standard structure: accept options with `inputData` and `emailAccount` parameters, implement input validation with early returns, define separate system and user prompts, create a Zod schema for response validation, and use `createGenerateObject` to execute the LLM call
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/**/*.{ts,tsx} : Use proper error handling with try/catch blocks
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:39:23.326Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-11-25T14:39:23.326Z
Learning: Applies to app/api/**/*.ts : Use `SafeError` for error responses to prevent information disclosure - provide generic messages (e.g., 'Rule not found' not 'Rule {id} does not exist for user {userId}') without revealing internal IDs or ownership details
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't use unnecessary catch clauses
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't reassign exceptions in catch clauses
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:40.146Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/data-fetching.mdc:0-0
Timestamp: 2025-11-25T14:36:40.146Z
Learning: Applies to **/*.{ts,tsx} : Use `result?.serverError` with `toastError` from `@/components/Toast` for error handling in async operations
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:36.276Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/data-fetching.mdc:0-0
Timestamp: 2025-11-25T14:36:36.276Z
Learning: Applies to **/*.{ts,tsx} : Use `result?.serverError` with `toastError` and `toastSuccess` for error handling in server actions
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Always include a `type` attribute for button elements
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use valid, non-abstract ARIA roles for elements with ARIA roles
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{jsx,tsx} : Make sure all dependencies are correctly specified in React hooks
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Make static elements with click handlers use a valid role attribute
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Make sure ARIA properties are valid for the element's supported roles
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{jsx,tsx} : Watch out for possible "wrong" semicolons inside JSX elements
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:51.389Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:51.389Z
Learning: Applies to **/*Form.{ts,tsx} : Validate form inputs before submission using React Hook Form and Zod resolver
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/components/**/*Form*.tsx : Use React Hook Form with Zod validation (`zodResolver`) for form handling, with form components using `register`, `handleSubmit`, and error handling from the hook
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:51.389Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:51.389Z
Learning: Applies to **/*Form.{ts,tsx} : Use React Hook Form with Zod for form validation
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/components/**/*.tsx : Use React Hook Form with Zod validation for form components
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:53.147Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:53.147Z
Learning: Applies to **/*Form.{ts,tsx} : Use React Hook Form with Zod for validation in form components
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:53.147Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:53.147Z
Learning: Applies to **/*Form.{ts,tsx} : Validate form inputs before submission
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:38:56.992Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-11-25T14:38:56.992Z
Learning: Applies to apps/web/components/ui/**/*.tsx : Shadcn UI components are located in `components/ui` directory
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/**/*.tsx : Use shadcn/ui components when available
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:11.919Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-25T14:42:11.919Z
Learning: Applies to utils/**/*.{js,ts,jsx,tsx} : The `utils` folder contains core app logic such as Next.js Server Actions and Gmail API requests
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:40:00.833Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-25T14:40:00.833Z
Learning: Applies to **/*.test.{ts,tsx} : Use test helpers `getEmail`, `getEmailAccount`, and `getRule` from `@/__tests__/helpers` for mocking emails, accounts, and rules
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-09T19:50:05.292Z
Learnt from: ppranay20
Repo: elie222/inbox-zero PR: 935
File: apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx:367-369
Timestamp: 2025-11-09T19:50:05.292Z
Learning: In React Hook Form, when using `useMemo` or `useEffect` with form errors, always use `formState` as the dependency rather than `errors` or `formState.errors`. This is because React Hook Form uses a Proxy pattern where the errors object is mutable and won't trigger dependency arrays correctly. The formState dependency ensures proper reactivity when form validation state changes.
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
🧬 Code graph analysis (1)
apps/web/utils/condition.ts (1)
apps/web/utils/config.ts (2)
ConditionType(14-19)ConditionType(21-21)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: test
🔇 Additional comments (8)
apps/web/components/Input.tsx (1)
143-143: LGTM – Styling simplified for consistency.The removal of
font-semiboldandleading-snugstreamlines the error message styling while preserving visibility through the red color. This aligns with the PR's goal of consistent typography across the new card-based UI components.apps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx (2)
165-176: useEffect still has edge-case data loss potentialThe current implementation only sets a prompt condition when
uiType === undefined, which is an improvement from the earlier version. However, there's still a subtle issue: if a rule is loaded with conditions whereconditions[0]exists but has all fields null (whichgetConditionFromUIType(undefined)produces), this will get replaced with a prompt condition, potentially not matching user intent.Consider adding a more explicit check or documenting this behavior:
useEffect(() => { if (conditions.length > 0) { const firstCondition = conditions[0]; const uiType = getUIConditionType(firstCondition); // Only set to prompt if the condition is empty (undefined type) // Don't replace existing static conditions (from/to/subject) - if (uiType === undefined) { + // Also check if this is a freshly added empty condition vs loaded data + if (uiType === undefined && firstCondition.type !== ConditionType.AI) { const promptCondition = getConditionFromUIType("prompt"); setValue("conditions.0", promptCondition); } } }, [conditions, setValue]);
546-547: Tooltip text function is well-structuredThe
getFilterTooltipTexthelper provides consistent, informative tooltip content for filter types.apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx (3)
392-428: Well-structured conditional rendering for rule sectionsThe
RuleSectionCardwrapper with conditional content based onisConversationStatusTypeprovides clear separation of concerns. The error display integration is clean.
253-256: React Hook Form dependency onconditionsin useEffectThe
useEffectthat triggers validation has a suppressed exhaustive-deps warning. Per learnings, when using form state in effects, prefer usingformStateas the dependency rather than derived values likeconditions. However, since this is triggering validation (not reading errors), the current approach is acceptable.
273-277: Error handling is properly separated between form-level and field-specific errorsThe current implementation is correct and intentional.
formErrorscaptures only top-level errors with a directmessageproperty (like validation on thenamefield). Array-level errors forconditionsandactionsare handled separately and explicitly:
conditionsarray errors display viaerrors.conditions?.root?.message(line 397)actionsarray errors extract viaactionErrorswhich accesseserrors?.actions?.[index]?.{url,labelId,to}?.root?.message(lines 258-268)This is proper separation of concerns. No changes needed.
apps/web/utils/condition.ts (2)
57-99: Well-structured STATIC condition splittingThe new approach of creating separate STATIC conditions for each populated field aligns well with the UI design where each condition row handles a single field. The explicit null values for unused fields maintain type consistency.
46-55: AI condition now includes explicit null fieldsGood improvement—the AI condition object now includes explicit
from: null,to: null,subject: null,body: nullfields, ensuring consistent shape with STATIC conditions and preventing potential undefined property access.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx (2)
279-284: Add missingElementTypeimport.This is still using
React.ElementTypewithout importing it. As flagged in the previous review, you need to importElementTypefrom React.Apply this diff:
-import { useCallback, useEffect, useMemo, useState } from "react"; +import { useCallback, useEffect, useMemo, useState, type ElementType } from "react";And update the type definition:
const typeOptions = useMemo(() => { const options: { label: string; value: ActionType; - icon: React.ElementType; + icon: ElementType; }[] = [
528-567: Empty catch block loses error context.The catch block at line 561 swallows the error without logging it, making debugging difficult if the delete operation fails for unexpected reasons. This was flagged in the previous review.
Apply this diff:
- } catch { + } catch (error) { + console.error("Failed to delete rule:", error); toastError({ description: "Failed to delete rule." });
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx(7 hunks)apps/web/utils/ai/assistant/process-user-request.ts(1 hunks)version.txt(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- version.txt
🧰 Additional context used
📓 Path-based instructions (18)
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Use@/path aliases for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Follow consistent naming conventions using PascalCase for components
Centralize shared types in dedicated type filesImport specific lodash functions rather than entire lodash library to minimize bundle size (e.g.,
import groupBy from 'lodash/groupBy')
Files:
apps/web/utils/ai/assistant/process-user-request.tsapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/data-fetching.mdc)
**/*.{ts,tsx}: For API GET requests to server, use theswrpackage
Useresult?.serverErrorwithtoastErrorfrom@/components/Toastfor error handling in async operations
**/*.{ts,tsx}: Use wrapper functions for Gmail message operations (get, list, batch, etc.) from @/utils/gmail/message.ts instead of direct API calls
Use wrapper functions for Gmail thread operations from @/utils/gmail/thread.ts instead of direct API calls
Use wrapper functions for Gmail label operations from @/utils/gmail/label.ts instead of direct API calls
**/*.{ts,tsx}: For early access feature flags, create hooks using the naming conventionuse[FeatureName]Enabledthat return a boolean fromuseFeatureFlagEnabled("flag-key")
For A/B test variant flags, create hooks using the naming conventionuse[FeatureName]Variantthat define variant types, useuseFeatureFlagVariantKey()with type casting, and provide a default "control" fallback
Use kebab-case for PostHog feature flag keys (e.g.,inbox-cleaner,pricing-options-2)
Always define types for A/B test variant flags (e.g.,type PricingVariant = "control" | "variant-a" | "variant-b") and provide type safety through type casting
**/*.{ts,tsx}: Don't use primitive type aliases or misleading types
Don't use empty type parameters in type aliases and interfaces
Don't use this and super in static contexts
Don't use any or unknown as type constraints
Don't use the TypeScript directive @ts-ignore
Don't use TypeScript enums
Don't export imported variables
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions
Don't use TypeScript namespaces
Don't use non-null assertions with the!postfix operator
Don't use parameter properties in class constructors
Don't use user-defined types
Useas constinstead of literal types and type annotations
Use eitherT[]orArray<T>consistently
Initialize each enum member value explicitly
Useexport typefor types
Use `impo...
Files:
apps/web/utils/ai/assistant/process-user-request.tsapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
apps/web/{utils/ai,utils/llms,__tests__}/**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/llm.mdc)
LLM-related code must be organized in specific directories:
apps/web/utils/ai/for main implementations,apps/web/utils/llms/for core utilities and configurations, andapps/web/__tests__/for LLM-specific tests
Files:
apps/web/utils/ai/assistant/process-user-request.ts
apps/web/utils/ai/**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/llm.mdc)
apps/web/utils/ai/**/*.ts: LLM feature functions must import fromzodfor schema validation, usecreateScopedLoggerfrom@/utils/logger,chatCompletionObjectandcreateGenerateObjectfrom@/utils/llms, and importEmailAccountWithAItype from@/utils/llms/types
LLM feature functions must follow a standard structure: accept options withinputDataandemailAccountparameters, implement input validation with early returns, define separate system and user prompts, create a Zod schema for response validation, and usecreateGenerateObjectto execute the LLM call
System prompts must define the LLM's role and task specifications
User prompts must contain the actual data and context, and should be kept separate from system prompts
Always define a Zod schema for LLM response validation and make schemas as specific as possible to guide the LLM output
Use descriptive scoped loggers for each LLM feature, log inputs and outputs with appropriate log levels, and include relevant context in log messages
Implement early returns for invalid LLM inputs, use proper error types and logging, implement fallbacks for AI failures, and add retry logic for transient failures usingwithRetry
Use XML-like tags to structure data in prompts, remove excessive whitespace and truncate long inputs, and format data consistently across similar LLM functions
Use TypeScript types for all LLM function parameters and return values, and define clear interfaces for complex input/output structures
Keep related AI functions in the same file or directory, extract common patterns into utility functions, and document complex AI logic with clear comments
Files:
apps/web/utils/ai/assistant/process-user-request.ts
**/{server,api,actions,utils}/**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/logging.mdc)
**/{server,api,actions,utils}/**/*.ts: UsecreateScopedLoggerfrom "@/utils/logger" for logging in backend code
Add thecreateScopedLoggerinstantiation at the top of the file with an appropriate scope name
Use.with()method to attach context variables only within specific functions, not on global loggers
For large functions with reused variables, usecreateScopedLogger().with()to attach context once and reuse the logger without passing variables repeatedly
Files:
apps/web/utils/ai/assistant/process-user-request.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/prisma-enum-imports.mdc)
Always import Prisma enums from
@/generated/prisma/enumsinstead of@/generated/prisma/clientto avoid Next.js bundling errors in client componentsImport Prisma using the project's centralized utility:
import prisma from '@/utils/prisma'
Files:
apps/web/utils/ai/assistant/process-user-request.tsapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/security.mdc)
**/*.ts: ALL database queries MUST be scoped to the authenticated user/account by including user/account filtering in WHERE clauses to prevent unauthorized data access
Always validate that resources belong to the authenticated user before performing operations, using ownership checks in WHERE clauses or relationships
Always validate all input parameters for type, format, and length before using them in database queries
Use SafeError for error responses to prevent information disclosure. Generic error messages should not reveal internal IDs, logic, or resource ownership details
Only return necessary fields in API responses using Prisma'sselectoption. Never expose sensitive data such as password hashes, private keys, or system flags
Prevent Insecure Direct Object References (IDOR) by validating resource ownership before operations. AllfindUnique/findFirstcalls MUST include ownership filters
Prevent mass assignment vulnerabilities by explicitly whitelisting allowed fields in update operations instead of accepting all user-provided data
Prevent privilege escalation by never allowing users to modify system fields, ownership fields, or admin-only attributes through user input
AllfindManyqueries MUST be scoped to the user's data by including appropriate WHERE filters to prevent returning data from other users
Use Prisma relationships for access control by leveraging nested where clauses (e.g.,emailAccount: { id: emailAccountId }) to validate ownership
Files:
apps/web/utils/ai/assistant/process-user-request.ts
**/*.{tsx,ts}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
**/*.{tsx,ts}: Use Shadcn UI and Tailwind for components and styling
Usenext/imagepackage for images
For API GET requests to server, use theswrpackage with hooks likeuseSWRto fetch data
For text inputs, use theInputcomponent withregisterPropsfor form integration and error handling
Files:
apps/web/utils/ai/assistant/process-user-request.tsapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*.{tsx,ts,css}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
Implement responsive design with Tailwind CSS using a mobile-first approach
Files:
apps/web/utils/ai/assistant/process-user-request.tsapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{js,jsx,ts,tsx}: Don't useaccessKeyattribute on any HTML element
Don't setaria-hidden="true"on focusable elements
Don't add ARIA roles, states, and properties to elements that don't support them
Don't use distracting elements like<marquee>or<blink>
Only use thescopeprop on<th>elements
Don't assign non-interactive ARIA roles to interactive HTML elements
Make sure label elements have text content and are associated with an input
Don't assign interactive ARIA roles to non-interactive HTML elements
Don't assigntabIndexto non-interactive HTML elements
Don't use positive integers fortabIndexproperty
Don't include "image", "picture", or "photo" in img alt prop
Don't use explicit role property that's the same as the implicit/default role
Make static elements with click handlers use a valid role attribute
Always include atitleelement for SVG elements
Give all elements requiring alt text meaningful information for screen readers
Make sure anchors have content that's accessible to screen readers
AssigntabIndexto non-interactive HTML elements witharia-activedescendant
Include all required ARIA attributes for elements with ARIA roles
Make sure ARIA properties are valid for the element's supported roles
Always include atypeattribute for button elements
Make elements with interactive roles and handlers focusable
Give heading elements content that's accessible to screen readers (not hidden witharia-hidden)
Always include alangattribute on the html element
Always include atitleattribute for iframe elements
AccompanyonClickwith at least one of:onKeyUp,onKeyDown, oronKeyPress
AccompanyonMouseOver/onMouseOutwithonFocus/onBlur
Include caption tracks for audio and video elements
Use semantic elements instead of role attributes in JSX
Make sure all anchors are valid and navigable
Ensure all ARIA properties (aria-*) are valid
Use valid, non-abstract ARIA roles for elements with ARIA roles
Use valid AR...
Files:
apps/web/utils/ai/assistant/process-user-request.tsapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
!(pages/_document).{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
Don't use the next/head module in pages/_document.js on Next.js projects
Files:
apps/web/utils/ai/assistant/process-user-request.tsapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
**/*.{js,ts,jsx,tsx}: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size (e.g.,import groupBy from 'lodash/groupBy')
Files:
apps/web/utils/ai/assistant/process-user-request.tsapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
apps/web/app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
Follow NextJS app router structure with (app) directory
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
apps/web/**/*.tsx
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/**/*.tsx: Follow tailwindcss patterns with prettier-plugin-tailwindcss for class sorting
Prefer functional components with hooks over class components
Use shadcn/ui components when available
Ensure responsive design with mobile-first approach
Use LoadingContent component for async data with loading and error states
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*Form.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/form-handling.mdc)
**/*Form.{ts,tsx}: Use React Hook Form with Zod for validation in form components
Validate form inputs before submission
Show validation errors inline next to form fields
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
apps/web/app/(app)/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/page-structure.mdc)
apps/web/app/(app)/**/*.{ts,tsx}: Components for the page are either put inpage.tsx, or in theapps/web/app/(app)/PAGE_NAMEfolder
If we're in a deeply nested component we will useswrto fetch via API
If you need to useonClickin a component, that component is a client component and file must start withuse client
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
**/*.tsx: Use theLoadingContentcomponent to handle loading states instead of manual loading state management
For text areas, use theInputcomponent withtype='text',autosizeTextareaprop set to true, andregisterPropsfor form integration
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{jsx,tsx}: Don't use unnecessary fragments
Don't pass children as props
Don't use the return value of React.render
Make sure all dependencies are correctly specified in React hooks
Make sure all React hooks are called from the top level of component functions
Don't forget key props in iterators and collection literals
Don't define React components inside other components
Don't use event handlers on non-interactive elements
Don't assign to React component props
Don't use bothchildrenanddangerouslySetInnerHTMLprops on the same element
Don't use dangerous JSX props
Don't use Array index in keys
Don't insert comments as text nodes
Don't assign JSX properties multiple times
Don't add extra closing tags for components without children
Use<>...</>instead of<Fragment>...</Fragment>
Watch out for possible "wrong" semicolons inside JSX elements
Make sure void (self-closing) elements don't have children
Don't usetarget="_blank"withoutrel="noopener"
Don't use<img>elements in Next.js projects
Don't use<head>elements in Next.js projects
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
🧠 Learnings (37)
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : System prompts must define the LLM's role and task specifications
Applied to files:
apps/web/utils/ai/assistant/process-user-request.ts
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : User prompts must contain the actual data and context, and should be kept separate from system prompts
Applied to files:
apps/web/utils/ai/assistant/process-user-request.ts
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : Use XML-like tags to structure data in prompts, remove excessive whitespace and truncate long inputs, and format data consistently across similar LLM functions
Applied to files:
apps/web/utils/ai/assistant/process-user-request.tsapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : Keep related AI functions in the same file or directory, extract common patterns into utility functions, and document complex AI logic with clear comments
Applied to files:
apps/web/utils/ai/assistant/process-user-request.ts
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : LLM feature functions must follow a standard structure: accept options with `inputData` and `emailAccount` parameters, implement input validation with early returns, define separate system and user prompts, create a Zod schema for response validation, and use `createGenerateObject` to execute the LLM call
Applied to files:
apps/web/utils/ai/assistant/process-user-request.tsapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/components/**/*Form*.tsx : Handle form submission results using `result?.serverError` to show error toasts and `toastSuccess` to show success messages after server action completion
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/**/*.{ts,tsx} : Use proper error handling with try/catch blocks
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:39:23.326Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-11-25T14:39:23.326Z
Learning: Applies to app/api/**/*.ts : Use `SafeError` for error responses to prevent information disclosure - provide generic messages (e.g., 'Rule not found' not 'Rule {id} does not exist for user {userId}') without revealing internal IDs or ownership details
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't use unnecessary catch clauses
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't reassign exceptions in catch clauses
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:40.146Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/data-fetching.mdc:0-0
Timestamp: 2025-11-25T14:36:40.146Z
Learning: Applies to **/*.{ts,tsx} : Use `result?.serverError` with `toastError` from `@/components/Toast` for error handling in async operations
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:36.276Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/data-fetching.mdc:0-0
Timestamp: 2025-11-25T14:36:36.276Z
Learning: Applies to **/*.{ts,tsx} : Use `result?.serverError` with `toastError` and `toastSuccess` for error handling in server actions
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/components/**/*.tsx : Use `result?.serverError` with `toastError` and `toastSuccess` for error handling in form submissions
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use semantic elements instead of role attributes in JSX
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Always include a `type` attribute for button elements
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use valid, non-abstract ARIA roles for elements with ARIA roles
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Make static elements with click handlers use a valid role attribute
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{jsx,tsx} : Make sure all dependencies are correctly specified in React hooks
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Make sure label elements have text content and are associated with an input
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:40:13.649Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:13.649Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : For text areas in forms, use the `Input` component with `type='text'`, `autosizeTextarea` prop, `rows`, `name`, `placeholder`, `registerProps` from react-hook-form, and `error` props
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Make sure ARIA properties are valid for the element's supported roles
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:40:13.649Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:13.649Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : For text inputs in forms, use the `Input` component with `type='email'`, `name`, `label`, `registerProps` from react-hook-form, and `error` props
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{jsx,tsx} : Watch out for possible "wrong" semicolons inside JSX elements
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:51.389Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:51.389Z
Learning: Applies to **/*Form.{ts,tsx} : Validate form inputs before submission using React Hook Form and Zod resolver
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/components/**/*Form*.tsx : Use React Hook Form with Zod validation (`zodResolver`) for form handling, with form components using `register`, `handleSubmit`, and error handling from the hook
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:51.389Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:51.389Z
Learning: Applies to **/*Form.{ts,tsx} : Use React Hook Form with Zod for form validation
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/components/**/*.tsx : Use React Hook Form with Zod validation for form components
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:53.147Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:53.147Z
Learning: Applies to **/*Form.{ts,tsx} : Use React Hook Form with Zod for validation in form components
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:51.389Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:51.389Z
Learning: Applies to **/*Form.{ts,tsx} : Show validation errors inline next to form fields in the UI
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:53.147Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:53.147Z
Learning: Applies to **/*Form.{ts,tsx} : Validate form inputs before submission
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:53.147Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:53.147Z
Learning: Applies to **/*Form.{ts,tsx} : Show validation errors inline next to form fields
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:38:56.992Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-11-25T14:38:56.992Z
Learning: Applies to apps/web/components/ui/**/*.tsx : Shadcn UI components are located in `components/ui` directory
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/**/*.tsx : Use shadcn/ui components when available
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:11.919Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-25T14:42:11.919Z
Learning: Applies to utils/**/*.{js,ts,jsx,tsx} : The `utils` folder contains core app logic such as Next.js Server Actions and Gmail API requests
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:40:00.833Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-25T14:40:00.833Z
Learning: Applies to **/*.test.{ts,tsx} : Use test helpers `getEmail`, `getEmailAccount`, and `getRule` from `@/__tests__/helpers` for mocking emails, accounts, and rules
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-09T19:50:05.292Z
Learnt from: ppranay20
Repo: elie222/inbox-zero PR: 935
File: apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx:367-369
Timestamp: 2025-11-09T19:50:05.292Z
Learning: In React Hook Form, when using `useMemo` or `useEffect` with form errors, always use `formState` as the dependency rather than `errors` or `formState.errors`. This is because React Hook Form uses a Proxy pattern where the errors object is mutable and won't trigger dependency arrays correctly. The formState dependency ensures proper reactivity when form validation state changes.
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:40:15.063Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:15.063Z
Learning: Applies to **/*.{tsx,ts} : For text inputs, use the `Input` component with `registerProps` for form integration and error handling
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
🧬 Code graph analysis (1)
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx (5)
apps/web/utils/action-display.tsx (1)
getActionIcon(86-115)apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsx (1)
RuleSectionCard(5-37)apps/web/utils/reply-tracker/conversation-status-config.ts (1)
isConversationStatusType(16-22)apps/web/utils/rule/consts.ts (1)
getRuleConfig(112-116)apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx (1)
ActionSteps(46-107)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: test
🔇 Additional comments (1)
apps/web/utils/ai/assistant/process-user-request.ts (1)
90-90: LGTM! URL updated to reflect the new rules UI location.The URL path change from
/assistant?tab=rulesto/automation?tab=rulesaligns with the rules UI refactoring described in the PR objectives.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx (1)
319-361: Remove redundant mutate() calls in delete handler.The delete handler calls
mutate()three times:
- Via the
onSettledcallback of theuseActionhook (line 89)- On line 343 after successful deletion
- In the
finallyblock on line 351Since
onSettledalready handles revalidation for all outcomes, themutate()calls on lines 343 and 351 are redundant. While SWR deduplicates requests, removing these unnecessary calls improves clarity.Apply this diff:
toast.promise( async () => { const res = await deleteRule({ id: rule.id, }); if ( res?.serverError || res?.validationErrors ) { throw new Error( res?.serverError || "There was an error deleting your rule", ); } - - mutate(); }, { loading: "Deleting rule...", success: "Rule deleted", error: (error) => `Error deleting rule. ${error.message}`, - finally: () => { - mutate(); - }, }, );
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx(6 hunks)apps/web/app/(app)/[emailAccountId]/assistant/RulesTabNew.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/web/app/(app)/[emailAccountId]/assistant/RulesTabNew.tsx
🧰 Additional context used
📓 Path-based instructions (13)
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Use@/path aliases for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Follow consistent naming conventions using PascalCase for components
Centralize shared types in dedicated type filesImport specific lodash functions rather than entire lodash library to minimize bundle size (e.g.,
import groupBy from 'lodash/groupBy')
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
apps/web/app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
Follow NextJS app router structure with (app) directory
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
apps/web/**/*.tsx
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/**/*.tsx: Follow tailwindcss patterns with prettier-plugin-tailwindcss for class sorting
Prefer functional components with hooks over class components
Use shadcn/ui components when available
Ensure responsive design with mobile-first approach
Use LoadingContent component for async data with loading and error states
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/data-fetching.mdc)
**/*.{ts,tsx}: For API GET requests to server, use theswrpackage
Useresult?.serverErrorwithtoastErrorfrom@/components/Toastfor error handling in async operations
**/*.{ts,tsx}: Use wrapper functions for Gmail message operations (get, list, batch, etc.) from @/utils/gmail/message.ts instead of direct API calls
Use wrapper functions for Gmail thread operations from @/utils/gmail/thread.ts instead of direct API calls
Use wrapper functions for Gmail label operations from @/utils/gmail/label.ts instead of direct API calls
**/*.{ts,tsx}: For early access feature flags, create hooks using the naming conventionuse[FeatureName]Enabledthat return a boolean fromuseFeatureFlagEnabled("flag-key")
For A/B test variant flags, create hooks using the naming conventionuse[FeatureName]Variantthat define variant types, useuseFeatureFlagVariantKey()with type casting, and provide a default "control" fallback
Use kebab-case for PostHog feature flag keys (e.g.,inbox-cleaner,pricing-options-2)
Always define types for A/B test variant flags (e.g.,type PricingVariant = "control" | "variant-a" | "variant-b") and provide type safety through type casting
**/*.{ts,tsx}: Don't use primitive type aliases or misleading types
Don't use empty type parameters in type aliases and interfaces
Don't use this and super in static contexts
Don't use any or unknown as type constraints
Don't use the TypeScript directive @ts-ignore
Don't use TypeScript enums
Don't export imported variables
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions
Don't use TypeScript namespaces
Don't use non-null assertions with the!postfix operator
Don't use parameter properties in class constructors
Don't use user-defined types
Useas constinstead of literal types and type annotations
Use eitherT[]orArray<T>consistently
Initialize each enum member value explicitly
Useexport typefor types
Use `impo...
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
apps/web/app/(app)/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/page-structure.mdc)
apps/web/app/(app)/**/*.{ts,tsx}: Components for the page are either put inpage.tsx, or in theapps/web/app/(app)/PAGE_NAMEfolder
If we're in a deeply nested component we will useswrto fetch via API
If you need to useonClickin a component, that component is a client component and file must start withuse client
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/prisma-enum-imports.mdc)
Always import Prisma enums from
@/generated/prisma/enumsinstead of@/generated/prisma/clientto avoid Next.js bundling errors in client componentsImport Prisma using the project's centralized utility:
import prisma from '@/utils/prisma'
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
**/*.{tsx,ts}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
**/*.{tsx,ts}: Use Shadcn UI and Tailwind for components and styling
Usenext/imagepackage for images
For API GET requests to server, use theswrpackage with hooks likeuseSWRto fetch data
For text inputs, use theInputcomponent withregisterPropsfor form integration and error handling
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
**/*.{tsx,ts,css}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
Implement responsive design with Tailwind CSS using a mobile-first approach
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
**/*.tsx: Use theLoadingContentcomponent to handle loading states instead of manual loading state management
For text areas, use theInputcomponent withtype='text',autosizeTextareaprop set to true, andregisterPropsfor form integration
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{js,jsx,ts,tsx}: Don't useaccessKeyattribute on any HTML element
Don't setaria-hidden="true"on focusable elements
Don't add ARIA roles, states, and properties to elements that don't support them
Don't use distracting elements like<marquee>or<blink>
Only use thescopeprop on<th>elements
Don't assign non-interactive ARIA roles to interactive HTML elements
Make sure label elements have text content and are associated with an input
Don't assign interactive ARIA roles to non-interactive HTML elements
Don't assigntabIndexto non-interactive HTML elements
Don't use positive integers fortabIndexproperty
Don't include "image", "picture", or "photo" in img alt prop
Don't use explicit role property that's the same as the implicit/default role
Make static elements with click handlers use a valid role attribute
Always include atitleelement for SVG elements
Give all elements requiring alt text meaningful information for screen readers
Make sure anchors have content that's accessible to screen readers
AssigntabIndexto non-interactive HTML elements witharia-activedescendant
Include all required ARIA attributes for elements with ARIA roles
Make sure ARIA properties are valid for the element's supported roles
Always include atypeattribute for button elements
Make elements with interactive roles and handlers focusable
Give heading elements content that's accessible to screen readers (not hidden witharia-hidden)
Always include alangattribute on the html element
Always include atitleattribute for iframe elements
AccompanyonClickwith at least one of:onKeyUp,onKeyDown, oronKeyPress
AccompanyonMouseOver/onMouseOutwithonFocus/onBlur
Include caption tracks for audio and video elements
Use semantic elements instead of role attributes in JSX
Make sure all anchors are valid and navigable
Ensure all ARIA properties (aria-*) are valid
Use valid, non-abstract ARIA roles for elements with ARIA roles
Use valid AR...
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{jsx,tsx}: Don't use unnecessary fragments
Don't pass children as props
Don't use the return value of React.render
Make sure all dependencies are correctly specified in React hooks
Make sure all React hooks are called from the top level of component functions
Don't forget key props in iterators and collection literals
Don't define React components inside other components
Don't use event handlers on non-interactive elements
Don't assign to React component props
Don't use bothchildrenanddangerouslySetInnerHTMLprops on the same element
Don't use dangerous JSX props
Don't use Array index in keys
Don't insert comments as text nodes
Don't assign JSX properties multiple times
Don't add extra closing tags for components without children
Use<>...</>instead of<Fragment>...</Fragment>
Watch out for possible "wrong" semicolons inside JSX elements
Make sure void (self-closing) elements don't have children
Don't usetarget="_blank"withoutrel="noopener"
Don't use<img>elements in Next.js projects
Don't use<head>elements in Next.js projects
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
!(pages/_document).{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
Don't use the next/head module in pages/_document.js on Next.js projects
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
**/*.{js,ts,jsx,tsx}: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size (e.g.,import groupBy from 'lodash/groupBy')
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
🧠 Learnings (19)
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : Use XML-like tags to structure data in prompts, remove excessive whitespace and truncate long inputs, and format data consistently across similar LLM functions
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:36:33.376Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/cursor-rules.mdc:0-0
Timestamp: 2025-11-25T14:36:33.376Z
Learning: Applies to .cursor/rules/**/*.mdc : Make cursor rule filenames descriptive of the rule's purpose
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : Keep related AI functions in the same file or directory, extract common patterns into utility functions, and document complex AI logic with clear comments
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:40:13.649Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:13.649Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : Use the `LoadingContent` component to handle loading states
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/**/*.tsx : Use LoadingContent component for async data with loading and error states
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/components/**/*.tsx : Use `LoadingContent` component to consistently handle loading and error states, passing `loading`, `error`, and `children` props
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:36:36.276Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/data-fetching.mdc:0-0
Timestamp: 2025-11-25T14:36:36.276Z
Learning: Applies to **/*.{ts,tsx} : Import error and success toast utilities from '@/components/Toast' for displaying notifications
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:38:56.992Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-11-25T14:38:56.992Z
Learning: Applies to apps/web/components/ui/**/*.tsx : Shadcn UI components are located in `components/ui` directory
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/**/*.tsx : Use shadcn/ui components when available
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:37:30.660Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/hooks.mdc:0-0
Timestamp: 2025-11-25T14:37:30.660Z
Learning: Applies to apps/web/hooks/use*.ts : Create dedicated hooks for specific data types (e.g., `useAccounts`, `useLabels`) that wrap `useSWR`, handle the API endpoint URL, and return data, loading state, error state, and the `mutate` function
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:39:49.448Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-11-25T14:39:49.448Z
Learning: Applies to apps/web/utils/actions/*.ts : Use `actionClient` when both authenticated user context and a specific emailAccountId are needed, with emailAccountId bound when calling from the client
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:39:49.448Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-11-25T14:39:49.448Z
Learning: Applies to apps/web/utils/actions/*.ts : Implement all server actions using the `next-safe-action` library with actionClient, actionClientUser, or adminActionClient for type safety and validation
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:42:11.919Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-25T14:42:11.919Z
Learning: Applies to utils/**/*.{js,ts,jsx,tsx} : The `utils` folder contains core app logic such as Next.js Server Actions and Gmail API requests
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:37:35.343Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/hooks.mdc:0-0
Timestamp: 2025-11-25T14:37:35.343Z
Learning: Applies to apps/web/hooks/use*.ts : Create dedicated hooks for specific data types (e.g., `useAccounts`, `useLabels`) to wrap `useSWR` for individual API endpoints
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/utils/actions/**/*.ts : Use `next-safe-action` with `actionClient` for server actions with Zod schema validation
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:42:16.602Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-25T14:42:16.602Z
Learning: The `utils` folder contains core app logic such as Next.js Server Actions and Gmail API requests
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:37:35.343Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/hooks.mdc:0-0
Timestamp: 2025-11-25T14:37:35.343Z
Learning: Applies to apps/web/hooks/use*.ts : Use the `use` prefix for custom hook filenames (e.g., `useAccounts.ts`)
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:36:40.146Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/data-fetching.mdc:0-0
Timestamp: 2025-11-25T14:36:40.146Z
Learning: Applies to **/*{.action,.server}.{ts,tsx} : For mutating data, use Next.js server actions
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/utils/actions/*.ts : Use `next-safe-action` with Zod schemas for all server actions (create/update/delete mutations), storing validation schemas in `apps/web/utils/actions/*.validation.ts`
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
🧬 Code graph analysis (1)
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx (4)
apps/web/utils/rule/rule.ts (1)
deleteRule(244-260)apps/web/app/api/user/rules/route.ts (1)
RulesResponse(5-5)apps/web/components/Tooltip.tsx (1)
Tooltip(18-41)apps/web/utils/condition.ts (1)
conditionsToString(200-217)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: test
🔇 Additional comments (4)
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx (4)
13-13: LGTM! Import and header changes align with refactoring objectives.The new imports (FilterIcon, Tooltip, conditionsToString) are properly used in the StaticConditionsIcon component, and the table header restructure correctly replaces the Conditions column with an Action column as described in the PR objectives.
Also applies to: 53-54, 147-150
411-411: LGTM! ActionBadges alignment change.The
justify-startalignment correctly positions the action badges to the left as specified in the PR objectives.
240-318: LGTM! Action menu restructure is well-implemented.The new dropdown menu structure provides clear actions:
- Edit manually opens the rule dialog in edit mode
- Edit via AI pre-fills the chat with rule context (properly gated for system rules)
- Duplicate opens the dialog with a rule copy
- History navigates correctly based on rule type
The conditional rendering logic and event handling are appropriate.
454-466: LGTM! Helper functions are well-structured.The
hasStaticConditionshelper correctly identifies rules with static conditions, andStaticConditionsIconprovides a clean UI indicator with tooltip showing the condition details viaconditionsToString.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx (1)
523-573: Empty catch block loses error context.The catch block at line 563 doesn't capture the error parameter, making debugging difficult if the delete operation fails for unexpected reasons. This was noted in a previous review.
Apply this diff:
- } catch { + } catch (error) { + console.error("Failed to delete rule:", error); toastError({ description: "Failed to delete rule." }); } finally {
🧹 Nitpick comments (1)
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx (1)
281-286: Consider importingElementTypeseparately.While
React.ElementTypeworks, TypeScript best practice is to importElementTypeas a type directly from React. This was noted in a previous review comment.Apply this diff:
-import { useCallback, useEffect, useMemo, useState } from "react"; +import { useCallback, useEffect, useMemo, useState, type ElementType } from "react";Then update line 285:
- icon: React.ElementType; + icon: ElementType;
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx(8 hunks)apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx(6 hunks)
🧰 Additional context used
📓 Path-based instructions (14)
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Use@/path aliases for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Follow consistent naming conventions using PascalCase for components
Centralize shared types in dedicated type filesImport specific lodash functions rather than entire lodash library to minimize bundle size (e.g.,
import groupBy from 'lodash/groupBy')
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
apps/web/app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
Follow NextJS app router structure with (app) directory
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
apps/web/**/*.tsx
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/**/*.tsx: Follow tailwindcss patterns with prettier-plugin-tailwindcss for class sorting
Prefer functional components with hooks over class components
Use shadcn/ui components when available
Ensure responsive design with mobile-first approach
Use LoadingContent component for async data with loading and error states
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/data-fetching.mdc)
**/*.{ts,tsx}: For API GET requests to server, use theswrpackage
Useresult?.serverErrorwithtoastErrorfrom@/components/Toastfor error handling in async operations
**/*.{ts,tsx}: Use wrapper functions for Gmail message operations (get, list, batch, etc.) from @/utils/gmail/message.ts instead of direct API calls
Use wrapper functions for Gmail thread operations from @/utils/gmail/thread.ts instead of direct API calls
Use wrapper functions for Gmail label operations from @/utils/gmail/label.ts instead of direct API calls
**/*.{ts,tsx}: For early access feature flags, create hooks using the naming conventionuse[FeatureName]Enabledthat return a boolean fromuseFeatureFlagEnabled("flag-key")
For A/B test variant flags, create hooks using the naming conventionuse[FeatureName]Variantthat define variant types, useuseFeatureFlagVariantKey()with type casting, and provide a default "control" fallback
Use kebab-case for PostHog feature flag keys (e.g.,inbox-cleaner,pricing-options-2)
Always define types for A/B test variant flags (e.g.,type PricingVariant = "control" | "variant-a" | "variant-b") and provide type safety through type casting
**/*.{ts,tsx}: Don't use primitive type aliases or misleading types
Don't use empty type parameters in type aliases and interfaces
Don't use this and super in static contexts
Don't use any or unknown as type constraints
Don't use the TypeScript directive @ts-ignore
Don't use TypeScript enums
Don't export imported variables
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions
Don't use TypeScript namespaces
Don't use non-null assertions with the!postfix operator
Don't use parameter properties in class constructors
Don't use user-defined types
Useas constinstead of literal types and type annotations
Use eitherT[]orArray<T>consistently
Initialize each enum member value explicitly
Useexport typefor types
Use `impo...
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
apps/web/app/(app)/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/page-structure.mdc)
apps/web/app/(app)/**/*.{ts,tsx}: Components for the page are either put inpage.tsx, or in theapps/web/app/(app)/PAGE_NAMEfolder
If we're in a deeply nested component we will useswrto fetch via API
If you need to useonClickin a component, that component is a client component and file must start withuse client
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/prisma-enum-imports.mdc)
Always import Prisma enums from
@/generated/prisma/enumsinstead of@/generated/prisma/clientto avoid Next.js bundling errors in client componentsImport Prisma using the project's centralized utility:
import prisma from '@/utils/prisma'
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*.{tsx,ts}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
**/*.{tsx,ts}: Use Shadcn UI and Tailwind for components and styling
Usenext/imagepackage for images
For API GET requests to server, use theswrpackage with hooks likeuseSWRto fetch data
For text inputs, use theInputcomponent withregisterPropsfor form integration and error handling
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*.{tsx,ts,css}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
Implement responsive design with Tailwind CSS using a mobile-first approach
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
**/*.tsx: Use theLoadingContentcomponent to handle loading states instead of manual loading state management
For text areas, use theInputcomponent withtype='text',autosizeTextareaprop set to true, andregisterPropsfor form integration
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{js,jsx,ts,tsx}: Don't useaccessKeyattribute on any HTML element
Don't setaria-hidden="true"on focusable elements
Don't add ARIA roles, states, and properties to elements that don't support them
Don't use distracting elements like<marquee>or<blink>
Only use thescopeprop on<th>elements
Don't assign non-interactive ARIA roles to interactive HTML elements
Make sure label elements have text content and are associated with an input
Don't assign interactive ARIA roles to non-interactive HTML elements
Don't assigntabIndexto non-interactive HTML elements
Don't use positive integers fortabIndexproperty
Don't include "image", "picture", or "photo" in img alt prop
Don't use explicit role property that's the same as the implicit/default role
Make static elements with click handlers use a valid role attribute
Always include atitleelement for SVG elements
Give all elements requiring alt text meaningful information for screen readers
Make sure anchors have content that's accessible to screen readers
AssigntabIndexto non-interactive HTML elements witharia-activedescendant
Include all required ARIA attributes for elements with ARIA roles
Make sure ARIA properties are valid for the element's supported roles
Always include atypeattribute for button elements
Make elements with interactive roles and handlers focusable
Give heading elements content that's accessible to screen readers (not hidden witharia-hidden)
Always include alangattribute on the html element
Always include atitleattribute for iframe elements
AccompanyonClickwith at least one of:onKeyUp,onKeyDown, oronKeyPress
AccompanyonMouseOver/onMouseOutwithonFocus/onBlur
Include caption tracks for audio and video elements
Use semantic elements instead of role attributes in JSX
Make sure all anchors are valid and navigable
Ensure all ARIA properties (aria-*) are valid
Use valid, non-abstract ARIA roles for elements with ARIA roles
Use valid AR...
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{jsx,tsx}: Don't use unnecessary fragments
Don't pass children as props
Don't use the return value of React.render
Make sure all dependencies are correctly specified in React hooks
Make sure all React hooks are called from the top level of component functions
Don't forget key props in iterators and collection literals
Don't define React components inside other components
Don't use event handlers on non-interactive elements
Don't assign to React component props
Don't use bothchildrenanddangerouslySetInnerHTMLprops on the same element
Don't use dangerous JSX props
Don't use Array index in keys
Don't insert comments as text nodes
Don't assign JSX properties multiple times
Don't add extra closing tags for components without children
Use<>...</>instead of<Fragment>...</Fragment>
Watch out for possible "wrong" semicolons inside JSX elements
Make sure void (self-closing) elements don't have children
Don't usetarget="_blank"withoutrel="noopener"
Don't use<img>elements in Next.js projects
Don't use<head>elements in Next.js projects
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
!(pages/_document).{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
Don't use the next/head module in pages/_document.js on Next.js projects
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
**/*.{js,ts,jsx,tsx}: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size (e.g.,import groupBy from 'lodash/groupBy')
Files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
**/*Form.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/form-handling.mdc)
**/*Form.{ts,tsx}: Use React Hook Form with Zod for validation in form components
Validate form inputs before submission
Show validation errors inline next to form fields
Files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
🧠 Learnings (45)
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : Use XML-like tags to structure data in prompts, remove excessive whitespace and truncate long inputs, and format data consistently across similar LLM functions
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : Keep related AI functions in the same file or directory, extract common patterns into utility functions, and document complex AI logic with clear comments
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:36:36.276Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/data-fetching.mdc:0-0
Timestamp: 2025-11-25T14:36:36.276Z
Learning: Applies to **/*.{ts,tsx} : Import error and success toast utilities from '@/components/Toast' for displaying notifications
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:38:56.992Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-11-25T14:38:56.992Z
Learning: Applies to apps/web/components/ui/**/*.tsx : Shadcn UI components are located in `components/ui` directory
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/**/*.tsx : Use shadcn/ui components when available
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:37:30.660Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/hooks.mdc:0-0
Timestamp: 2025-11-25T14:37:30.660Z
Learning: Applies to apps/web/hooks/use*.ts : Create dedicated hooks for specific data types (e.g., `useAccounts`, `useLabels`) that wrap `useSWR`, handle the API endpoint URL, and return data, loading state, error state, and the `mutate` function
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:39:49.448Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-11-25T14:39:49.448Z
Learning: Applies to apps/web/utils/actions/*.ts : Use `actionClient` when both authenticated user context and a specific emailAccountId are needed, with emailAccountId bound when calling from the client
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:39:49.448Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-11-25T14:39:49.448Z
Learning: Applies to apps/web/utils/actions/*.ts : Implement all server actions using the `next-safe-action` library with actionClient, actionClientUser, or adminActionClient for type safety and validation
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:42:11.919Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-25T14:42:11.919Z
Learning: Applies to utils/**/*.{js,ts,jsx,tsx} : The `utils` folder contains core app logic such as Next.js Server Actions and Gmail API requests
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsxapps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:37:35.343Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/hooks.mdc:0-0
Timestamp: 2025-11-25T14:37:35.343Z
Learning: Applies to apps/web/hooks/use*.ts : Create dedicated hooks for specific data types (e.g., `useAccounts`, `useLabels`) to wrap `useSWR` for individual API endpoints
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/utils/actions/**/*.ts : Use `next-safe-action` with `actionClient` for server actions with Zod schema validation
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:42:16.602Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-11-25T14:42:16.602Z
Learning: The `utils` folder contains core app logic such as Next.js Server Actions and Gmail API requests
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:37:35.343Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/hooks.mdc:0-0
Timestamp: 2025-11-25T14:37:35.343Z
Learning: Applies to apps/web/hooks/use*.ts : Use the `use` prefix for custom hook filenames (e.g., `useAccounts.ts`)
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/utils/actions/*.ts : Use `next-safe-action` with Zod schemas for all server actions (create/update/delete mutations), storing validation schemas in `apps/web/utils/actions/*.validation.ts`
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:36:40.146Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/data-fetching.mdc:0-0
Timestamp: 2025-11-25T14:36:40.146Z
Learning: Applies to **/*{.action,.server}.{ts,tsx} : For mutating data, use Next.js server actions
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
📚 Learning: 2025-11-25T14:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/components/**/*Form*.tsx : Handle form submission results using `result?.serverError` to show error toasts and `toastSuccess` to show success messages after server action completion
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : LLM feature functions must follow a standard structure: accept options with `inputData` and `emailAccount` parameters, implement input validation with early returns, define separate system and user prompts, create a Zod schema for response validation, and use `createGenerateObject` to execute the LLM call
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/**/*.{ts,tsx} : Use proper error handling with try/catch blocks
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:39:23.326Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-11-25T14:39:23.326Z
Learning: Applies to app/api/**/*.ts : Use `SafeError` for error responses to prevent information disclosure - provide generic messages (e.g., 'Rule not found' not 'Rule {id} does not exist for user {userId}') without revealing internal IDs or ownership details
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't use unnecessary catch clauses
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't reassign exceptions in catch clauses
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:40.146Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/data-fetching.mdc:0-0
Timestamp: 2025-11-25T14:36:40.146Z
Learning: Applies to **/*.{ts,tsx} : Use `result?.serverError` with `toastError` from `@/components/Toast` for error handling in async operations
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:36.276Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/data-fetching.mdc:0-0
Timestamp: 2025-11-25T14:36:36.276Z
Learning: Applies to **/*.{ts,tsx} : Use `result?.serverError` with `toastError` and `toastSuccess` for error handling in server actions
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/components/**/*.tsx : Use `result?.serverError` with `toastError` and `toastSuccess` for error handling in form submissions
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use semantic elements instead of role attributes in JSX
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Always include a `type` attribute for button elements
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use valid, non-abstract ARIA roles for elements with ARIA roles
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Make static elements with click handlers use a valid role attribute
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{jsx,tsx} : Make sure all dependencies are correctly specified in React hooks
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Make sure label elements have text content and are associated with an input
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:40:13.649Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:13.649Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : For text areas in forms, use the `Input` component with `type='text'`, `autosizeTextarea` prop, `rows`, `name`, `placeholder`, `registerProps` from react-hook-form, and `error` props
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Make sure ARIA properties are valid for the element's supported roles
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:40:13.649Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:13.649Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : For text inputs in forms, use the `Input` component with `type='email'`, `name`, `label`, `registerProps` from react-hook-form, and `error` props
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{jsx,tsx} : Watch out for possible "wrong" semicolons inside JSX elements
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-09T19:50:05.292Z
Learnt from: ppranay20
Repo: elie222/inbox-zero PR: 935
File: apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx:367-369
Timestamp: 2025-11-09T19:50:05.292Z
Learning: In React Hook Form, when using `useMemo` or `useEffect` with form errors, always use `formState` as the dependency rather than `errors` or `formState.errors`. This is because React Hook Form uses a Proxy pattern where the errors object is mutable and won't trigger dependency arrays correctly. The formState dependency ensures proper reactivity when form validation state changes.
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/components/**/*Form*.tsx : Use React Hook Form with Zod validation (`zodResolver`) for form handling, with form components using `register`, `handleSubmit`, and error handling from the hook
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:51.389Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:51.389Z
Learning: Applies to **/*Form.{ts,tsx} : Validate form inputs before submission using React Hook Form and Zod resolver
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:51.389Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:51.389Z
Learning: Applies to **/*Form.{ts,tsx} : Use React Hook Form with Zod for form validation
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/components/**/*.tsx : Use React Hook Form with Zod validation for form components
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:53.147Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:53.147Z
Learning: Applies to **/*Form.{ts,tsx} : Use React Hook Form with Zod for validation in form components
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:51.389Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:51.389Z
Learning: Applies to **/*Form.{ts,tsx} : Show validation errors inline next to form fields in the UI
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:53.147Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:53.147Z
Learning: Applies to **/*Form.{ts,tsx} : Validate form inputs before submission
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:36:53.147Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:53.147Z
Learning: Applies to **/*Form.{ts,tsx} : Show validation errors inline next to form fields
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:40:00.833Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-25T14:40:00.833Z
Learning: Applies to **/*.test.{ts,tsx} : Use test helpers `getEmail`, `getEmailAccount`, and `getRule` from `@/__tests__/helpers` for mocking emails, accounts, and rules
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
📚 Learning: 2025-11-25T14:40:15.063Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:15.063Z
Learning: Applies to **/*.{tsx,ts} : For text inputs, use the `Input` component with `registerProps` for form integration and error handling
Applied to files:
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
🧬 Code graph analysis (2)
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx (4)
apps/web/utils/rule/rule.ts (1)
deleteRule(244-260)apps/web/app/api/user/rules/route.ts (1)
RulesResponse(5-5)apps/web/components/Tooltip.tsx (1)
Tooltip(18-41)apps/web/utils/condition.ts (1)
conditionsToString(200-217)
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx (8)
apps/web/utils/action-display.tsx (1)
getActionIcon(86-115)apps/web/app/(app)/[emailAccountId]/assistant/RuleSectionCard.tsx (1)
RuleSectionCard(5-37)apps/web/utils/reply-tracker/conversation-status-config.ts (1)
isConversationStatusType(16-22)apps/web/utils/rule/consts.ts (1)
getRuleConfig(112-116)apps/web/app/(app)/[emailAccountId]/assistant/ConditionSteps.tsx (1)
ConditionSteps(129-544)apps/web/app/(app)/[emailAccountId]/assistant/ActionSteps.tsx (1)
ActionSteps(46-107)apps/web/app/(app)/[emailAccountId]/assistant/group/LearnedPatterns.tsx (1)
LearnedPatternsDialog(21-96)apps/web/utils/actions/rule.ts (1)
deleteRuleAction(237-261)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: test
🔇 Additional comments (11)
apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx (5)
13-14: LGTM!The new imports for icons and tooltip functionality are correctly placed and used by the
StaticConditionsIconcomponent.Also applies to: 54-55
148-151: LGTM!The table header changes properly reflect the new UI structure, replacing the Condition column with an Action column and adjusting the sizing for the action menu.
234-240: LGTM!The ActionBadges rendering is correctly aligned to the left, matching the column header, and receives all necessary props.
412-428: LGTM!The
justify-startalignment in the flex container correctly positions the action badges to the left, matching the column header alignment.
455-476: LGTM!The helper functions correctly identify AI and static conditions, and the
StaticConditionsIconcomponent properly displays icons with a tooltip showing the formatted condition string.apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx (6)
128-128: LGTM!The form state destructuring correctly extracts
formStateand uses it for errors and submission state. TheuseFieldArraysetup for actions follows the standard React Hook Form pattern.Also applies to: 132-132, 142-146
260-270: LGTM!The
actionErrorsmemoization correctly usesformStateas a dependency and properly extracts error messages from action validation errors.
275-279: LGTM!The
formErrorsmemoization correctly usesformStateas a dependency (addressing the previous review comment) and properly extracts error messages with type-safe filtering.
357-468: LGTM!The form structure refactoring with
RuleSectionCardcomponents creates a clean, modular UI. The sections are well-organized with proper error handling, and the conditional rendering for conversation status rules is correctly implemented.
578-603: LGTM!The action buttons layout is clean and properly handles the conditional rendering of Cancel, Save, and Create buttons with appropriate loading and disabled states.
5-5: No action needed on this import change. TheInputcomponent import path change from@/components/ui/inputto@/components/Inputis correct. The custom Input component at@/components/Inputprovides proper form integration withregisterProps, error handling viaFieldError, and textarea support withautosizeTextarea—all required for form components per the coding guidelines.
| {!isColdEmailBlocker && | ||
| !isConversationStatus && ( | ||
| <DropdownMenuItem | ||
| onClick={async () => { | ||
| const yes = confirm( | ||
| `Are you sure you want to delete the rule "${rule.name}"?`, | ||
| ); | ||
| if (yes) { | ||
| toast.promise( | ||
| async () => { | ||
| const res = await deleteRule({ | ||
| id: rule.id, | ||
| }); | ||
|
|
||
| if ( | ||
| res?.serverError || | ||
| res?.validationErrors | ||
| ) { | ||
| throw new Error( | ||
| res?.serverError || | ||
| "There was an error deleting your rule", | ||
| ); | ||
| } | ||
|
|
||
| mutate(); | ||
| }, | ||
| { | ||
| loading: "Deleting rule...", | ||
| success: "Rule deleted", | ||
| error: (error) => | ||
| `Error deleting rule. ${error.message}`, | ||
| finally: () => { | ||
| mutate(); | ||
| }, | ||
| }, | ||
| ); | ||
| } | ||
| }} | ||
| > | ||
| <Trash2Icon className="mr-2 size-4" /> | ||
| Delete | ||
| </DropdownMenuItem> | ||
| )} |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check deleteRule action implementation and error handling patterns
rg -nP --type=ts -A 20 'export const deleteRule' apps/web/utils/actions/rule.tsRepository: elie222/inbox-zero
Length of output: 854
🏁 Script executed:
#!/bin/bash
# Get more context of the deleteRuleAction, especially the catch block
rg -nP --type=ts -A 35 'export const deleteRuleAction' apps/web/utils/actions/rule.ts | head -50Repository: elie222/inbox-zero
Length of output: 1422
🏁 Script executed:
#!/bin/bash
# Check the validation schema for deleteRuleAction
rg -nP --type=ts -B5 'deleteRuleBody' apps/web/utils/actions/rule.ts | head -20Repository: elie222/inbox-zero
Length of output: 368
🏁 Script executed:
#!/bin/bash
# Check the validation schema file for deleteRuleBody
rg -nP --type=ts 'deleteRuleBody' apps/web/utils/actions/rule.validation.tsRepository: elie222/inbox-zero
Length of output: 125
🏁 Script executed:
#!/bin/bash
# Check the SafeError implementation and how next-safe-action handles errors
rg -nP --type=ts 'class SafeError' . --max-count=5Repository: elie222/inbox-zero
Length of output: 129
🏁 Script executed:
#!/bin/bash
# Check the SafeError implementation
rg -nP --type=ts -A 10 'export class SafeError' apps/web/utils/error.tsRepository: elie222/inbox-zero
Length of output: 369
🏁 Script executed:
#!/bin/bash
# Check how toastError/toastSuccess are used elsewhere in the codebase
rg -nP --type=tsx 'toastError|toastSuccess' apps/web/app/\(app\)/\[emailAccountId\]/assistant/ -A 2 | head -30Repository: elie222/inbox-zero
Length of output: 89
🏁 Script executed:
#!/bin/bash
# Check how errors are handled in other parts of the codebase with server actions
rg -nP --type=ts 'toast\.(promise|error|success)' apps/web/app -A 3 | head -40Repository: elie222/inbox-zero
Length of output: 3750
🏁 Script executed:
#!/bin/bash
# Check how next-safe-action returns errors vs validation errors
rg -nP --type=ts 'validationErrors' apps/web/utils/actions/rule.ts -B 3 -A 3Repository: elie222/inbox-zero
Length of output: 44
🏁 Script executed:
#!/bin/bash
# Check how next-safe-action errors are handled at the client
rg -nP --type=ts 'serverError|validationErrors' apps/web/app/\(app\)/\[emailAccountId\]/assistant/Rules.tsx -B 2 -A 2Repository: elie222/inbox-zero
Length of output: 1062
🏁 Script executed:
#!/bin/bash
# Check if there are similar delete/action patterns with better error handling
rg -nP --type=ts 'serverError' apps/web/app/\(app\)/\[emailAccountId\]/assistant/Rules.tsx -B 3 -A 3 | head -50Repository: elie222/inbox-zero
Length of output: 1216
Remove unnecessary validationErrors check and use toastError for consistency.
The validationErrors check is unnecessary since deleteRuleBody only validates a simple string ID that won't produce meaningful validation errors. Additionally, the error handling pattern here should match the pattern used elsewhere in the same file (line 218-223): use toastError directly with result?.serverError instead of throwing within toast.promise, as indicated by the data-fetching guidelines.
🤖 Prompt for AI Agents
In apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx around lines 320 to
362, remove the unnecessary check for result?.validationErrors inside the delete
flow and replace the current throw-based error handling in toast.promise with
the consistent pattern used elsewhere: call toastError(result?.serverError) when
the deleteRule response has a serverError, avoid throwing from within the
toast.promise callback, and keep mutate() in the promise's finally handler so
the UI refreshes whether the call succeeded or failed.
Revamp rules UI to use step-based condition/action editors, iconized condition indicators, and redirect rule flows to /automation?tab=rules
Refactors the rules experience to step-based editors for conditions and actions, replaces the table’s inline condition text with tooltiped icons, adds reusable rule step/card components, updates validation to allow one AI condition plus distinct per-field static conditions, and changes post-create/delete navigation to /automation?tab=rules.
📍Where to Start
Start with the
Rulestable changes and condition icon logic in Rules.tsx, then review the new step editors in RuleForm.tsx, ConditionSteps.tsx, and ActionSteps.tsx.Macroscope summarized c1c2e2c.
Summary by CodeRabbit
New Features
Improvements
Style
✏️ Tip: You can customize this high-level summary in your review settings.
Note
Cursor Bugbot is generating a summary for commit 6067f44. Configure here.