diff --git a/apps/web/src/app/(dashboard)/domains/[domainId]/delete-domain.tsx b/apps/web/src/app/(dashboard)/domains/[domainId]/delete-domain.tsx index 0886be7..31acd3d 100644 --- a/apps/web/src/app/(dashboard)/domains/[domainId]/delete-domain.tsx +++ b/apps/web/src/app/(dashboard)/domains/[domainId]/delete-domain.tsx @@ -12,22 +12,51 @@ import { DialogTitle, DialogTrigger, } from "@unsend/ui/src/dialog"; + +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@unsend/ui/src/form"; + import { api } from "~/trpc/react"; import React, { useState } from "react"; import { Domain } from "@prisma/client"; import { useRouter } from "next/navigation"; import { toast } from "@unsend/ui/src/toaster"; +import { z } from "zod"; +import { useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; + +const domainSchema = z.object({ + domain: z.string(), +}); export const DeleteDomain: React.FC<{ domain: Domain }> = ({ domain }) => { const [open, setOpen] = useState(false); const [domainName, setDomainName] = useState(""); const deleteDomainMutation = api.domain.deleteDomain.useMutation(); + const domainForm = useForm>({ + resolver: zodResolver(domainSchema), + }); + const utils = api.useUtils(); const router = useRouter(); - function handleSave() { + async function onDomainDelete(values: z.infer) { + if (values.domain !== domain.name) { + domainForm.setError("domain", { + message: "Domain name does not match", + }); + return; + } + deleteDomainMutation.mutate( { id: domain.id, @@ -62,30 +91,41 @@ export const DeleteDomain: React.FC<{ domain: Domain }> = ({ domain }) => { You can't reverse this. -
- - setDomainName(e.target.value)} - value={domainName} - /> -
- - - + ( + + Domain + + + + {formState.errors.domain ? ( + + ) : ( + + . + + )} + + )} + /> +
+ +
+ + ); diff --git a/apps/web/src/app/(dashboard)/domains/add-domain.tsx b/apps/web/src/app/(dashboard)/domains/add-domain.tsx index ee9c5ab..22b4ea8 100644 --- a/apps/web/src/app/(dashboard)/domains/add-domain.tsx +++ b/apps/web/src/app/(dashboard)/domains/add-domain.tsx @@ -2,34 +2,60 @@ import { Button } from "@unsend/ui/src/button"; import { Input } from "@unsend/ui/src/input"; -import { Label } from "@unsend/ui/src/label"; import { Dialog, DialogContent, - DialogDescription, - DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@unsend/ui/src/dialog"; +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@unsend/ui/src/form"; import { api } from "~/trpc/react"; import { useState } from "react"; import { Plus } from "lucide-react"; import { useRouter } from "next/navigation"; +import * as tldts from "tldts"; +import { z } from "zod"; +import { useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; + +const domainSchema = z.object({ + domain: z.string({ required_error: "Domain is required" }), +}); export default function AddDomain() { const [open, setOpen] = useState(false); - const [domainName, setDomainName] = useState(""); const addDomainMutation = api.domain.createDomain.useMutation(); + const domainForm = useForm>({ + resolver: zodResolver(domainSchema), + }); + const utils = api.useUtils(); const router = useRouter(); - function handleSave() { + async function onDomainAdd(values: z.infer) { + const domain = tldts.getDomain(values.domain); + if (!domain) { + domainForm.setError("domain", { + message: "Invalid domain", + }); + + return; + } + addDomainMutation.mutate( { - name: domainName, + name: values.domain, }, { onSuccess: async (data) => { @@ -55,30 +81,45 @@ export default function AddDomain() { Add a new domain - This creates a new domain
- - setDomainName(e.target.value)} - value={domainName} - /> +
+ + ( + + Domain + + + + {formState.errors.domain ? ( + + ) : ( + + Use subdomains to separate transactional and marketing + emails.{" "} + + )} + + )} + /> +
+ +
+ +
- - -
); diff --git a/apps/web/src/server/service/domain-service.ts b/apps/web/src/server/service/domain-service.ts index 8419b17..8a41d84 100644 --- a/apps/web/src/server/service/domain-service.ts +++ b/apps/web/src/server/service/domain-service.ts @@ -7,6 +7,12 @@ import { db } from "~/server/db"; const dnsResolveTxt = util.promisify(dns.resolveTxt); export async function createDomain(teamId: number, name: string) { + const domainStr = tldts.getDomain(name); + + if (!domainStr) { + throw new Error("Invalid domain"); + } + const subdomain = tldts.getSubdomain(name); const publicKey = await ses.addDomain(name);