Conversation
This commit introduces the email templates feature, allowing you to create reusable templates for broadcast and sequence emails. Backend: - Added `EmailTemplate` model. - Implemented GraphQL queries (`getEmailTemplate`, `getEmailTemplates`) and mutations (`createEmailTemplate`, `updateEmailTemplate`, `deleteEmailTemplate`) for email templates. - Added logic for the new GraphQL operations. Frontend: - Added a 'Templates' tab to the `/dashboard/mails` page. - Created a `TemplatesList` component to display email templates. - Created an email template editor page. - Created a new page for selecting a template when creating a new broadcast or sequence. - Updated the `createSequence` mutation to accept `title` and `content` from a template.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
| .build(); | ||
|
|
||
| try { | ||
| dispatch && dispatch(networkAction(true)); |
Check warning
Code scanning / CodeQL
Superfluous trailing arguments Warning
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 1 day ago
In general, to fix a “superfluous trailing arguments” issue, either remove the unused arguments or ensure the callee’s signature and implementation actually make use of them. In this case, the argument to dispatch is semantically important (it is an action from networkAction(true/false)), so the correct fix is to make dispatch accept and use that argument instead of being a no-op function.
Concretely, in apps/web/app/(with-contexts)/dashboard/mails/new/new-mail-page-client.tsx, replace the stub const dispatch = () => {}; with a proper Redux dispatch obtained from the store or from a hook. Since we already import AppState, ThunkDispatch, and AnyAction, the most minimal, functionality-preserving change within this file is to import useDispatch from react-redux and use it to get a correctly typed dispatch function:
- Add
import { useDispatch } from "react-redux";alongside the other imports. - Change line 28 from
const dispatch = () => {};to:
const dispatch: ThunkDispatch<AppState, unknown, AnyAction> = useDispatch();This way, dispatch(networkAction(true)) and dispatch(networkAction(false)) become meaningful calls to the Redux dispatch function, the argument is no longer superfluous, and existing behavior (intended network action toggling) is preserved rather than removed.
| @@ -13,6 +13,7 @@ | ||
| import { AnyAction } from "redux"; | ||
| import { AddressContext } from "@components/contexts"; | ||
| import { useContext } from "react"; | ||
| import { useDispatch } from "react-redux"; | ||
|
|
||
| interface NewMailPageClientProps { | ||
| systemTemplates: EmailTemplate[]; | ||
| @@ -25,7 +26,7 @@ | ||
| const { toast } = useToast(); | ||
| const router = useRouter(); | ||
| const searchParams = useSearchParams(); | ||
| const dispatch = () => {}; | ||
| const dispatch: ThunkDispatch<AppState, unknown, AnyAction> = useDispatch(); | ||
|
|
||
| const type = searchParams?.get("type") as SequenceType; | ||
|
|
| @@ -102,7 +102,8 @@ | ||
| "tailwind-merge": "^2.5.4", | ||
| "tailwindcss-animate": "^1.0.7", | ||
| "xml2js": "^0.6.2", | ||
| "zod": "^3.24.1" | ||
| "zod": "^3.24.1", | ||
| "react-redux": "^9.2.0" | ||
| }, | ||
| "devDependencies": { | ||
| "@eslint/eslintrc": "^3.3.1", |
| Package | Version | Security advisories |
| react-redux (npm) | 9.2.0 | None |
| variant: "destructive", | ||
| }); | ||
| } finally { | ||
| dispatch && dispatch(networkAction(false)); |
Check warning
Code scanning / CodeQL
Superfluous trailing arguments Warning
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 1 day ago
In general, to fix superfluous trailing arguments, either (a) remove the extra arguments if they truly are not needed, or (b) update the function so it correctly accepts and uses those arguments. Here, calls like dispatch(networkAction(true)) are intended to dispatch Redux actions; the problem is that dispatch is currently a zero-argument no-op. Removing the argument would only hide the intent and keep the code from dispatching anything, so the correct fix is to replace the stub with a real dispatch that accepts an action argument.
The best fix with minimal functional change is to obtain a proper Redux dispatch from the Redux store using the useDispatch hook from react-redux, typed as ThunkDispatch<AppState, null, AnyAction> to match the existing imports. Then replace const dispatch = () => {}; with const dispatch = useDispatch<ThunkDispatch<AppState, null, AnyAction>>();. This makes dispatch a function that expects an action (or thunk) argument, so the existing calls with networkAction(true/false) become meaningful and no longer have superfluous arguments.
Concretely:
- In
apps/web/app/(with-contexts)/dashboard/mails/new/new-mail-page-client.tsx, add an import foruseDispatchfromreact-reduxalongside the other imports. - Replace the line
const dispatch = () => {};with a typeduseDispatchcall, e.g.const dispatch = useDispatch<ThunkDispatch<AppState, null, AnyAction>>();.
No other changes are required in the shown snippet.
| @@ -13,6 +13,7 @@ | ||
| import { AnyAction } from "redux"; | ||
| import { AddressContext } from "@components/contexts"; | ||
| import { useContext } from "react"; | ||
| import { useDispatch } from "react-redux"; | ||
|
|
||
| interface NewMailPageClientProps { | ||
| systemTemplates: EmailTemplate[]; | ||
| @@ -25,7 +26,7 @@ | ||
| const { toast } = useToast(); | ||
| const router = useRouter(); | ||
| const searchParams = useSearchParams(); | ||
| const dispatch = () => {}; | ||
| const dispatch = useDispatch<ThunkDispatch<AppState, null, AnyAction>>(); | ||
|
|
||
| const type = searchParams?.get("type") as SequenceType; | ||
|
|
| try { | ||
| dispatch && | ||
| (dispatch as ThunkDispatch<AppState, null, AnyAction>)( | ||
| networkAction(true), |
Check warning
Code scanning / CodeQL
Superfluous trailing arguments Warning
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 1 day ago
To fix this, we should ensure that dispatch is actually a Redux Thunk dispatch function rather than a no-op. That way, calling dispatch(networkAction(true)) and dispatch(networkAction(false)) is both type-correct and functionally meaningful, and the argument to networkAction is no longer “superfluous” in practice.
Concretely, in apps/web/app/(with-contexts)/dashboard/mails/new/new-mail-page-client.tsx:
- Replace the placeholder
const dispatch = () => {};with a real dispatch obtained from the Redux store, usinguseDispatchfromreact-reduxand typing it asThunkDispatch<AppState, null, AnyAction>. - Add the necessary import for
useDispatchfromreact-redux.
This preserves the existing behavior intent (toggling network state before/after the async call) without changing other logic.
| @@ -13,6 +13,7 @@ | ||
| import { AnyAction } from "redux"; | ||
| import { AddressContext } from "@components/contexts"; | ||
| import { useContext } from "react"; | ||
| import { useDispatch } from "react-redux"; | ||
|
|
||
| interface NewMailPageClientProps { | ||
| systemTemplates: EmailTemplate[]; | ||
| @@ -25,7 +26,7 @@ | ||
| const { toast } = useToast(); | ||
| const router = useRouter(); | ||
| const searchParams = useSearchParams(); | ||
| const dispatch = () => {}; | ||
| const dispatch = useDispatch<ThunkDispatch<AppState, null, AnyAction>>(); | ||
|
|
||
| const type = searchParams?.get("type") as SequenceType; | ||
|
|
| } finally { | ||
| dispatch && | ||
| (dispatch as ThunkDispatch<AppState, null, AnyAction>)( | ||
| networkAction(false), |
Check warning
Code scanning / CodeQL
Superfluous trailing arguments Warning
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 1 day ago
In general, to fix “superfluous trailing arguments” you either (a) remove the unused arguments from the call site, or (b) update the function so it actually accepts and uses those arguments. Here, dispatch is clearly intended to receive actions created by networkAction, matching Redux usage already present elsewhere in the codebase (as suggested by the imports from @courselit/state-management and use of ThunkDispatch). Removing the arguments would hide the underlying bug (that network actions are never dispatched). The best fix is to replace the dummy dispatch implementation with a proper one retrieved from Redux.
Concretely, in apps/web/app/(with-contexts)/dashboard/mails/new/new-mail-page-client.tsx, replace const dispatch = () => {}; with a typed Redux dispatch from useDispatch (from react-redux), using the existing ThunkDispatch<AppState, null, AnyAction> type. This way, dispatch(networkAction(true)) and dispatch(networkAction(false)) become valid calls whose argument is actually consumed, eliminating the “superfluous argument” condition and restoring the intended behavior. To implement this, add an import for useDispatch from react-redux, then define const dispatch: ThunkDispatch<AppState, null, AnyAction> = useDispatch(); (or similar) in place of the stub. No other call sites need to change.
| @@ -13,6 +13,7 @@ | ||
| import { AnyAction } from "redux"; | ||
| import { AddressContext } from "@components/contexts"; | ||
| import { useContext } from "react"; | ||
| import { useDispatch } from "react-redux"; | ||
|
|
||
| interface NewMailPageClientProps { | ||
| systemTemplates: EmailTemplate[]; | ||
| @@ -25,7 +26,7 @@ | ||
| const { toast } = useToast(); | ||
| const router = useRouter(); | ||
| const searchParams = useSearchParams(); | ||
| const dispatch = () => {}; | ||
| const dispatch: ThunkDispatch<AppState, null, AnyAction> = useDispatch(); | ||
|
|
||
| const type = searchParams?.get("type") as SequenceType; | ||
|
|
| @@ -102,7 +102,8 @@ | ||
| "tailwind-merge": "^2.5.4", | ||
| "tailwindcss-animate": "^1.0.7", | ||
| "xml2js": "^0.6.2", | ||
| "zod": "^3.24.1" | ||
| "zod": "^3.24.1", | ||
| "react-redux": "^9.2.0" | ||
| }, | ||
| "devDependencies": { | ||
| "@eslint/eslintrc": "^3.3.1", |
| Package | Version | Security advisories |
| react-redux (npm) | 9.2.0 | None |
| const NewMailPageClient = ({ systemTemplates }: NewMailPageClientProps) => { | ||
| const address = useContext(AddressContext); | ||
| const [templates, setTemplates] = useState<EmailTemplate[]>([]); | ||
| const [isLoading, setIsLoading] = useState(false); |
Check notice
Code scanning / CodeQL
Unused variable, import, function or class Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 1 day ago
To fix the problem, remove the unused isLoading state variable and its setter calls, since no rendering or logic depends on it. This avoids maintaining redundant state and eliminates the CodeQL warning.
Concretely, in apps/web/app/(with-contexts)/dashboard/mails/new/new-mail-page-client.tsx:
- Change the
useStatedeclaration on line 24 so that it no longer createsisLoading/setIsLoading. Since neither is used elsewhere, simply remove that line entirely. - In
loadTemplates, remove the calls tosetIsLoading(true);(line 41) andsetIsLoading(false);(line 78 or 79, depending on numbering after edits), as these will no longer be defined and serve no purpose.
No new methods, imports, or definitions are needed. Functionality is unchanged, because nothing depended on isLoading before.
| @@ -21,7 +21,6 @@ | ||
| const NewMailPageClient = ({ systemTemplates }: NewMailPageClientProps) => { | ||
| const address = useContext(AddressContext); | ||
| const [templates, setTemplates] = useState<EmailTemplate[]>([]); | ||
| const [isLoading, setIsLoading] = useState(false); | ||
| const { toast } = useToast(); | ||
| const router = useRouter(); | ||
| const searchParams = useSearchParams(); | ||
| @@ -38,7 +37,6 @@ | ||
| }, []); | ||
|
|
||
| const loadTemplates = async () => { | ||
| setIsLoading(true); | ||
| const query = ` | ||
| query GetEmailTemplates { | ||
| templates: getEmailTemplates { | ||
| @@ -75,7 +73,6 @@ | ||
| }); | ||
| } finally { | ||
| dispatch && dispatch(networkAction(false)); | ||
| setIsLoading(false); | ||
| } | ||
| }; | ||
|
|
This commit introduces the email templates feature, allowing you to create reusable templates for broadcast and sequence emails.
Backend:
EmailTemplatemodel.getEmailTemplate,getEmailTemplates) and mutations (createEmailTemplate,updateEmailTemplate,deleteEmailTemplate) for email templates.Frontend:
/dashboard/mailspage.TemplatesListcomponent to display email templates.createSequencemutation to accepttitleandcontentfrom a template.