Feat: Added ability to overwrite sender mail and name for templates and campaigns
This commit is contained in:
@@ -32,6 +32,8 @@ import { network } from "../../lib/network";
|
||||
interface CampaignValues {
|
||||
subject: string;
|
||||
body: string;
|
||||
email?: string;
|
||||
from?: string;
|
||||
recipients: string[];
|
||||
style: "PLUNK" | "HTML";
|
||||
}
|
||||
@@ -71,6 +73,8 @@ export default function Index() {
|
||||
watch,
|
||||
reset,
|
||||
setValue,
|
||||
setError,
|
||||
clearErrors,
|
||||
} = useForm<CampaignValues>({
|
||||
resolver: zodResolver(CampaignSchemas.update),
|
||||
defaultValues: { recipients: [], body: undefined },
|
||||
@@ -87,6 +91,21 @@ export default function Index() {
|
||||
});
|
||||
}, [reset, campaign]);
|
||||
|
||||
useEffect(() => {
|
||||
watch((value, { name, type }) => {
|
||||
if (name === "email") {
|
||||
if (value.email && project?.email && !value.email.endsWith(project.email.split("@")[1])) {
|
||||
setError("email", {
|
||||
type: "manual",
|
||||
message: `The sender address must end with @${project.email?.split("@")[1]}`,
|
||||
});
|
||||
} else {
|
||||
clearErrors("email");
|
||||
}
|
||||
}
|
||||
});
|
||||
}, [watch, project, setError, clearErrors]);
|
||||
|
||||
if (!project || !campaign || !events || (watch("body") as string | undefined) === undefined) {
|
||||
return <FullscreenLoader />;
|
||||
}
|
||||
@@ -404,13 +423,35 @@ export default function Index() {
|
||||
}
|
||||
>
|
||||
<form onSubmit={handleSubmit(update)} className="space-6 grid gap-6 sm:grid-cols-6">
|
||||
<Input
|
||||
className={"sm:col-span-6"}
|
||||
label={"Subject"}
|
||||
placeholder={`Welcome to ${project.name}!`}
|
||||
register={register("subject")}
|
||||
error={errors.subject}
|
||||
/>
|
||||
<div className={"sm:col-span-6 grid sm:grid-cols-6 gap-6"}>
|
||||
<Input
|
||||
className={"sm:col-span-6"}
|
||||
label={"Subject"}
|
||||
placeholder={`Welcome to ${project.name}!`}
|
||||
register={register("subject")}
|
||||
error={errors.subject}
|
||||
/>
|
||||
|
||||
{project.verified && (
|
||||
<Input
|
||||
className={"sm:col-span-3"}
|
||||
label={"Sender Email"}
|
||||
placeholder={`${project.email}`}
|
||||
register={register("email")}
|
||||
error={errors.email}
|
||||
/>
|
||||
)}
|
||||
|
||||
{project.verified && (
|
||||
<Input
|
||||
className={"sm:col-span-3"}
|
||||
label={"Sender Name"}
|
||||
placeholder={`${project.name}`}
|
||||
register={register("from")}
|
||||
error={errors.from}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{contacts ? (
|
||||
<>
|
||||
|
||||
@@ -6,7 +6,7 @@ import dayjs from "dayjs";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import { Search, Users2, XIcon } from "lucide-react";
|
||||
import { useRouter } from "next/router";
|
||||
import React, { useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { type FieldError, useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { Alert, Card, Dropdown, Editor, FullscreenLoader, Input, MultiselectDropdown } from "../../components";
|
||||
@@ -20,6 +20,8 @@ import { network } from "../../lib/network";
|
||||
interface CampaignValues {
|
||||
subject: string;
|
||||
body: string;
|
||||
email?: string;
|
||||
from?: string;
|
||||
recipients: string[];
|
||||
style: "PLUNK" | "HTML";
|
||||
}
|
||||
@@ -58,6 +60,8 @@ export default function Index() {
|
||||
formState: { errors },
|
||||
setValue,
|
||||
watch,
|
||||
setError,
|
||||
clearErrors,
|
||||
} = useForm<CampaignValues>({
|
||||
resolver: zodResolver(CampaignSchemas.create),
|
||||
defaultValues: {
|
||||
@@ -67,6 +71,21 @@ export default function Index() {
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
watch((value, { name, type }) => {
|
||||
if (name === "email") {
|
||||
if (value.email && project?.email && !value.email.endsWith(project.email.split("@")[1])) {
|
||||
setError("email", {
|
||||
type: "manual",
|
||||
message: `The sender address must end with @${project.email?.split("@")[1]}`,
|
||||
});
|
||||
} else {
|
||||
clearErrors("email");
|
||||
}
|
||||
}
|
||||
});
|
||||
}, [watch, project, setError, clearErrors]);
|
||||
|
||||
if (!project || !events) {
|
||||
return <FullscreenLoader />;
|
||||
}
|
||||
@@ -194,13 +213,36 @@ export default function Index() {
|
||||
<Dashboard>
|
||||
<Card title={"Create a new campaign"}>
|
||||
<form onSubmit={handleSubmit(create)} className="space-6 grid gap-6 sm:grid-cols-6">
|
||||
<Input
|
||||
className={"sm:col-span-6"}
|
||||
label={"Subject"}
|
||||
placeholder={`Welcome to ${project.name}!`}
|
||||
register={register("subject")}
|
||||
error={errors.subject}
|
||||
/>
|
||||
<div className={"sm:col-span-6 grid sm:grid-cols-6 gap-6"}>
|
||||
<Input
|
||||
className={"sm:col-span-6"}
|
||||
label={"Subject"}
|
||||
placeholder={`Welcome to ${project.name}!`}
|
||||
register={register("subject")}
|
||||
error={errors.subject}
|
||||
/>
|
||||
|
||||
{project.verified && (
|
||||
<Input
|
||||
className={"sm:col-span-3"}
|
||||
label={"Sender Email"}
|
||||
placeholder={`${project.email}`}
|
||||
register={register("email")}
|
||||
error={errors.email}
|
||||
/>
|
||||
)}
|
||||
|
||||
{project.verified && (
|
||||
<Input
|
||||
className={"sm:col-span-3"}
|
||||
label={"Sender Name"}
|
||||
placeholder={`${project.name}`}
|
||||
register={register("from")}
|
||||
error={errors.from}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{contacts ? (
|
||||
<>
|
||||
<div className={"sm:col-span-3"}>
|
||||
|
||||
@@ -16,6 +16,8 @@ import { network } from "../../lib/network";
|
||||
interface TemplateValues {
|
||||
subject: string;
|
||||
body: string;
|
||||
email?: string;
|
||||
from?: string;
|
||||
type: "MARKETING" | "TRANSACTIONAL";
|
||||
style: "PLUNK" | "HTML";
|
||||
}
|
||||
@@ -41,6 +43,8 @@ export default function Index() {
|
||||
watch,
|
||||
setValue,
|
||||
reset,
|
||||
setError,
|
||||
clearErrors,
|
||||
} = useForm<TemplateValues>({
|
||||
resolver: zodResolver(TemplateSchemas.update),
|
||||
defaultValues: {
|
||||
@@ -56,6 +60,21 @@ export default function Index() {
|
||||
reset(template);
|
||||
}, [reset, template]);
|
||||
|
||||
useEffect(() => {
|
||||
watch((value, { name, type }) => {
|
||||
if (name === "email") {
|
||||
if (value.email && project?.email && !value.email.endsWith(project.email.split("@")[1])) {
|
||||
setError("email", {
|
||||
type: "manual",
|
||||
message: `The sender address must end with @${project.email?.split("@")[1]}`,
|
||||
});
|
||||
} else {
|
||||
clearErrors("email");
|
||||
}
|
||||
}
|
||||
});
|
||||
}, [watch, project, setError, clearErrors]);
|
||||
|
||||
if (!project || !template || (watch("body") as string | undefined) === undefined) {
|
||||
return <FullscreenLoader />;
|
||||
}
|
||||
@@ -248,6 +267,26 @@ export default function Index() {
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
|
||||
{project.verified && (
|
||||
<Input
|
||||
className={"sm:col-span-3"}
|
||||
label={"Sender Email"}
|
||||
placeholder={`${project.email}`}
|
||||
register={register("email")}
|
||||
error={errors.email}
|
||||
/>
|
||||
)}
|
||||
|
||||
{project.verified && (
|
||||
<Input
|
||||
className={"sm:col-span-3"}
|
||||
label={"Sender Name"}
|
||||
placeholder={`${project.name}`}
|
||||
register={register("from")}
|
||||
error={errors.from}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className={"sm:col-span-6"}>
|
||||
<Editor
|
||||
value={watch("body")}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { TemplateSchemas } from "@plunk/shared";
|
||||
import type { Template } from "@prisma/client";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import { useRouter } from "next/router";
|
||||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { Card, Dropdown, Editor, FullscreenLoader, Input, Tooltip } from "../../components";
|
||||
@@ -15,6 +15,8 @@ import { network } from "../../lib/network";
|
||||
interface TemplateValues {
|
||||
subject: string;
|
||||
body: string;
|
||||
email?: string;
|
||||
from?: string;
|
||||
type: "MARKETING" | "TRANSACTIONAL";
|
||||
style: "PLUNK" | "HTML";
|
||||
}
|
||||
@@ -41,6 +43,8 @@ export default function Index() {
|
||||
formState: { errors },
|
||||
watch,
|
||||
setValue,
|
||||
setError,
|
||||
clearErrors,
|
||||
} = useForm<TemplateValues>({
|
||||
resolver: zodResolver(TemplateSchemas.create),
|
||||
defaultValues: {
|
||||
@@ -50,6 +54,21 @@ export default function Index() {
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
watch((value, { name, type }) => {
|
||||
if (name === "email") {
|
||||
if (value.email && project?.email && !value.email.endsWith(project.email.split("@")[1])) {
|
||||
setError("email", {
|
||||
type: "manual",
|
||||
message: `The sender address must end with @${project.email?.split("@")[1]}`,
|
||||
});
|
||||
} else {
|
||||
clearErrors("email");
|
||||
}
|
||||
}
|
||||
});
|
||||
}, [watch, project, setError, clearErrors]);
|
||||
|
||||
if (!project) {
|
||||
return <FullscreenLoader />;
|
||||
}
|
||||
@@ -141,6 +160,26 @@ export default function Index() {
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
|
||||
{project.verified && (
|
||||
<Input
|
||||
className={"sm:col-span-3"}
|
||||
label={"Sender Email"}
|
||||
placeholder={`${project.email}`}
|
||||
register={register("email")}
|
||||
error={errors.email}
|
||||
/>
|
||||
)}
|
||||
|
||||
{project.verified && (
|
||||
<Input
|
||||
className={"sm:col-span-3"}
|
||||
label={"Sender Name"}
|
||||
placeholder={`${project.name}`}
|
||||
register={register("from")}
|
||||
error={errors.from}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className={"sm:col-span-6"}>
|
||||
<Editor
|
||||
value={watch("body")}
|
||||
|
||||
Reference in New Issue
Block a user