Update domain page UI
This commit is contained in:
@@ -290,8 +290,7 @@ const DomainSettings: React.FC<{ domain: Domain }> = ({ domain }) => {
|
||||
<p className="font-semibold text-xl mt-2 text-destructive">Danger</p>
|
||||
|
||||
<p className="text-destructive text-sm font-semibold">
|
||||
Deleting a domain will remove all of its DNS records and stop sending
|
||||
emails.
|
||||
Deleting a domain will stop sending emails with this domain.
|
||||
</p>
|
||||
<DeleteDomain domain={domain} />
|
||||
</div>
|
||||
|
@@ -1,8 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
import { Label } from "@unsend/ui/src/label";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -18,27 +16,120 @@ import { Domain } from "@prisma/client";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { Send, SendHorizonal } from "lucide-react";
|
||||
import { Code } from "@unsend/ui/src/code";
|
||||
|
||||
const jsCode = `const requestOptions = {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer us_ad9a79256e366399c747cbf0b38eca3c472e8a2e"
|
||||
},
|
||||
body: JSON.stringify({
|
||||
"to": "koushikmohan1996@gmail.com",
|
||||
"from": "hello@test.splitpro.app",
|
||||
"subject": "Test mail",
|
||||
"html": "<p>Hello this is a test mail</p>"
|
||||
}),
|
||||
redirect: "follow"
|
||||
};
|
||||
|
||||
fetch("http://localhost:3000/api/v1/emails", requestOptions)
|
||||
.then(response => response.text())
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(error));
|
||||
`;
|
||||
|
||||
const pythonCode = `import requests
|
||||
import json
|
||||
|
||||
url = "http://localhost:3000/api/v1/emails"
|
||||
|
||||
payload = json.dumps({
|
||||
"to": "koushikmohan1996@gmail.com",
|
||||
"from": "hello@test.splitpro.app",
|
||||
"subject": "Test mail",
|
||||
"html": "<p>Hello this is a test mail</p>"
|
||||
})
|
||||
headers = {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer us_ad9a79256e366399c747cbf0b38eca3c472e8a2e'
|
||||
}
|
||||
|
||||
response = requests.request("POST", url, headers=headers, data=payload)
|
||||
|
||||
print(response.text)`;
|
||||
|
||||
const rubyCode = `require 'uri'
|
||||
require 'net/http'
|
||||
require 'json'
|
||||
|
||||
url = URI("http://localhost:3000/api/v1/emails")
|
||||
|
||||
http = Net::HTTP.new(url.host, url.port)
|
||||
request = Net::HTTP::Post.new(url)
|
||||
request["Accept"] = 'application/json'
|
||||
request["Content-Type"] = 'application/json'
|
||||
request["Authorization"] = 'Bearer us_ad9a79256e366399c747cbf0b38eca3c472e8a2e'
|
||||
request.body = JSON.dump({
|
||||
"to" => "koushikmohan1996@gmail.com",
|
||||
"from" => "hello@test.splitpro.app",
|
||||
"subject" => "Test mail",
|
||||
"html" => "<p>Hello this is a test mail</p>"
|
||||
})
|
||||
|
||||
response = http.request(request)
|
||||
puts response.read_body`;
|
||||
|
||||
const phpCode = `$url = "http://localhost:3000/api/v1/emails";
|
||||
|
||||
$payload = json_encode(array(
|
||||
"to" => "koushikmohan1996@gmail.com",
|
||||
"from" => "hello@test.splitpro.app",
|
||||
"subject" => "Test mail",
|
||||
"html" => "<p>Hello this is a test mail</p>"
|
||||
));
|
||||
|
||||
$headers = array(
|
||||
"Accept: application/json",
|
||||
"Content-Type: application/json",
|
||||
"Authorization: Bearer us_ad9a79256e366399c747cbf0b38eca3c472e8a2e"
|
||||
);
|
||||
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
if (curl_errno($ch)) {
|
||||
echo 'Error:' . curl_error($ch);
|
||||
} else {
|
||||
echo $response;
|
||||
}`;
|
||||
|
||||
export const SendTestMail: React.FC<{ domain: Domain }> = ({ domain }) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [domainName, setDomainName] = useState("");
|
||||
const deleteDomainMutation = api.domain.deleteDomain.useMutation();
|
||||
const sendTestEmailFromDomainMutation =
|
||||
api.domain.sendTestEmailFromDomain.useMutation();
|
||||
|
||||
const utils = api.useUtils();
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
function handleSave() {
|
||||
deleteDomainMutation.mutate(
|
||||
function handleSendTestEmail() {
|
||||
sendTestEmailFromDomainMutation.mutate(
|
||||
{
|
||||
id: domain.id,
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
utils.domain.domains.invalidate();
|
||||
toast.success(`Test email sent`);
|
||||
setOpen(false);
|
||||
toast.success(`Domain ${domain.name} deleted`);
|
||||
router.replace("/domains");
|
||||
},
|
||||
}
|
||||
);
|
||||
@@ -55,10 +146,28 @@ export const SendTestMail: React.FC<{ domain: Domain }> = ({ domain }) => {
|
||||
Send test email
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogContent className=" max-w-2xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Send test email</DialogTitle>
|
||||
</DialogHeader>
|
||||
<Code
|
||||
codeBlocks={[
|
||||
{ language: "js", code: jsCode },
|
||||
{ language: "ruby", code: rubyCode },
|
||||
{ language: "php", code: phpCode },
|
||||
{ language: "python", code: pythonCode },
|
||||
]}
|
||||
/>
|
||||
<div className="flex justify-end w-full">
|
||||
<Button
|
||||
onClick={handleSendTestEmail}
|
||||
disabled={sendTestEmailFromDomainMutation.isPending}
|
||||
>
|
||||
{sendTestEmailFromDomainMutation.isPending
|
||||
? "Sending email..."
|
||||
: "Send test email"}
|
||||
</Button>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
|
@@ -13,6 +13,7 @@ import {
|
||||
getDomain,
|
||||
updateDomain,
|
||||
} from "~/server/service/domain-service";
|
||||
import { sendEmail } from "~/server/service/email-service";
|
||||
|
||||
export const domainRouter = createTRPCRouter({
|
||||
createDomain: teamProcedure
|
||||
@@ -61,4 +62,37 @@ export const domainRouter = createTRPCRouter({
|
||||
await deleteDomain(input.id);
|
||||
return { success: true };
|
||||
}),
|
||||
|
||||
sendTestEmailFromDomain: teamProcedure
|
||||
.input(z.object({ id: z.number() }))
|
||||
.mutation(
|
||||
async ({
|
||||
ctx: {
|
||||
session: { user },
|
||||
team,
|
||||
},
|
||||
input,
|
||||
}) => {
|
||||
const domain = await db.domain.findFirst({
|
||||
where: { id: input.id, teamId: team.id },
|
||||
});
|
||||
|
||||
if (!domain) {
|
||||
throw new Error("Domain not found");
|
||||
}
|
||||
|
||||
if (!user.email) {
|
||||
throw new Error("User email not found");
|
||||
}
|
||||
|
||||
return sendEmail({
|
||||
teamId: team.id,
|
||||
to: user.email,
|
||||
from: `hello@${domain.name}`,
|
||||
subject: "Test mail",
|
||||
text: "Hello this is a test mail",
|
||||
html: "<p>Hello this is a test mail</p>",
|
||||
});
|
||||
}
|
||||
),
|
||||
});
|
||||
|
@@ -8,16 +8,16 @@ export async function sendEmail(
|
||||
) {
|
||||
const { to, from, subject, text, html, teamId } = emailContent;
|
||||
|
||||
const domains = await db.domain.findMany({ where: { teamId } });
|
||||
|
||||
const fromDomain = from.split("@")[1];
|
||||
if (!fromDomain) {
|
||||
throw new Error("From email is not valid");
|
||||
}
|
||||
|
||||
const domain = domains.find((domain) => domain.name === fromDomain);
|
||||
const domain = await db.domain.findFirst({
|
||||
where: { teamId, name: fromDomain },
|
||||
});
|
||||
|
||||
if (!domain) {
|
||||
throw new Error("Domain not found. Add domain to unsend first");
|
||||
throw new Error(
|
||||
"Domain of from email is wrong. Use the email verified by unsend"
|
||||
);
|
||||
}
|
||||
|
||||
if (domain.status !== "SUCCESS") {
|
||||
|
Reference in New Issue
Block a user