Skip to content

Commit

Permalink
Add radio group match/skip for smart category
Browse files Browse the repository at this point in the history
  • Loading branch information
elie222 committed Dec 20, 2024
1 parent dac204e commit 3ecbf70
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 37 deletions.
54 changes: 30 additions & 24 deletions apps/web/app/(app)/automation/RuleForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
SectionDescription,
TypographyH3,
} from "@/components/Typography";
import { ActionType, CategoryFilterType, RuleType } from "@prisma/client";
import { ActionType, type CategoryFilterType, RuleType } from "@prisma/client";
import { createRuleAction, updateRuleAction } from "@/utils/actions/rule";
import {
type CreateRuleBody,
Expand Down Expand Up @@ -57,6 +57,7 @@ import { useCategories } from "@/hooks/useCategories";
import { hasVariables } from "@/utils/template";
import { getEmptyConditions } from "@/utils/condition";
import { AlertError } from "@/components/Alert";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";

export function RuleForm({ rule }: { rule: CreateRuleBody & { id?: string } }) {
const {
Expand Down Expand Up @@ -311,6 +312,34 @@ export function RuleForm({ rule }: { rule: CreateRuleBody & { id?: string } }) {

{watch(`conditions.${index}.type`) === RuleType.CATEGORY && (
<>
<div className="flex items-center gap-4">
<RadioGroup
defaultValue="include"
value={
watch(`conditions.${index}.categoryFilterType`) ||
undefined
}
onValueChange={(value) =>
setValue(
`conditions.${index}.categoryFilterType`,
value as CategoryFilterType,
)
}
className="flex gap-6"
>
<div className="flex items-center space-x-2">
<RadioGroupItem value="include" id="include" />
<Label name="include" label="Match" />
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="exclude" id="exclude" />
<Label name="exclude" label="Skip" />
</div>
</RadioGroup>

<TooltipExplanation text="This stops the AI from applying this rule to emails that don't match your criteria." />
</div>

<LoadingContent
loading={categoriesLoading}
error={categoriesError}
Expand Down Expand Up @@ -355,29 +384,6 @@ export function RuleForm({ rule }: { rule: CreateRuleBody & { id?: string } }) {
<ExternalLinkIcon className="ml-1.5 size-4" />
</Link>
</Button>

<Select
label="Filter type"
tooltipText="This stops the AI from applying this rule to emails that don't match your criteria."
options={[
{
label: "Include",
value: CategoryFilterType.INCLUDE,
},
{
label: "Exclude",
value: CategoryFilterType.EXCLUDE,
},
]}
{...register(`conditions.${index}.categoryFilterType`)}
error={
(
errors.conditions?.[index] as {
categoryFilterType?: FieldError;
}
)?.categoryFilterType
}
/>
</>
)}
</div>
Expand Down
44 changes: 44 additions & 0 deletions apps/web/components/ui/radio-group.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"use client";

import * as React from "react";
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
import { Circle } from "lucide-react";

import { cn } from "@/utils";

const RadioGroup = React.forwardRef<
React.ElementRef<typeof RadioGroupPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>
>(({ className, ...props }, ref) => {
return (
<RadioGroupPrimitive.Root
className={cn("grid gap-2", className)}
{...props}
ref={ref}
/>
);
});
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;

const RadioGroupItem = React.forwardRef<
React.ElementRef<typeof RadioGroupPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>
>(({ className, ...props }, ref) => {
return (
<RadioGroupPrimitive.Item
ref={ref}
className={cn(
"aspect-square h-4 w-4 rounded-full border border-slate-200 border-slate-900 text-slate-900 ring-offset-white focus:outline-none focus-visible:ring-2 focus-visible:ring-slate-950 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-50 dark:border-slate-800 dark:text-slate-50 dark:ring-offset-slate-950 dark:focus-visible:ring-slate-300",
className,
)}
{...props}
>
<RadioGroupPrimitive.Indicator className="flex items-center justify-center">
<Circle className="h-2.5 w-2.5 fill-current text-current" />
</RadioGroupPrimitive.Indicator>
</RadioGroupPrimitive.Item>
);
});
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;

export { RadioGroup, RadioGroupItem };
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"@radix-ui/react-label": "^2.1.1",
"@radix-ui/react-navigation-menu": "^1.2.2",
"@radix-ui/react-popover": "^1.1.3",
"@radix-ui/react-radio-group": "^1.2.2",
"@radix-ui/react-scroll-area": "^1.2.2",
"@radix-ui/react-select": "^2.1.3",
"@radix-ui/react-separator": "^1.1.1",
Expand Down
2 changes: 1 addition & 1 deletion apps/web/utils/condition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ const staticEmptyCondition = {

const categoryEmptyCondition = {
type: RuleType.CATEGORY,
categoryFilterType: null,
categoryFilterType: CategoryFilterType.INCLUDE,
categoryFilters: null,
};

Expand Down
46 changes: 34 additions & 12 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 3ecbf70

Please sign in to comment.