diff --git a/apps/web/app/(app)/automation/RuleForm.tsx b/apps/web/app/(app)/automation/RuleForm.tsx
index eebb4dfa..ba70f56b 100644
--- a/apps/web/app/(app)/automation/RuleForm.tsx
+++ b/apps/web/app/(app)/automation/RuleForm.tsx
@@ -18,7 +18,7 @@ import { toast } from "sonner";
import TextareaAutosize from "react-textarea-autosize";
import { capitalCase } from "capital-case";
import { usePostHog } from "posthog-js/react";
-import { ExternalLinkIcon, PlusIcon } from "lucide-react";
+import { ExternalLinkIcon, PlusIcon, FilterIcon } from "lucide-react";
import { Card } from "@/components/Card";
import { Button } from "@/components/ui/button";
import { ErrorMessage, Input, Label } from "@/components/Input";
@@ -28,7 +28,12 @@ import {
SectionDescription,
TypographyH3,
} from "@/components/Typography";
-import { ActionType, CategoryFilterType, RuleType } from "@prisma/client";
+import {
+ ActionType,
+ CategoryFilterType,
+ LogicalOperator,
+ RuleType,
+} from "@prisma/client";
import { createRuleAction, updateRuleAction } from "@/utils/actions/rule";
import {
type CreateRuleBody,
@@ -58,6 +63,13 @@ import { hasVariables } from "@/utils/template";
import { getEmptyCondition } from "@/utils/condition";
import { AlertError } from "@/components/Alert";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuRadioGroup,
+ DropdownMenuRadioItem,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu";
export function RuleForm({ rule }: { rule: CreateRuleBody & { id?: string } }) {
const {
@@ -189,7 +201,36 @@ export function RuleForm({ rule }: { rule: CreateRuleBody & { id?: string } }) {
/>
- Conditions
+
+ Conditions
+
+
+
+
+
+
+
+ setValue("conditionalOperator", value as LogicalOperator)
+ }
+ >
+
+ Match all conditions
+
+
+ Match any condition
+
+
+
+
+
{errors.conditions?.root?.message && (
diff --git a/apps/web/utils/actions/rule.ts b/apps/web/utils/actions/rule.ts
index ba4b9da1..522346ac 100644
--- a/apps/web/utils/actions/rule.ts
+++ b/apps/web/utils/actions/rule.ts
@@ -19,6 +19,7 @@ import { getGmailAccessToken, getGmailClient } from "@/utils/gmail/client";
import { aiFindExampleMatches } from "@/utils/ai/example-matches/find-example-matches";
import { withActionInstrumentation } from "@/utils/actions/middleware";
import { flattenConditions } from "@/utils/condition";
+import { LogicalOperator } from "@prisma/client";
export const createRuleAction = withActionInstrumentation(
"createRule",
@@ -58,6 +59,7 @@ export const createRuleAction = withActionInstrumentation(
}
: undefined,
userId: session.user.id,
+ conditionalOperator: body.conditionalOperator || LogicalOperator.AND,
// conditions
instructions: conditions.instructions || null,
from: conditions.from || null,
@@ -124,6 +126,8 @@ export const updateRuleAction = withActionInstrumentation(
automate: body.automate ?? undefined,
runOnThreads: body.runOnThreads ?? undefined,
name: body.name || undefined,
+ conditionalOperator:
+ body.conditionalOperator || LogicalOperator.AND,
// conditions
instructions: conditions.instructions || null,
from: conditions.from || null,
diff --git a/apps/web/utils/actions/validation.ts b/apps/web/utils/actions/validation.ts
index d72898dd..72745c66 100644
--- a/apps/web/utils/actions/validation.ts
+++ b/apps/web/utils/actions/validation.ts
@@ -1,5 +1,9 @@
import { z } from "zod";
-import { CategoryFilterType, GroupItemType } from "@prisma/client";
+import {
+ CategoryFilterType,
+ GroupItemType,
+ LogicalOperator,
+} from "@prisma/client";
import { ActionType, RuleType } from "@prisma/client";
// groups
@@ -134,6 +138,9 @@ export const createRuleBody = z.object({
message: "You can't have two conditions with the same type.",
},
),
+ conditionalOperator: z
+ .enum([LogicalOperator.AND, LogicalOperator.OR])
+ .default(LogicalOperator.AND),
});
export type CreateRuleBody = z.infer;