rebrand to useSend (#210)
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
|
||||
import { Plus } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
|
@@ -1,13 +1,13 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
|
||||
import { Edit } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
@@ -20,13 +20,13 @@ import {
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@unsend/ui/src/form";
|
||||
} from "@usesend/ui/src/form";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { z } from "zod";
|
||||
import { api } from "~/trpc/react";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import Spinner from "@unsend/ui/src/spinner";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import Spinner from "@usesend/ui/src/spinner";
|
||||
import { SesSetting } from "@prisma/client";
|
||||
|
||||
const FormSchema = z.object({
|
||||
|
@@ -2,12 +2,13 @@
|
||||
|
||||
import AddSesConfiguration from "./add-ses-configuration";
|
||||
import SesConfigurations from "./ses-configurations";
|
||||
import { H1 } from "@usesend/ui";
|
||||
|
||||
export default function ApiKeysPage() {
|
||||
return (
|
||||
<div>
|
||||
<div className="flex justify-between items-center">
|
||||
<h1 className="font-bold text-lg">Admin</h1>
|
||||
<H1>Admin</H1>
|
||||
<AddSesConfiguration />
|
||||
</div>
|
||||
<div className="mt-10">
|
||||
|
@@ -7,12 +7,12 @@ import {
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@unsend/ui/src/table";
|
||||
} from "@usesend/ui/src/table";
|
||||
import { formatDistanceToNow } from "date-fns";
|
||||
import { api } from "~/trpc/react";
|
||||
import Spinner from "@unsend/ui/src/spinner";
|
||||
import Spinner from "@usesend/ui/src/spinner";
|
||||
import EditSesConfiguration from "./edit-ses-configuration";
|
||||
import { TextWithCopyButton } from "@unsend/ui/src/text-with-copy";
|
||||
import { TextWithCopyButton } from "@usesend/ui/src/text-with-copy";
|
||||
|
||||
export default function SesConfigurations() {
|
||||
const sesSettingsQuery = api.admin.getSesSettings.useQuery();
|
||||
|
@@ -1,10 +1,10 @@
|
||||
"use client";
|
||||
|
||||
import { api } from "~/trpc/react";
|
||||
import { Spinner } from "@unsend/ui/src/spinner";
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
import { Editor } from "@unsend/email-editor";
|
||||
import { Spinner } from "@usesend/ui/src/spinner";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import { Editor } from "@usesend/email-editor";
|
||||
import { use, useState } from "react";
|
||||
import { Campaign } from "@prisma/client";
|
||||
import {
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
} from "@unsend/ui/src/select";
|
||||
} from "@usesend/ui/src/select";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
import { z } from "zod";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
@@ -31,8 +31,8 @@ import {
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@unsend/ui/src/form";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
} from "@usesend/ui/src/form";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import { useDebouncedCallback } from "use-debounce";
|
||||
import { formatDistanceToNow } from "date-fns";
|
||||
import {
|
||||
@@ -40,7 +40,7 @@ import {
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "@unsend/ui/src/accordion";
|
||||
} from "@usesend/ui/src/accordion";
|
||||
|
||||
const sendSchema = z.object({
|
||||
confirmation: z.string(),
|
||||
@@ -63,7 +63,7 @@ export default function EditCampaignPage({
|
||||
{ campaignId },
|
||||
{
|
||||
enabled: !!campaignId,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (isLoading) {
|
||||
@@ -98,7 +98,7 @@ function CampaignEditor({
|
||||
const utils = api.useUtils();
|
||||
|
||||
const [json, setJson] = useState<Record<string, any> | undefined>(
|
||||
campaign.content ? JSON.parse(campaign.content) : undefined
|
||||
campaign.content ? JSON.parse(campaign.content) : undefined,
|
||||
);
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
const [name, setName] = useState(campaign.name);
|
||||
@@ -106,10 +106,10 @@ function CampaignEditor({
|
||||
const [from, setFrom] = useState(campaign.from);
|
||||
const [contactBookId, setContactBookId] = useState(campaign.contactBookId);
|
||||
const [replyTo, setReplyTo] = useState<string | undefined>(
|
||||
campaign.replyTo[0]
|
||||
campaign.replyTo[0],
|
||||
);
|
||||
const [previewText, setPreviewText] = useState<string | null>(
|
||||
campaign.previewText
|
||||
campaign.previewText,
|
||||
);
|
||||
const [openSendDialog, setOpenSendDialog] = useState(false);
|
||||
|
||||
@@ -135,7 +135,7 @@ function CampaignEditor({
|
||||
|
||||
const deboucedUpdateCampaign = useDebouncedCallback(
|
||||
updateEditorContent,
|
||||
1000
|
||||
1000,
|
||||
);
|
||||
|
||||
async function onSendCampaign(values: z.infer<typeof sendSchema>) {
|
||||
@@ -160,14 +160,14 @@ function CampaignEditor({
|
||||
onError: (error) => {
|
||||
toast.error(`Failed to send campaign: ${error.message}`);
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
const handleFileChange = async (file: File) => {
|
||||
if (file.size > IMAGE_SIZE_LIMIT) {
|
||||
throw new Error(
|
||||
`File should be less than ${IMAGE_SIZE_LIMIT / 1024 / 1024}MB`
|
||||
`File should be less than ${IMAGE_SIZE_LIMIT / 1024 / 1024}MB`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ function CampaignEditor({
|
||||
const confirmation = sendForm.watch("confirmation");
|
||||
|
||||
const contactBook = contactBooksQuery.data?.find(
|
||||
(book) => book.id === contactBookId
|
||||
(book) => book.id === contactBookId,
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -220,7 +220,7 @@ function CampaignEditor({
|
||||
toast.error(`${e.message}. Reverting changes.`);
|
||||
setName(campaign.name);
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
}}
|
||||
/>
|
||||
@@ -315,7 +315,7 @@ function CampaignEditor({
|
||||
toast.error(`${e.message}. Reverting changes.`);
|
||||
setSubject(campaign.subject);
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
}}
|
||||
className="mt-1 py-1 text-sm block w-full outline-none border-b border-transparent focus:border-border bg-transparent"
|
||||
@@ -350,7 +350,7 @@ function CampaignEditor({
|
||||
toast.error(`${e.message}. Reverting changes.`);
|
||||
setFrom(campaign.from);
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
}}
|
||||
/>
|
||||
@@ -381,7 +381,7 @@ function CampaignEditor({
|
||||
toast.error(`${e.message}. Reverting changes.`);
|
||||
setReplyTo(campaign.replyTo[0]);
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
}}
|
||||
/>
|
||||
@@ -414,7 +414,7 @@ function CampaignEditor({
|
||||
toast.error(`${e.message}. Reverting changes.`);
|
||||
setPreviewText(campaign.previewText ?? "");
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
}}
|
||||
className="mt-1 py-1 text-sm block w-full outline-none border-b border-transparent bg-transparent focus:border-border"
|
||||
@@ -440,7 +440,7 @@ function CampaignEditor({
|
||||
onError: () => {
|
||||
setContactBookId(campaign.contactBookId);
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
setContactBookId(val);
|
||||
}}
|
||||
|
@@ -7,10 +7,11 @@ import {
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from "@unsend/ui/src/breadcrumb";
|
||||
} from "@usesend/ui/src/breadcrumb";
|
||||
import Link from "next/link";
|
||||
import { H2 } from "@usesend/ui";
|
||||
|
||||
import Spinner from "@unsend/ui/src/spinner";
|
||||
import Spinner from "@usesend/ui/src/spinner";
|
||||
import { api } from "~/trpc/react";
|
||||
import { use } from "react";
|
||||
|
||||
@@ -80,7 +81,7 @@ export default function CampaignDetailsPage({
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
<div className="mt-10">
|
||||
<h2 className="text-xl font-semibold mb-4"> Statistics</h2>
|
||||
<H2 className="mb-4"> Statistics</H2>
|
||||
<div className="flex gap-4">
|
||||
{statusCards.map((card) => (
|
||||
<div
|
||||
@@ -110,7 +111,7 @@ export default function CampaignDetailsPage({
|
||||
|
||||
{campaign.html && (
|
||||
<div className=" rounded-lg mt-16">
|
||||
<h2 className="text-xl font-semibold mb-4">Email</h2>
|
||||
<H2 className="mb-4">Email</H2>
|
||||
|
||||
<div className="p-2 rounded-lg border shadow flex flex-col gap-4 w-full">
|
||||
<div className="flex flex-col gap-3 px-4 py-1">
|
||||
|
@@ -7,11 +7,11 @@ import {
|
||||
TableHead,
|
||||
TableBody,
|
||||
TableCell,
|
||||
} from "@unsend/ui/src/table";
|
||||
} from "@usesend/ui/src/table";
|
||||
import { api } from "~/trpc/react";
|
||||
import { useUrlState } from "~/hooks/useUrlState";
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import Spinner from "@unsend/ui/src/spinner";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import Spinner from "@usesend/ui/src/spinner";
|
||||
import { formatDistanceToNow } from "date-fns";
|
||||
import { CampaignStatus } from "@prisma/client";
|
||||
import DeleteCampaign from "./delete-campaign";
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
SelectTrigger,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
} from "@unsend/ui/src/select";
|
||||
} from "@usesend/ui/src/select";
|
||||
|
||||
export default function CampaignList() {
|
||||
const [page, setPage] = useUrlState("page", "1");
|
||||
|
@@ -1,14 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@unsend/ui/src/form";
|
||||
} from "@usesend/ui/src/form";
|
||||
|
||||
import { api } from "~/trpc/react";
|
||||
import { useState } from "react";
|
||||
@@ -24,9 +24,9 @@ import { Plus } from "lucide-react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { z } from "zod";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Spinner from "@unsend/ui/src/spinner";
|
||||
import Spinner from "@usesend/ui/src/spinner";
|
||||
|
||||
const campaignSchema = z.object({
|
||||
name: z.string({ required_error: "Name is required" }).min(1, {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -9,10 +9,10 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
import { api } from "~/trpc/react";
|
||||
import React, { useState } from "react";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import { Trash2 } from "lucide-react";
|
||||
import { z } from "zod";
|
||||
import { useForm } from "react-hook-form";
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@unsend/ui/src/form";
|
||||
} from "@usesend/ui/src/form";
|
||||
import { Campaign } from "@prisma/client";
|
||||
|
||||
const campaignSchema = z.object({
|
||||
|
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -8,10 +8,10 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
import { api } from "~/trpc/react";
|
||||
import React, { useState } from "react";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import { Copy } from "lucide-react";
|
||||
import { Campaign } from "@prisma/client";
|
||||
|
||||
|
@@ -2,12 +2,13 @@
|
||||
|
||||
import CampaignList from "./campaign-list";
|
||||
import CreateCampaign from "./create-campaign";
|
||||
import { H1 } from "@usesend/ui";
|
||||
|
||||
export default function ContactsPage() {
|
||||
return (
|
||||
<div>
|
||||
<div className="flex justify-between items-center">
|
||||
<h1 className="font-bold text-lg">Campaigns</h1>
|
||||
<H1>Campaigns</H1>
|
||||
<CreateCampaign />
|
||||
</div>
|
||||
<CampaignList />
|
||||
|
@@ -1,14 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Textarea } from "@unsend/ui/src/textarea";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { Textarea } from "@usesend/ui/src/textarea";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@unsend/ui/src/form";
|
||||
} from "@usesend/ui/src/form";
|
||||
|
||||
import { api } from "~/trpc/react";
|
||||
import { useState } from "react";
|
||||
@@ -26,7 +26,7 @@ import { useRouter } from "next/navigation";
|
||||
import { z } from "zod";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
|
||||
const contactsSchema = z.object({
|
||||
contacts: z.string({ required_error: "Contacts are required" }).min(1, {
|
||||
|
@@ -1,13 +1,13 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
} from "@unsend/ui/src/select";
|
||||
import Spinner from "@unsend/ui/src/spinner";
|
||||
} from "@usesend/ui/src/select";
|
||||
import Spinner from "@usesend/ui/src/spinner";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@unsend/ui/src/table";
|
||||
} from "@usesend/ui/src/table";
|
||||
import { formatDistanceToNow } from "date-fns";
|
||||
import Image from "next/image";
|
||||
import { useUrlState } from "~/hooks/useUrlState";
|
||||
@@ -23,14 +23,14 @@ import { api } from "~/trpc/react";
|
||||
import { getGravatarUrl } from "~/utils/gravatar-utils";
|
||||
import DeleteContact from "./delete-contact";
|
||||
import EditContact from "./edit-contact";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import { useDebouncedCallback } from "use-debounce";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "@unsend/ui/src/tooltip";
|
||||
} from "@usesend/ui/src/tooltip";
|
||||
import { UnsubscribeReason } from "@prisma/client";
|
||||
|
||||
function getUnsubscribeReason(reason: UnsubscribeReason) {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -9,10 +9,10 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
import { api } from "~/trpc/react";
|
||||
import React, { useState } from "react";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import { Trash2 } from "lucide-react";
|
||||
import { z } from "zod";
|
||||
import { useForm } from "react-hook-form";
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@unsend/ui/src/form";
|
||||
} from "@usesend/ui/src/form";
|
||||
import { Contact } from "@prisma/client";
|
||||
|
||||
const contactSchema = z.object({
|
||||
|
@@ -1,14 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@unsend/ui/src/form";
|
||||
} from "@usesend/ui/src/form";
|
||||
|
||||
import { api } from "~/trpc/react";
|
||||
import { useState } from "react";
|
||||
@@ -26,8 +26,8 @@ import { useRouter } from "next/navigation";
|
||||
import { z } from "zod";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { Switch } from "@unsend/ui/src/switch";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import { Switch } from "@usesend/ui/src/switch";
|
||||
import { Contact } from "@prisma/client";
|
||||
|
||||
const contactSchema = z.object({
|
||||
|
@@ -8,20 +8,20 @@ import {
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from "@unsend/ui/src/breadcrumb";
|
||||
} from "@usesend/ui/src/breadcrumb";
|
||||
import Link from "next/link";
|
||||
import AddContact from "./add-contact";
|
||||
import ContactList from "./contact-list";
|
||||
import { TextWithCopyButton } from "@unsend/ui/src/text-with-copy";
|
||||
import { TextWithCopyButton } from "@usesend/ui/src/text-with-copy";
|
||||
import { formatDistanceToNow } from "date-fns";
|
||||
import EmojiPicker, { Theme } from "emoji-picker-react";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@unsend/ui/src/popover";
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { useTheme } from "@unsend/ui";
|
||||
} from "@usesend/ui/src/popover";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { useTheme } from "@usesend/ui";
|
||||
import { use } from "react";
|
||||
|
||||
export default function ContactsPage({
|
||||
@@ -51,7 +51,7 @@ export default function ContactsPage({
|
||||
...old,
|
||||
...data,
|
||||
};
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
onSettled: () => {
|
||||
|
@@ -1,19 +1,19 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
|
||||
import { api } from "~/trpc/react";
|
||||
import { useState } from "react";
|
||||
import { Plus } from "lucide-react";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import { z } from "zod";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@unsend/ui/src/form";
|
||||
} from "@usesend/ui/src/form";
|
||||
import { useUpgradeModalStore } from "~/store/upgradeModalStore";
|
||||
import { LimitReason } from "~/lib/constants/plans";
|
||||
|
||||
|
@@ -8,7 +8,7 @@ import EditContactBook from "./edit-contact-book";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { motion } from "framer-motion";
|
||||
import { useUrlState } from "~/hooks/useUrlState";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import { useDebouncedCallback } from "use-debounce";
|
||||
|
||||
export default function ContactBooksList() {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -9,10 +9,10 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
import { api } from "~/trpc/react";
|
||||
import React, { useState } from "react";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import { Trash2 } from "lucide-react";
|
||||
import { z } from "zod";
|
||||
import { useForm } from "react-hook-form";
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@unsend/ui/src/form";
|
||||
} from "@usesend/ui/src/form";
|
||||
import { ContactBook } from "@prisma/client";
|
||||
|
||||
const contactBookSchema = z.object({
|
||||
|
@@ -1,14 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
@@ -16,14 +16,14 @@ import {
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@unsend/ui/src/form";
|
||||
} from "@usesend/ui/src/form";
|
||||
import { api } from "~/trpc/react";
|
||||
import { useState } from "react";
|
||||
import { Edit } from "lucide-react";
|
||||
import { z } from "zod";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
|
||||
const contactBookSchema = z.object({
|
||||
name: z.string().min(1, { message: "Name is required" }),
|
||||
|
@@ -2,12 +2,13 @@
|
||||
|
||||
import AddContactBook from "./add-contact-book";
|
||||
import ContactBooksList from "./contact-books-list";
|
||||
import { H1 } from "@usesend/ui";
|
||||
|
||||
export default function ContactsPage() {
|
||||
return (
|
||||
<div>
|
||||
<div className="flex justify-between items-center">
|
||||
<h1 className="font-semibold text-xl">Contact books</h1>
|
||||
<H1>Contact books</H1>
|
||||
<AddContactBook />
|
||||
</div>
|
||||
<ContactBooksList />
|
||||
|
@@ -1,9 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import { AppSidebar } from "~/components/AppSideBar";
|
||||
import { SidebarInset, SidebarTrigger } from "@unsend/ui/src/sidebar";
|
||||
import { SidebarProvider } from "@unsend/ui/src/sidebar";
|
||||
import { useIsMobile } from "@unsend/ui/src/hooks/use-mobile";
|
||||
import { SidebarInset, SidebarTrigger } from "@usesend/ui/src/sidebar";
|
||||
import { SidebarProvider } from "@usesend/ui/src/sidebar";
|
||||
import { useIsMobile } from "@usesend/ui/src/hooks/use-mobile";
|
||||
import { UpgradeModal } from "~/components/payments/UpgradeModal";
|
||||
|
||||
export function DashboardLayout({ children }: { children: React.ReactNode }) {
|
||||
|
@@ -1,12 +1,12 @@
|
||||
import React from "react";
|
||||
import { Tabs, TabsList, TabsTrigger } from "@unsend/ui/src/tabs";
|
||||
import { Tabs, TabsList, TabsTrigger } from "@usesend/ui/src/tabs";
|
||||
import { useUrlState } from "~/hooks/useUrlState";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
} from "@unsend/ui/src/select";
|
||||
} from "@usesend/ui/src/select";
|
||||
import { api } from "~/trpc/react";
|
||||
|
||||
interface DashboardFiltersProps {
|
||||
|
@@ -13,8 +13,8 @@ import {
|
||||
import { EmailStatusIcon } from "../emails/email-status-badge";
|
||||
import { EmailStatus } from "@prisma/client";
|
||||
import { api } from "~/trpc/react";
|
||||
import Spinner from "@unsend/ui/src/spinner";
|
||||
import { useTheme } from "@unsend/ui";
|
||||
import Spinner from "@usesend/ui/src/spinner";
|
||||
import { useTheme } from "@usesend/ui";
|
||||
import { useColors } from "./hooks/useColors";
|
||||
|
||||
interface EmailChartProps {
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { useTheme } from "@unsend/ui";
|
||||
import { useTheme } from "@usesend/ui";
|
||||
|
||||
export function useColors() {
|
||||
const { resolvedTheme } = useTheme();
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
import EmailChart from "./email-chart";
|
||||
import DashboardFilters from "./dashboard-filters";
|
||||
import { H1 } from "@usesend/ui";
|
||||
import { useUrlState } from "~/hooks/useUrlState";
|
||||
import { ReputationMetrics } from "./reputation-metrics";
|
||||
|
||||
@@ -13,7 +14,7 @@ export default function Dashboard() {
|
||||
<div>
|
||||
<div className="w-full">
|
||||
<div className="flex justify-between items-center mb-10">
|
||||
<h1 className="font-semibold text-xl">Analytics</h1>
|
||||
<H1>Analytics</H1>
|
||||
<DashboardFilters
|
||||
days={days ?? "7"}
|
||||
setDays={setDays}
|
||||
|
@@ -3,7 +3,7 @@ import {
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "@unsend/ui/src/tooltip";
|
||||
} from "@usesend/ui/src/tooltip";
|
||||
import {
|
||||
CheckCircle2,
|
||||
CheckCircle2Icon,
|
||||
|
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -9,12 +9,12 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
|
||||
import { api } from "~/trpc/react";
|
||||
import { useState } from "react";
|
||||
import { CheckIcon, ClipboardCopy, Eye, EyeOff, Plus } from "lucide-react";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import { z } from "zod";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@unsend/ui/src/form";
|
||||
} from "@usesend/ui/src/form";
|
||||
|
||||
const apiKeySchema = z.object({
|
||||
name: z.string({ required_error: "Name is required" }).min(1, {
|
||||
|
@@ -7,11 +7,11 @@ import {
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@unsend/ui/src/table";
|
||||
} from "@usesend/ui/src/table";
|
||||
import { formatDistanceToNow } from "date-fns";
|
||||
import { api } from "~/trpc/react";
|
||||
import DeleteApiKey from "./delete-api-key";
|
||||
import Spinner from "@unsend/ui/src/spinner";
|
||||
import Spinner from "@usesend/ui/src/spinner";
|
||||
|
||||
export default function ApiList() {
|
||||
const apiKeysQuery = api.apiKey.getApiKeys.useQuery();
|
||||
|
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -9,11 +9,11 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
import { api } from "~/trpc/react";
|
||||
import React, { useState } from "react";
|
||||
import { ApiKey } from "@prisma/client";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import { Trash2 } from "lucide-react";
|
||||
import { z } from "zod";
|
||||
import { useForm } from "react-hook-form";
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@unsend/ui/src/form";
|
||||
} from "@usesend/ui/src/form";
|
||||
|
||||
const apiKeySchema = z.object({
|
||||
name: z.string(),
|
||||
|
@@ -2,12 +2,13 @@
|
||||
|
||||
import AddApiKey from "./add-api-key";
|
||||
import ApiList from "./api-list";
|
||||
import { H1 } from "@usesend/ui";
|
||||
|
||||
export default function ApiKeysPage() {
|
||||
return (
|
||||
<div>
|
||||
<div className="flex justify-between items-center">
|
||||
<h2 className="font-medium">API Keys</h2>
|
||||
<H1>API Keys</H1>
|
||||
<AddApiKey />
|
||||
</div>
|
||||
<ApiList />
|
||||
|
@@ -2,12 +2,13 @@
|
||||
|
||||
import AddApiKey from "./api-keys/add-api-key";
|
||||
import ApiList from "./api-keys/api-list";
|
||||
import { H1 } from "@usesend/ui";
|
||||
|
||||
export default function ApiKeysPage() {
|
||||
return (
|
||||
<div>
|
||||
<div className="flex justify-between items-center">
|
||||
<h2 className="font-medium">API Keys</h2>
|
||||
<H1>API Keys</H1>
|
||||
<AddApiKey />
|
||||
</div>
|
||||
<ApiList />
|
||||
|
@@ -5,8 +5,8 @@ import {
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@unsend/ui/src/card";
|
||||
import { TextWithCopyButton } from "@unsend/ui/src/text-with-copy";
|
||||
} from "@usesend/ui/src/card";
|
||||
import { TextWithCopyButton } from "@usesend/ui/src/text-with-copy";
|
||||
import { env } from "~/env";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
|
||||
import {
|
||||
Form,
|
||||
@@ -19,13 +19,13 @@ import {
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@unsend/ui/src/form";
|
||||
} from "@usesend/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 { toast } from "@usesend/ui/src/toaster";
|
||||
import { z } from "zod";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
@@ -66,7 +66,7 @@ export const DeleteDomain: React.FC<{ domain: Domain }> = ({ domain }) => {
|
||||
toast.success(`Domain ${domain.name} deleted`);
|
||||
router.replace("/domains");
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -9,7 +9,7 @@ import {
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from "@unsend/ui/src/breadcrumb";
|
||||
} from "@usesend/ui/src/breadcrumb";
|
||||
import { DomainStatusBadge } from "../domain-badge";
|
||||
import {
|
||||
Table,
|
||||
@@ -18,15 +18,16 @@ import {
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@unsend/ui/src/table";
|
||||
import { TextWithCopyButton } from "@unsend/ui/src/text-with-copy";
|
||||
} from "@usesend/ui/src/table";
|
||||
import { TextWithCopyButton } from "@usesend/ui/src/text-with-copy";
|
||||
import React, { use } from "react";
|
||||
import { Switch } from "@unsend/ui/src/switch";
|
||||
import { Switch } from "@usesend/ui/src/switch";
|
||||
import DeleteDomain from "./delete-domain";
|
||||
import SendTestMail from "./send-test-mail";
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import Link from "next/link";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import { H1 } from "@usesend/ui";
|
||||
|
||||
export default function DomainItemPage({
|
||||
params,
|
||||
@@ -42,7 +43,7 @@ export default function DomainItemPage({
|
||||
{
|
||||
refetchInterval: (q) => (q?.state.data?.isVerifying ? 10000 : false),
|
||||
refetchIntervalInBackground: true,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const verifyQuery = api.domain.startVerification.useMutation();
|
||||
@@ -54,7 +55,7 @@ export default function DomainItemPage({
|
||||
onSettled: () => {
|
||||
domainQuery.refetch();
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
@@ -67,7 +68,7 @@ export default function DomainItemPage({
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="flex items-center gap-4">
|
||||
{/* <div className="flex items-center gap-4">
|
||||
<h1 className="font-medium text-2xl">{domainQuery.data?.name}</h1>
|
||||
<H1>{domainQuery.data?.name}</H1>
|
||||
</div> */}
|
||||
<Breadcrumb>
|
||||
<BreadcrumbList>
|
||||
@@ -151,7 +152,7 @@ export default function DomainItemPage({
|
||||
<TableCell className="">TXT</TableCell>
|
||||
<TableCell>
|
||||
<TextWithCopyButton
|
||||
value={`unsend._domainkey.${domainQuery.data?.subdomain || domainQuery.data?.name}`}
|
||||
value={`${domainQuery.data?.dkimSelector ?? "unsend"}._domainkey.${domainQuery.data?.subdomain || domainQuery.data?.name}`}
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell className="">
|
||||
@@ -232,7 +233,7 @@ const DomainSettings: React.FC<{ domain: Domain }> = ({ domain }) => {
|
||||
const utils = api.useUtils();
|
||||
|
||||
const [clickTracking, setClickTracking] = React.useState(
|
||||
domain.clickTracking
|
||||
domain.clickTracking,
|
||||
);
|
||||
const [openTracking, setOpenTracking] = React.useState(domain.openTracking);
|
||||
|
||||
@@ -245,7 +246,7 @@ const DomainSettings: React.FC<{ domain: Domain }> = ({ domain }) => {
|
||||
utils.domain.invalidate();
|
||||
toast.success("Click tracking updated");
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -258,7 +259,7 @@ const DomainSettings: React.FC<{ domain: Domain }> = ({ domain }) => {
|
||||
utils.domain.invalidate();
|
||||
toast.success("Open tracking updated");
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
return (
|
||||
|
@@ -1,121 +1,17 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { api } from "~/trpc/react";
|
||||
import React, { useState } from "react";
|
||||
import React from "react";
|
||||
import { Domain } from "@prisma/client";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import { SendHorizonal } from "lucide-react";
|
||||
import { Code } from "@unsend/ui/src/code";
|
||||
import { useSession } from "next-auth/react";
|
||||
import { getSendTestEmailCode } from "~/lib/constants/example-codes";
|
||||
|
||||
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;
|
||||
}`;
|
||||
// Removed dialog and example code. Clicking the button now sends the email directly.
|
||||
|
||||
export const SendTestMail: React.FC<{ domain: Domain }> = ({ domain }) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const sendTestEmailFromDomainMutation =
|
||||
api.domain.sendTestEmailFromDomain.useMutation();
|
||||
|
||||
const { data: session } = useSession();
|
||||
|
||||
const utils = api.useUtils();
|
||||
|
||||
function handleSendTestEmail() {
|
||||
@@ -127,50 +23,24 @@ export const SendTestMail: React.FC<{ domain: Domain }> = ({ domain }) => {
|
||||
onSuccess: () => {
|
||||
utils.domain.domains.invalidate();
|
||||
toast.success(`Test email sent`);
|
||||
setOpen(false);
|
||||
},
|
||||
}
|
||||
onError: (err) => {
|
||||
toast.error(err.message || "Failed to send test email");
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={open}
|
||||
onOpenChange={(_open) => (_open !== open ? setOpen(_open) : null)}
|
||||
<Button
|
||||
onClick={handleSendTestEmail}
|
||||
disabled={sendTestEmailFromDomainMutation.isPending}
|
||||
>
|
||||
<DialogTrigger asChild>
|
||||
<Button>
|
||||
<SendHorizonal className="h-4 w-4 mr-2" />
|
||||
Send test email
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className=" max-w-2xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Send test email</DialogTitle>
|
||||
</DialogHeader>
|
||||
<Code
|
||||
codeBlocks={getSendTestEmailCode({
|
||||
from: `hello@${domain.name}`,
|
||||
to: session?.user?.email || "",
|
||||
subject: "Unsend test email",
|
||||
body: "hello,\\n\\nUnsend is the best open source sending platform",
|
||||
bodyHtml:
|
||||
"<p>hello,</p><p>Unsend is the best open source sending platform<p><p>check out <a href='https://unsend.dev'>unsend.dev</a>",
|
||||
})}
|
||||
codeClassName="max-w-[38rem] h-[20rem]"
|
||||
/>
|
||||
<div className="flex justify-end w-full">
|
||||
<Button
|
||||
onClick={handleSendTestEmail}
|
||||
disabled={sendTestEmailFromDomainMutation.isPending}
|
||||
>
|
||||
{sendTestEmailFromDomainMutation.isPending
|
||||
? "Sending email..."
|
||||
: "Send test email"}
|
||||
</Button>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
<SendHorizonal className="h-4 w-4 mr-2" />
|
||||
{sendTestEmailFromDomainMutation.isPending
|
||||
? "Sending email..."
|
||||
: "Send test email"}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
|
@@ -1,14 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
@@ -17,10 +17,10 @@ import {
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@unsend/ui/src/form";
|
||||
} from "@usesend/ui/src/form";
|
||||
|
||||
import { api } from "~/trpc/react";
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Plus } from "lucide-react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import * as tldts from "tldts";
|
||||
@@ -33,15 +33,13 @@ import {
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@unsend/ui/src/select";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
} from "@usesend/ui/src/select";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import { useUpgradeModalStore } from "~/store/upgradeModalStore";
|
||||
import { LimitReason } from "~/lib/constants/plans";
|
||||
|
||||
const domainSchema = z.object({
|
||||
region: z.string({ required_error: "Region is required" }).min(1, {
|
||||
message: "Region is required",
|
||||
}),
|
||||
region: z.string().optional(),
|
||||
domain: z.string({ required_error: "Domain is required" }).min(1, {
|
||||
message: "Domain is required",
|
||||
}),
|
||||
@@ -68,6 +66,11 @@ export default function AddDomain() {
|
||||
const utils = api.useUtils();
|
||||
const router = useRouter();
|
||||
|
||||
const singleRegion =
|
||||
regionQuery.data?.length === 1 ? regionQuery.data[0] : undefined;
|
||||
|
||||
const showRegionSelect = (regionQuery.data?.length ?? 0) > 1;
|
||||
|
||||
async function onDomainAdd(values: z.infer<typeof domainSchema>) {
|
||||
const domain = tldts.getDomain(values.domain);
|
||||
if (!domain) {
|
||||
@@ -78,6 +81,13 @@ export default function AddDomain() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!values.region && !singleRegion) {
|
||||
domainForm.setError("region", {
|
||||
message: "Region is required",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (limitsQuery.data?.isLimitReached) {
|
||||
openModal(limitsQuery.data.reason);
|
||||
return;
|
||||
@@ -86,7 +96,7 @@ export default function AddDomain() {
|
||||
addDomainMutation.mutate(
|
||||
{
|
||||
name: values.domain,
|
||||
region: values.region,
|
||||
region: singleRegion ?? values.region ?? "",
|
||||
},
|
||||
{
|
||||
onSuccess: async (data) => {
|
||||
@@ -151,40 +161,43 @@ export default function AddDomain() {
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={domainForm.control}
|
||||
name="region"
|
||||
render={({ field, formState }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Region</FormLabel>
|
||||
<Select
|
||||
onValueChange={field.onChange}
|
||||
value={field.value}
|
||||
disabled={regionQuery.isLoading}
|
||||
>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select region" />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
{regionQuery.data?.map((region) => (
|
||||
<SelectItem value={region} key={region}>
|
||||
{region}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{formState.errors.region ? (
|
||||
<FormMessage />
|
||||
) : (
|
||||
<FormDescription>
|
||||
Select the region from where the email is sent{" "}
|
||||
</FormDescription>
|
||||
)}
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
{showRegionSelect && (
|
||||
<FormField
|
||||
control={domainForm.control}
|
||||
name="region"
|
||||
render={({ field, formState }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Region</FormLabel>
|
||||
<Select
|
||||
onValueChange={field.onChange}
|
||||
value={field.value}
|
||||
disabled={regionQuery.isLoading}
|
||||
>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select region" />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
{regionQuery.data?.map((region) => (
|
||||
<SelectItem value={region} key={region}>
|
||||
{region}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{formState.errors.region ? (
|
||||
<FormMessage />
|
||||
) : (
|
||||
<FormDescription>
|
||||
Select the region from where the email is sent{" "}
|
||||
</FormDescription>
|
||||
)}
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button
|
||||
|
@@ -3,12 +3,12 @@
|
||||
import { Domain } from "@prisma/client";
|
||||
import { formatDistanceToNow } from "date-fns";
|
||||
import Link from "next/link";
|
||||
import { Switch } from "@unsend/ui/src/switch";
|
||||
import { Switch } from "@usesend/ui/src/switch";
|
||||
import { api } from "~/trpc/react";
|
||||
import React from "react";
|
||||
import { StatusIndicator } from "./status-indicator";
|
||||
import { DomainStatusBadge } from "./domain-badge";
|
||||
import Spinner from "@unsend/ui/src/spinner";
|
||||
import Spinner from "@usesend/ui/src/spinner";
|
||||
|
||||
export default function DomainsList() {
|
||||
const domainsQuery = api.domain.domains.useQuery();
|
||||
|
@@ -2,12 +2,13 @@
|
||||
|
||||
import DomainsList from "./domain-list";
|
||||
import AddDomain from "./add-domain";
|
||||
import { H1 } from "@usesend/ui";
|
||||
|
||||
export default function DomainsPage() {
|
||||
return (
|
||||
<div>
|
||||
<div className="flex justify-between items-center">
|
||||
<h1 className="font-bold text-lg">Domains</h1>
|
||||
<H1>Domains</H1>
|
||||
<AddDomain />
|
||||
</div>
|
||||
<DomainsList />
|
||||
|
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -9,10 +9,10 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
import { api } from "~/trpc/react";
|
||||
import React, { useState } from "react";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import { Trash2 } from "lucide-react";
|
||||
import { z } from "zod";
|
||||
import { useForm } from "react-hook-form";
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@unsend/ui/src/form";
|
||||
} from "@usesend/ui/src/form";
|
||||
|
||||
const cancelSchema = z.object({
|
||||
confirmation: z.string(),
|
||||
|
@@ -1,27 +1,27 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
import * as chrono from "chrono-node";
|
||||
import { api } from "~/trpc/react";
|
||||
import { useRef, useState } from "react";
|
||||
import { Edit3 } from "lucide-react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuTrigger,
|
||||
} from "@unsend/ui/src/dropdown-menu";
|
||||
} from "@usesend/ui/src/dropdown-menu";
|
||||
import {
|
||||
Command,
|
||||
CommandDialog,
|
||||
@@ -31,7 +31,7 @@ import {
|
||||
CommandItem,
|
||||
CommandList,
|
||||
CommandSeparator,
|
||||
} from "@unsend/ui/src/command";
|
||||
} from "@usesend/ui/src/command";
|
||||
|
||||
export const EditSchedule: React.FC<{
|
||||
emailId: string;
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
import { UAParser } from "ua-parser-js";
|
||||
import { api } from "~/trpc/react";
|
||||
import { Separator } from "@unsend/ui/src/separator";
|
||||
import { Separator } from "@usesend/ui/src/separator";
|
||||
import { EmailStatusBadge, EmailStatusIcon } from "./email-status-badge";
|
||||
import { formatDate } from "date-fns";
|
||||
import { motion } from "framer-motion";
|
||||
|
@@ -7,7 +7,7 @@ import {
|
||||
TableHead,
|
||||
TableBody,
|
||||
TableCell,
|
||||
} from "@unsend/ui/src/table";
|
||||
} from "@usesend/ui/src/table";
|
||||
import { api } from "~/trpc/react";
|
||||
import {
|
||||
Mail,
|
||||
@@ -23,34 +23,34 @@ import { EmailStatusBadge } from "./email-status-badge";
|
||||
import EmailDetails from "./email-details";
|
||||
import dynamic from "next/dynamic";
|
||||
import { useUrlState } from "~/hooks/useUrlState";
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
} from "@unsend/ui/src/select";
|
||||
import Spinner from "@unsend/ui/src/spinner";
|
||||
} from "@usesend/ui/src/select";
|
||||
import Spinner from "@usesend/ui/src/spinner";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "@unsend/ui/src/tooltip";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
} from "@usesend/ui/src/tooltip";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import { DEFAULT_QUERY_LIMIT } from "~/lib/constants";
|
||||
import { useDebouncedCallback } from "use-debounce";
|
||||
import { useState } from "react";
|
||||
import { SheetTitle, SheetDescription } from "@unsend/ui/src/sheet";
|
||||
import { SheetTitle, SheetDescription } from "@usesend/ui/src/sheet";
|
||||
|
||||
/* Stupid hydrating error. And I so stupid to understand the stupid NextJS docs */
|
||||
const DynamicSheetWithNoSSR = dynamic(
|
||||
() => import("@unsend/ui/src/sheet").then((mod) => mod.Sheet),
|
||||
() => import("@usesend/ui/src/sheet").then((mod) => mod.Sheet),
|
||||
{ ssr: false },
|
||||
);
|
||||
|
||||
const DynamicSheetContentWithNoSSR = dynamic(
|
||||
() => import("@unsend/ui/src/sheet").then((mod) => mod.SheetContent),
|
||||
() => import("@usesend/ui/src/sheet").then((mod) => mod.SheetContent),
|
||||
{ ssr: false },
|
||||
);
|
||||
|
||||
|
@@ -1,12 +1,13 @@
|
||||
"use client";
|
||||
|
||||
import EmailList from "./email-list";
|
||||
import { H1 } from "@usesend/ui";
|
||||
|
||||
export default function EmailsPage() {
|
||||
return (
|
||||
<div>
|
||||
<div className="flex justify-between items-center">
|
||||
<h1 className="font-semibold text-xl">Emails</h1>
|
||||
<H1>Emails</H1>
|
||||
</div>
|
||||
<EmailList />
|
||||
</div>
|
||||
|
@@ -1,11 +1,12 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import Spinner from "@unsend/ui/src/spinner";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import Spinner from "@usesend/ui/src/spinner";
|
||||
import { CheckCircle2 } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import { api } from "~/trpc/react";
|
||||
import { H1 } from "@usesend/ui";
|
||||
|
||||
export default function PaymentsPage() {
|
||||
const searchParams = useSearchParams();
|
||||
@@ -15,9 +16,7 @@ export default function PaymentsPage() {
|
||||
|
||||
return (
|
||||
<div className="container mx-auto py-10">
|
||||
<h1 className="text-2xl font-semibold mb-8">
|
||||
Payment {success ? "Success" : canceled ? "Canceled" : "Unknown"}
|
||||
</h1>
|
||||
<H1>Payment {success ? "Success" : canceled ? "Canceled" : "Unknown"}</H1>
|
||||
{canceled ? (
|
||||
<Link href="/settings/billing">
|
||||
<Button>Go to billing</Button>
|
||||
|
@@ -1,9 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Card } from "@unsend/ui/src/card";
|
||||
import { Spinner } from "@unsend/ui/src/spinner";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { Card } from "@usesend/ui/src/card";
|
||||
import { Spinner } from "@usesend/ui/src/spinner";
|
||||
import { format } from "date-fns";
|
||||
import { useTeam } from "~/providers/team-context";
|
||||
import { api } from "~/trpc/react";
|
||||
|
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -8,10 +8,10 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
import { api } from "~/trpc/react";
|
||||
import { useState } from "react";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import { Trash2 } from "lucide-react";
|
||||
|
||||
export const DeleteTeamInvite: React.FC<{
|
||||
|
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -8,10 +8,10 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
import { api } from "~/trpc/react";
|
||||
import { useState } from "react";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import { Role } from "@prisma/client";
|
||||
import { LogOut, Trash2 } from "lucide-react";
|
||||
|
||||
|
@@ -1,13 +1,13 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@unsend/ui/src/form";
|
||||
} from "@usesend/ui/src/form";
|
||||
|
||||
import { api } from "~/trpc/react";
|
||||
import { useState } from "react";
|
||||
@@ -23,7 +23,7 @@ import { PencilIcon } from "lucide-react";
|
||||
import { z } from "zod";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import { Role } from "@prisma/client";
|
||||
import {
|
||||
Select,
|
||||
@@ -31,7 +31,7 @@ import {
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@unsend/ui/src/select";
|
||||
} from "@usesend/ui/src/select";
|
||||
|
||||
const teamUserSchema = z.object({
|
||||
role: z.enum(["MEMBER", "ADMIN"]),
|
||||
|
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
import {
|
||||
Dialog,
|
||||
@@ -9,18 +9,18 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@unsend/ui/src/select";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
} from "@usesend/ui/src/select";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { api } from "~/trpc/react";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import { z } from "zod";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import {
|
||||
@@ -31,7 +31,7 @@ import {
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@unsend/ui/src/form";
|
||||
} from "@usesend/ui/src/form";
|
||||
import { useTeam } from "~/providers/team-context";
|
||||
import { isCloud, isSelfHosted } from "~/utils/common";
|
||||
import { useUpgradeModalStore } from "~/store/upgradeModalStore";
|
||||
|
@@ -1,15 +1,15 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { api } from "~/trpc/react";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import { Copy, RotateCw } from "lucide-react";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "@unsend/ui/src/tooltip";
|
||||
} from "@usesend/ui/src/tooltip";
|
||||
import { isSelfHosted } from "~/utils/common";
|
||||
|
||||
export const ResendTeamInvite: React.FC<{
|
||||
|
@@ -7,10 +7,10 @@ import {
|
||||
TableHead,
|
||||
TableBody,
|
||||
TableCell,
|
||||
} from "@unsend/ui/src/table";
|
||||
} from "@usesend/ui/src/table";
|
||||
import { api } from "~/trpc/react";
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import Spinner from "@unsend/ui/src/spinner";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import Spinner from "@usesend/ui/src/spinner";
|
||||
import { formatDistanceToNow } from "date-fns";
|
||||
import { Role } from "@prisma/client";
|
||||
import { EditTeamMember } from "./edit-team-member";
|
||||
|
@@ -1,8 +1,8 @@
|
||||
"use client";
|
||||
|
||||
import { api } from "~/trpc/react";
|
||||
import { Card } from "@unsend/ui/src/card";
|
||||
import Spinner from "@unsend/ui/src/spinner";
|
||||
import { Card } from "@usesend/ui/src/card";
|
||||
import Spinner from "@usesend/ui/src/spinner";
|
||||
import { format } from "date-fns";
|
||||
import {
|
||||
getCost,
|
||||
@@ -14,7 +14,7 @@ import { useTeam } from "~/providers/team-context";
|
||||
import { EmailUsageType } from "@prisma/client";
|
||||
import { PlanDetails } from "~/components/payments/PlanDetails";
|
||||
import { UpgradeButton } from "~/components/payments/UpgradeButton";
|
||||
import { Progress } from "@unsend/ui/src/progress";
|
||||
import { Progress } from "@usesend/ui/src/progress";
|
||||
|
||||
const FREE_PLAN_LIMIT = 3000;
|
||||
|
||||
@@ -49,7 +49,7 @@ function FreePlanUsage({
|
||||
<div className="text-sm text-muted-foreground mt-1">
|
||||
{item.type === "TRANSACTIONAL"
|
||||
? "Mails sent using the send api or SMTP"
|
||||
: "Mails designed sent from unsend editor"}
|
||||
: "Mails designed sent from useSend editor"}
|
||||
</div>
|
||||
</div>
|
||||
<div className="font-mono font-medium">
|
||||
|
@@ -10,17 +10,17 @@ import {
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
import { Label } from "@unsend/ui/src/label";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import { Label } from "@usesend/ui/src/label";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@unsend/ui/src/select";
|
||||
} from "@usesend/ui/src/select";
|
||||
|
||||
interface AddSuppressionDialogProps {
|
||||
open: boolean;
|
||||
|
@@ -10,18 +10,18 @@ import {
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Label } from "@unsend/ui/src/label";
|
||||
import { Textarea } from "@unsend/ui/src/textarea";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { Label } from "@usesend/ui/src/label";
|
||||
import { Textarea } from "@usesend/ui/src/textarea";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@unsend/ui/src/select";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@unsend/ui/src/tabs";
|
||||
} from "@usesend/ui/src/select";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@usesend/ui/src/tabs";
|
||||
import { Upload, FileText } from "lucide-react";
|
||||
|
||||
interface BulkAddSuppressionsDialogProps {
|
||||
|
@@ -5,8 +5,9 @@ import AddSuppressionDialog from "./add-suppression";
|
||||
import BulkAddSuppressionsDialog from "./bulk-add-suppressions";
|
||||
import SuppressionList from "./suppression-list";
|
||||
import SuppressionStats from "./suppression-stats";
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { Plus, Upload } from "lucide-react";
|
||||
import { H1 } from "@usesend/ui";
|
||||
|
||||
export default function SuppressionsPage() {
|
||||
const [showAddDialog, setShowAddDialog] = useState(false);
|
||||
@@ -16,7 +17,7 @@ export default function SuppressionsPage() {
|
||||
<div>
|
||||
{/* Header */}
|
||||
<div className="flex justify-between items-center mb-10">
|
||||
<h1 className="font-bold text-lg">Suppression List</h1>
|
||||
<H1>Suppression List</H1>
|
||||
<div className="flex gap-2">
|
||||
<Button variant="outline" onClick={() => setShowBulkAddDialog(true)}>
|
||||
<Upload className="h-4 w-4 mr-2" />
|
||||
|
@@ -7,8 +7,8 @@ import {
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
|
||||
interface RemoveSuppressionDialogProps {
|
||||
email: string | null;
|
||||
|
@@ -6,15 +6,15 @@ import { useUrlState } from "~/hooks/useUrlState";
|
||||
import { useDebouncedCallback } from "use-debounce";
|
||||
import { SuppressionReason } from "@prisma/client";
|
||||
import { formatDistanceToNow } from "date-fns";
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@unsend/ui/src/select";
|
||||
} from "@usesend/ui/src/select";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -22,10 +22,10 @@ import {
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@unsend/ui/src/table";
|
||||
} from "@usesend/ui/src/table";
|
||||
import { Trash2, Download } from "lucide-react";
|
||||
import RemoveSuppressionDialog from "./remove-suppression";
|
||||
import Spinner from "@unsend/ui/src/spinner";
|
||||
import Spinner from "@usesend/ui/src/spinner";
|
||||
|
||||
const reasonLabels = {
|
||||
HARD_BOUNCE: "Hard Bounce",
|
||||
|
@@ -1,12 +1,12 @@
|
||||
"use client";
|
||||
|
||||
import { api } from "~/trpc/react";
|
||||
import { Spinner } from "@unsend/ui/src/spinner";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
import { Editor } from "@unsend/email-editor";
|
||||
import { Spinner } from "@usesend/ui/src/spinner";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import { Editor } from "@usesend/email-editor";
|
||||
import { useState } from "react";
|
||||
import { Template } from "@prisma/client";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import { useDebouncedCallback } from "use-debounce";
|
||||
import { formatDistanceToNow } from "date-fns";
|
||||
import { ArrowLeft } from "lucide-react";
|
||||
|
@@ -1,14 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@unsend/ui/src/form";
|
||||
} from "@usesend/ui/src/form";
|
||||
|
||||
import { api } from "~/trpc/react";
|
||||
import { useState } from "react";
|
||||
@@ -24,9 +24,9 @@ import { Plus } from "lucide-react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { z } from "zod";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Spinner from "@unsend/ui/src/spinner";
|
||||
import Spinner from "@usesend/ui/src/spinner";
|
||||
|
||||
const templateSchema = z.object({
|
||||
name: z.string({ required_error: "Name is required" }).min(1, {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Input } from "@unsend/ui/src/input";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import { Input } from "@usesend/ui/src/input";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -9,10 +9,10 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
import { api } from "~/trpc/react";
|
||||
import React, { useState } from "react";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import { Trash2 } from "lucide-react";
|
||||
import { z } from "zod";
|
||||
import { useForm } from "react-hook-form";
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@unsend/ui/src/form";
|
||||
} from "@usesend/ui/src/form";
|
||||
import { Template } from "@prisma/client";
|
||||
|
||||
const templateSchema = z.object({
|
||||
|
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -8,10 +8,10 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@unsend/ui/src/dialog";
|
||||
} from "@usesend/ui/src/dialog";
|
||||
import { api } from "~/trpc/react";
|
||||
import React, { useState } from "react";
|
||||
import { toast } from "@unsend/ui/src/toaster";
|
||||
import { toast } from "@usesend/ui/src/toaster";
|
||||
import { Copy } from "lucide-react";
|
||||
import { Template } from "@prisma/client";
|
||||
|
||||
|
@@ -2,12 +2,13 @@
|
||||
|
||||
import TemplateList from "./template-list";
|
||||
import CreateTemplate from "./create-template";
|
||||
import { H1 } from "@usesend/ui";
|
||||
|
||||
export default function TemplatesPage() {
|
||||
return (
|
||||
<div>
|
||||
<div className="flex justify-between items-center">
|
||||
<h1 className="font-bold text-lg">Templates</h1>
|
||||
<H1>Templates</H1>
|
||||
<CreateTemplate />
|
||||
</div>
|
||||
<TemplateList />
|
||||
|
@@ -7,17 +7,17 @@ import {
|
||||
TableHead,
|
||||
TableBody,
|
||||
TableCell,
|
||||
} from "@unsend/ui/src/table";
|
||||
} from "@usesend/ui/src/table";
|
||||
import { api } from "~/trpc/react";
|
||||
import { useUrlState } from "~/hooks/useUrlState";
|
||||
import { Button } from "@unsend/ui/src/button";
|
||||
import Spinner from "@unsend/ui/src/spinner";
|
||||
import { Button } from "@usesend/ui/src/button";
|
||||
import Spinner from "@usesend/ui/src/spinner";
|
||||
import { formatDistanceToNow } from "date-fns";
|
||||
// import DeleteCampaign from "./delete-campaign";
|
||||
import Link from "next/link";
|
||||
// import DuplicateCampaign from "./duplicate-campaign";
|
||||
|
||||
import { TextWithCopyButton } from "@unsend/ui/src/text-with-copy";
|
||||
import { TextWithCopyButton } from "@usesend/ui/src/text-with-copy";
|
||||
import DeleteTemplate from "./delete-template";
|
||||
import DuplicateTemplate from "./duplicate-template";
|
||||
|
||||
|
Reference in New Issue
Block a user