Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import type { ParsedMessage } from "@/utils/types";
import { ViewEmailButton } from "@/components/ViewEmailButton";
import { ExecutedRuleStatus } from "@prisma/client";
import { FixWithChat } from "@/app/(app)/[emailAccountId]/assistant/FixWithChat";
import { useAssistantNavigation } from "@/hooks/useAssistantNavigation";
import { useAccount } from "@/providers/EmailAccountProvider";
import { isGoogleProvider } from "@/utils/email/provider-types";
import { useRuleDialog } from "@/app/(app)/[emailAccountId]/assistant/RuleDialog";

export function EmailCell({
from,
Expand Down Expand Up @@ -62,21 +62,19 @@ export function EmailCell({
}

export function RuleCell({
emailAccountId,
rule,
status,
reason,
message,
setInput,
}: {
emailAccountId: string;
rule: PendingExecutedRules["executedRules"][number]["rule"];
status: ExecutedRuleStatus;
reason?: string | null;
message: ParsedMessage;
setInput: (input: string) => void;
}) {
const { createAssistantUrl } = useAssistantNavigation(emailAccountId);
const { ruleDialog, RuleDialogComponent } = useRuleDialog();

return (
<div className="flex items-center justify-end gap-2">
Expand Down Expand Up @@ -104,21 +102,18 @@ export function RuleCell({
</div>
<div className="mt-2">
{!!rule && (
<Button size="sm" asChild>
<Link
href={createAssistantUrl({
tab: "rule",
ruleId: rule.id,
path: `/assistant/rule/${rule.id}`,
})}
>
View
</Link>
<Button
size="sm"
onClick={() => {
ruleDialog.onOpen({ ruleId: rule.id });
}}
>
View Rule
</Button>
)}
</div>
{!!reason && (
<div className="mt-4 space-y-2">
<div className="mt-4 space-y-2 bg-muted p-2 rounded-md">
<div className="font-medium">
Reason for choosing this rule:
</div>
Expand All @@ -143,6 +138,7 @@ export function RuleCell({
message={message}
result={{ rule, reason }}
/>
<RuleDialogComponent />
</div>
);
}
Expand Down
3 changes: 0 additions & 3 deletions apps/web/app/(app)/[emailAccountId]/assistant/FixWithChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,6 @@ export function FixWithChat({
const [selectedRuleId, setSelectedRuleId] = useState<string | null>(null);
const [explanation, setExplanation] = useState("");
const [showExplanation, setShowExplanation] = useState(false);
// const { createAssistantUrl } = useAssistantNavigation(emailAccountId);
// const router = useRouter();
// const [currentTab] = useQueryState("tab");

const { setOpen } = useSidebar();

Expand Down
3 changes: 1 addition & 2 deletions apps/web/app/(app)/[emailAccountId]/assistant/History.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ function HistoryTable({
data: PlanHistoryResponse["executedRules"];
totalPages: number;
}) {
const { userEmail, emailAccountId } = useAccount();
const { userEmail } = useAccount();
const { setInput } = useChat();

return (
Expand Down Expand Up @@ -98,7 +98,6 @@ function HistoryTable({
</TableCell>
<TableCell>
<RuleCell
emailAccountId={emailAccountId}
rule={p.rule}
status={p.status}
reason={p.reason}
Expand Down
1 change: 0 additions & 1 deletion apps/web/app/(app)/[emailAccountId]/assistant/Pending.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,6 @@ function PendingTable({
</TableCell>
<TableCell>
<RuleCell
emailAccountId={emailAccountId}
rule={p.rule}
status={p.status}
reason={p.reason}
Expand Down
19 changes: 19 additions & 0 deletions apps/web/app/(app)/[emailAccountId]/assistant/RuleDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use client";

import { useCallback } from "react";
import {
Dialog,
DialogContent,
Expand All @@ -10,6 +11,7 @@ import { RuleForm } from "./RuleForm";
import { LoadingContent } from "@/components/LoadingContent";
import { useRule } from "@/hooks/useRule";
import type { CreateRuleBody } from "@/utils/actions/rule.validation";
import { useDialogState } from "@/hooks/useDialogState";

interface RuleDialogProps {
ruleId?: string;
Expand All @@ -20,6 +22,23 @@ interface RuleDialogProps {
editMode?: boolean;
}

export function useRuleDialog() {
const ruleDialog = useDialogState<{ ruleId: string }>();

const RuleDialogComponent = useCallback(() => {
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Sep 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defining the component with useCallback tied to changing deps will remount the component on each change (e.g., toggling isOpen), potentially losing internal state; consider returning a memoized element instead or render RuleDialog directly with the returned state.

Prompt for AI agents
Address the following comment on apps/web/app/(app)/[emailAccountId]/assistant/RuleDialog.tsx at line 28:

<comment>Defining the component with useCallback tied to changing deps will remount the component on each change (e.g., toggling isOpen), potentially losing internal state; consider returning a memoized element instead or render RuleDialog directly with the returned state.</comment>

<file context>
@@ -20,6 +22,23 @@ interface RuleDialogProps {
+export function useRuleDialog() {
+  const ruleDialog = useDialogState&lt;{ ruleId: string }&gt;();
+
+  const RuleDialogComponent = useCallback(() =&gt; {
+    return (
+      &lt;RuleDialog
</file context>
Fix with Cubic

return (
<RuleDialog
ruleId={ruleDialog.data?.ruleId}
isOpen={ruleDialog.isOpen}
onClose={ruleDialog.onClose}
editMode={false}
/>
);
}, [ruleDialog.data?.ruleId, ruleDialog.isOpen, ruleDialog.onClose]);

return { ruleDialog, RuleDialogComponent };
}

export function RuleDialog({
ruleId,
isOpen,
Expand Down
11 changes: 4 additions & 7 deletions apps/web/app/(app)/[emailAccountId]/assistant/Rules.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ import type { RulesResponse } from "@/app/api/user/rules/route";
import { sortActionsByPriority } from "@/utils/action-sort";
import { inboxZeroLabels } from "@/utils/label";
import { isDefined } from "@/utils/types";
import { useAssistantNavigation } from "@/hooks/useAssistantNavigation";
import { getActionDisplay } from "@/utils/action-display";
import { RuleDialog } from "./RuleDialog";
import { useDialogState } from "@/hooks/useDialogState";
Expand Down Expand Up @@ -86,7 +85,6 @@ export function Rules({
const onCreateRule = () => ruleDialog.onOpen();

const { emailAccountId, provider } = useAccount();
const { createAssistantUrl } = useAssistantNavigation(emailAccountId);
const { executeAsync: setRuleEnabled } = useAction(
setRuleEnabledAction.bind(null, emailAccountId),
{
Expand Down Expand Up @@ -392,11 +390,10 @@ export function Rules({
emailAccountId,
"/cold-email-blocker",
)
: createAssistantUrl({
tab: "history",
ruleId: rule.id,
path: "/automation?tab=history",
})
: prefixPath(
emailAccountId,
`/automation?tab=history&ruleId=${rule.id}`,
)
}
target={
isColdEmailBlocker ? "_blank" : undefined
Expand Down
2 changes: 1 addition & 1 deletion apps/web/components/HoverCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function HoverCard(props: {
className?: string;
}) {
return (
<HoverCardUi>
<HoverCardUi openDelay={100} closeDelay={100}>
<HoverCardTrigger asChild>{props.children}</HoverCardTrigger>
<HoverCardContent className={props.className} align="start" side="right">
{props.content}
Expand Down
36 changes: 0 additions & 36 deletions apps/web/hooks/useAssistantNavigation.ts

This file was deleted.

2 changes: 1 addition & 1 deletion version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v2.9.14
v2.9.15
Loading