From b16562a83f55322cfca3e963978ebb6c20155693 Mon Sep 17 00:00:00 2001
From: Kiran K
Date: Thu, 27 Feb 2025 12:16:39 +0530
Subject: [PATCH] Add partner application approval email notification
---
.../lib/actions/partners/approve-partner.ts | 36 ++++-
.../partner-application-approved.tsx | 150 ++++++++++++++++++
2 files changed, 183 insertions(+), 3 deletions(-)
create mode 100644 packages/email/src/templates/partner-application-approved.tsx
diff --git a/apps/web/lib/actions/partners/approve-partner.ts b/apps/web/lib/actions/partners/approve-partner.ts
index f434a83020..834243fa67 100644
--- a/apps/web/lib/actions/partners/approve-partner.ts
+++ b/apps/web/lib/actions/partners/approve-partner.ts
@@ -1,5 +1,9 @@
"use server";
+import { determinePartnerReward } from "@/lib/partners/determine-partner-reward";
+import { ProgramRewardDescription } from "@/ui/partners/program-reward-description";
+import { sendEmail } from "@dub/email";
+import { PartnerApplicationApproved } from "@dub/email/templates/partner-application-approved";
import { prisma } from "@dub/prisma";
import { waitUntil } from "@vercel/functions";
import { getLinkOrThrow } from "../../api/links/get-link-or-throw";
@@ -33,11 +37,11 @@ export const approvePartnerAction = authActionClient
}),
]);
- if (link.programId) {
+ if (link.partnerId) {
throw new Error("Link is already associated with another partner.");
}
- const [programEnrollment, updatedLink] = await Promise.all([
+ const [programEnrollment, updatedLink, reward] = await Promise.all([
prisma.programEnrollment.update({
where: {
partnerId_programId: {
@@ -71,6 +75,12 @@ export const approvePartnerAction = authActionClient
},
},
}),
+
+ determinePartnerReward({
+ programId,
+ partnerId,
+ event: "sale",
+ }),
]);
const partner = programEnrollment.partner;
@@ -78,7 +88,27 @@ export const approvePartnerAction = authActionClient
waitUntil(
Promise.allSettled([
recordLink(updatedLink),
- // TODO: [partners] Notify partner of approval?
+
+ sendEmail({
+ subject: `Your application to join ${program.name} partner program has been approved!`,
+ email: partner.email!,
+ react: PartnerApplicationApproved({
+ program: {
+ name: program.name,
+ logo: program.logo,
+ slug: program.slug,
+ },
+ partner: {
+ name: partner.name,
+ email: partner.email!,
+ payoutsEnabled: partner.payoutsEnabled,
+ },
+ rewardDescription: ProgramRewardDescription({
+ reward,
+ }),
+ }),
+ }),
+
// TODO: send partner.created webhook
]),
);
diff --git a/packages/email/src/templates/partner-application-approved.tsx b/packages/email/src/templates/partner-application-approved.tsx
new file mode 100644
index 0000000000..6af84b8c63
--- /dev/null
+++ b/packages/email/src/templates/partner-application-approved.tsx
@@ -0,0 +1,150 @@
+import { DUB_WORDMARK } from "@dub/utils";
+import {
+ Body,
+ Container,
+ Head,
+ Heading,
+ Hr,
+ Html,
+ Img,
+ Link,
+ Preview,
+ Section,
+ Tailwind,
+ Text,
+} from "@react-email/components";
+import { ReactNode } from "react";
+import { Footer } from "../components/footer";
+
+export function PartnerApplicationApproved({
+ program = {
+ name: "Acme",
+ logo: DUB_WORDMARK,
+ slug: "acme",
+ },
+ partner = {
+ name: "John Doe",
+ email: "panic@thedis.co",
+ payoutsEnabled: false,
+ },
+ rewardDescription = "Earn 30% for each sale and again every month for 12 months.",
+}: {
+ program: {
+ name: string;
+ logo: string | null;
+ slug: string;
+ };
+ partner: {
+ name: string;
+ email: string;
+ payoutsEnabled: boolean;
+ };
+ rewardDescription: ReactNode;
+}) {
+ return (
+
+
+
+ Your application to join {program.name}'s partner program has been
+ approved!
+
+
+
+
+
+
+
+
+
+ Congratulations, {partner.name}!
+
+
+
+ Your application to join {program.name}'s partner
+ program has been approved. You can now start promoting their
+ products and earning commissions.
+
+
+
+ {rewardDescription}
+
+
+
+
+
+ Getting Started
+
+
+
+ 1. Find your unique referral links in the{" "}
+
+ Links
+ {" "}
+ section.
+
+
+
+ 2. Share your referral links on your website, blog, social media,
+ or email newsletters.
+
+
+
+ 3. Track your{" "}
+
+ link performance
+ {" "}
+ and{" "}
+
+ earnings
+ {" "}
+ in real-time.
+
+
+ {!partner.payoutsEnabled && (
+
+ 4. Connect your Stripe account to{" "}
+
+ enable payouts
+
+ .
+
+ )}
+
+
+
+
+
+ Go to your dashboard
+
+
+
+
+ If you have any questions about the program please don't hesitate
+ to reach out to the {program.name} team.
+
+
+
+ We're excited to have you as a partner and look forward to your
+ success!
+
+
+
+
+
+
+
+ );
+}
+
+export default PartnerApplicationApproved;