diff --git a/apps/web/src/app/(dashboard)/domains/domain-list.tsx b/apps/web/src/app/(dashboard)/domains/domain-list.tsx
index 24884f8..3552199 100644
--- a/apps/web/src/app/(dashboard)/domains/domain-list.tsx
+++ b/apps/web/src/app/(dashboard)/domains/domain-list.tsx
@@ -1,10 +1,11 @@
"use client";
-import { DomainStatus } from "@prisma/client";
+import { Domain, DomainStatus } from "@prisma/client";
import { formatDistanceToNow } from "date-fns";
import Link from "next/link";
import { Switch } from "@unsend/ui/src/switch";
import { api } from "~/trpc/react";
+import React from "react";
export default function DomainsList() {
const domainsQuery = api.domain.domains.useQuery();
@@ -14,51 +15,7 @@ export default function DomainsList() {
{!domainsQuery.isLoading && domainsQuery.data?.length ? (
domainsQuery.data?.map((domain) => (
-
-
-
-
-
-
- {domain.name}
-
-
-
-
-
-
- Created at
-
-
- {formatDistanceToNow(new Date(domain.createdAt), {
- addSuffix: true,
- })}
-
-
-
-
Region
-
-
- 🇺🇸 {domain.region}
-
-
-
-
-
-
-
+
))
) : (
No domains
@@ -68,6 +25,94 @@ export default function DomainsList() {
);
}
+const DomainItem: React.FC<{ domain: Domain }> = ({ domain }) => {
+ const updateDomain = api.domain.updateDomain.useMutation();
+ const utils = api.useUtils();
+
+ const [clickTracking, setClickTracking] = React.useState(
+ domain.clickTracking
+ );
+ const [openTracking, setOpenTracking] = React.useState(domain.openTracking);
+
+ function handleClickTrackingChange() {
+ setClickTracking(!clickTracking);
+ updateDomain.mutate(
+ { id: domain.id, clickTracking: !clickTracking },
+ {
+ onSuccess: () => {
+ utils.domain.domains.invalidate();
+ },
+ }
+ );
+ }
+
+ function handleOpenTrackingChange() {
+ setOpenTracking(!openTracking);
+ updateDomain.mutate(
+ { id: domain.id, openTracking: !openTracking },
+ {
+ onSuccess: () => {
+ utils.domain.domains.invalidate();
+ },
+ }
+ );
+ }
+
+ return (
+
+
+
+
+
+
+ {domain.name}
+
+
+
+
+
+
Created at
+
+ {formatDistanceToNow(new Date(domain.createdAt), {
+ addSuffix: true,
+ })}
+
+
+
+
Region
+
+
+ 🇺🇸 {domain.region}
+
+
+
+
+
+
+
+ );
+};
+
const DomainStatusBadge: React.FC<{ status: DomainStatus }> = ({ status }) => {
let badgeColor = "bg-gray-400/10 text-gray-500 border-gray-400/10"; // Default color
switch (status) {
diff --git a/apps/web/src/server/api/routers/domain.ts b/apps/web/src/server/api/routers/domain.ts
index 4a09465..b1f73d9 100644
--- a/apps/web/src/server/api/routers/domain.ts
+++ b/apps/web/src/server/api/routers/domain.ts
@@ -7,7 +7,11 @@ import {
teamProcedure,
} from "~/server/api/trpc";
import { db } from "~/server/db";
-import { createDomain, getDomain } from "~/server/service/domain-service";
+import {
+ createDomain,
+ getDomain,
+ updateDomain,
+} from "~/server/service/domain-service";
export const domainRouter = createTRPCRouter({
createDomain: teamProcedure
@@ -21,6 +25,9 @@ export const domainRouter = createTRPCRouter({
where: {
teamId: ctx.team.id,
},
+ orderBy: {
+ createdAt: "desc",
+ },
});
return domains;
@@ -31,4 +38,19 @@ export const domainRouter = createTRPCRouter({
.query(async ({ ctx, input }) => {
return getDomain(input.id);
}),
+
+ updateDomain: teamProcedure
+ .input(
+ z.object({
+ id: z.number(),
+ clickTracking: z.boolean().optional(),
+ openTracking: z.boolean().optional(),
+ })
+ )
+ .mutation(async ({ ctx, input }) => {
+ return updateDomain(input.id, {
+ clickTracking: input.clickTracking,
+ openTracking: input.openTracking,
+ });
+ }),
});
diff --git a/apps/web/src/server/aws/setup.ts b/apps/web/src/server/aws/setup.ts
index bebbc0b..24d664c 100644
--- a/apps/web/src/server/aws/setup.ts
+++ b/apps/web/src/server/aws/setup.ts
@@ -78,6 +78,12 @@ async function setupSESConfiguration() {
topicArn,
[...GENERAL_EVENTS, "OPEN"]
);
+
+ await setWebhookConfiguration(APP_SETTINGS.SES_CONFIGURATION_FULL, topicArn, [
+ ...GENERAL_EVENTS,
+ "CLICK",
+ "OPEN",
+ ]);
}
async function setWebhookConfiguration(
diff --git a/apps/web/src/server/service/domain-service.ts b/apps/web/src/server/service/domain-service.ts
index 044a859..852cf89 100644
--- a/apps/web/src/server/service/domain-service.ts
+++ b/apps/web/src/server/service/domain-service.ts
@@ -67,3 +67,13 @@ export async function getDomain(id: number) {
return domain;
}
+
+export async function updateDomain(
+ id: number,
+ data: { clickTracking?: boolean; openTracking?: boolean }
+) {
+ return db.domain.update({
+ where: { id },
+ data,
+ });
+}
diff --git a/apps/web/src/server/service/email-service.ts b/apps/web/src/server/service/email-service.ts
index 8883e5b..489cbb5 100644
--- a/apps/web/src/server/service/email-service.ts
+++ b/apps/web/src/server/service/email-service.ts
@@ -1,6 +1,7 @@
import { EmailContent } from "~/types";
import { db } from "../db";
import { sendEmailThroughSes } from "../ses";
+import { APP_SETTINGS } from "~/utils/constants";
export async function sendEmail(
emailContent: EmailContent & { teamId: number }
@@ -30,6 +31,10 @@ export async function sendEmail(
text,
html,
region: domain.region,
+ configurationSetName: getConfigurationSetName(
+ domain.clickTracking,
+ domain.openTracking
+ ),
});
if (messageId) {
@@ -47,3 +52,20 @@ export async function sendEmail(
});
}
}
+
+function getConfigurationSetName(
+ clickTracking: boolean,
+ openTracking: boolean
+) {
+ if (clickTracking && openTracking) {
+ return APP_SETTINGS.SES_CONFIGURATION_FULL;
+ }
+ if (clickTracking) {
+ return APP_SETTINGS.SES_CONFIGURATION_CLICK_TRACKING;
+ }
+ if (openTracking) {
+ return APP_SETTINGS.SES_CONFIGURATION_OPEN_TRACKING;
+ }
+
+ return APP_SETTINGS.SES_CONFIGURATION_GENERAL;
+}
diff --git a/apps/web/src/server/ses.ts b/apps/web/src/server/ses.ts
index 818d0eb..b0aac9c 100644
--- a/apps/web/src/server/ses.ts
+++ b/apps/web/src/server/ses.ts
@@ -97,8 +97,10 @@ export async function sendEmailThroughSes({
text,
html,
region = "us-east-1",
+ configurationSetName,
}: EmailContent & {
region?: string;
+ configurationSetName: string;
}) {
const sesClient = getSesClient(region);
const command = new SendEmailCommand({
@@ -128,6 +130,7 @@ export async function sendEmailThroughSes({
},
},
},
+ ConfigurationSetName: configurationSetName,
});
try {
diff --git a/apps/web/src/utils/constants.ts b/apps/web/src/utils/constants.ts
index 33d6c44..b4768d3 100644
--- a/apps/web/src/utils/constants.ts
+++ b/apps/web/src/utils/constants.ts
@@ -5,4 +5,5 @@ export const APP_SETTINGS = {
SES_CONFIGURATION_GENERAL: `SES_CONFIGURATION_GENERAL_${env.NODE_ENV}`,
SES_CONFIGURATION_CLICK_TRACKING: `SES_CONFIGURATION_CLICK_TRACKING_${env.NODE_ENV}`,
SES_CONFIGURATION_OPEN_TRACKING: `SES_CONFIGURATION_OPEN_TRACKING_${env.NODE_ENV}`,
+ SES_CONFIGURATION_FULL: `SES_CONFIGURATION_FULL_${env.NODE_ENV}`,
};