From bd8231912cf0ee8c29ca85e8bb6d2bea5b8bd01b Mon Sep 17 00:00:00 2001 From: Atridad Lahiji Date: Tue, 22 Aug 2023 21:26:26 -0600 Subject: [PATCH] User Created Email --- src/components/templates/Goodbye.tsx | 52 ------------------------- src/components/templates/Welcome.tsx | 58 ++++++++++++++-------------- src/pages/api/webhooks/index.ts | 22 ++++++++--- src/server/webhookHelpers.ts | 19 ++++++++- src/utils/types.ts | 14 ++++--- 5 files changed, 72 insertions(+), 93 deletions(-) delete mode 100644 src/components/templates/Goodbye.tsx diff --git a/src/components/templates/Goodbye.tsx b/src/components/templates/Goodbye.tsx deleted file mode 100644 index 3e2f310..0000000 --- a/src/components/templates/Goodbye.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { - Body, - Container, - Head, - Heading, - Hr, - Html, - Img, - Preview, - Section, - Tailwind, - Text, -} from "@react-email/components"; -import * as React from "react"; - -interface GoodbyeTemplateProps { - name: string; -} - -const baseUrl = process.env.VERCEL_URL - ? `https://${process.env.VERCEL_URL}` - : "http://localhost:3000"; - -export const Goodbye = ({ name }: GoodbyeTemplateProps) => ( - - - Sorry to see you go... 😭 - - - -
- {`Sprint -
- Farewell, {name}... - {"Were sorry to see you go."} - - Your data has been deleted, including all room history, user data, - votes, etc. - -
- — The Sprint Padawan team -
- -
- -); diff --git a/src/components/templates/Welcome.tsx b/src/components/templates/Welcome.tsx index 1602f00..1c46510 100644 --- a/src/components/templates/Welcome.tsx +++ b/src/components/templates/Welcome.tsx @@ -8,7 +8,7 @@ import { Img, Preview, Section, - Tailwind, + // Tailwind, Text, } from "@react-email/components"; import * as React from "react"; @@ -25,33 +25,33 @@ export const Welcome = ({ name }: WelcomeTemplateProps) => ( 🎉 Welcome to Sprint Padawan! 🎉 - - - -
- {`Sprint -
- - 🎉 Welcome to Sprint Padawan, {name}! 🎉 - - - Hello {name}, - - Thank you for signing up for Sprint Padawan! - - If at any point you encounter issues, please let me know at - support@sprintpadawan.dev. - -
- — The Sprint Padawan team -
- -
+ {/* */} + + +
+ {`Sprint +
+ + 🎉 Welcome to Sprint Padawan, {name}! 🎉 + + + Hello {name}, + + Thank you for signing up for Sprint Padawan! + + If at any point you encounter issues, please let me know at + support@sprintpadawan.dev. + +
+ — The Sprint Padawan team +
+ + {/*
*/} ); diff --git a/src/pages/api/webhooks/index.ts b/src/pages/api/webhooks/index.ts index a6ca28e..3b52c9d 100644 --- a/src/pages/api/webhooks/index.ts +++ b/src/pages/api/webhooks/index.ts @@ -3,7 +3,11 @@ import { onUserCreatedHandler, onUserDeletedHandler, } from "~/server/webhookHelpers"; -import { WebhookEventBodySchema, WebhookEvents } from "~/utils/types"; +import { + WebhookEventBody, + WebhookEventBodySchema, + WebhookEvents, +} from "~/utils/types"; export const config = { runtime: "edge", @@ -12,12 +16,17 @@ export const config = { export default async function handler(req: NextRequest) { try { - const requestBody = WebhookEventBodySchema.parse(await req.json()); + const eventBody = (await req.json()) as WebhookEventBody; + const { data, type } = WebhookEventBodySchema.parse(eventBody); let success = false; - switch (requestBody.type) { + switch (type) { case WebhookEvents.USER_CREATED: - success = await onUserCreatedHandler(requestBody.data.id); + success = await onUserCreatedHandler( + data.id, + `${data.first_name} ${data.last_name}`, + data.email_addresses?.map((email) => email.email_address) || [] + ); if (success) { return NextResponse.json( { result: "USER CREATED" }, @@ -31,7 +40,7 @@ export default async function handler(req: NextRequest) { } case WebhookEvents.USER_DELETED: - success = await onUserDeletedHandler(requestBody.data.id); + success = await onUserDeletedHandler(data.id); return NextResponse.json( { result: "USER DELETED" }, @@ -44,7 +53,8 @@ export default async function handler(req: NextRequest) { { status: 400, statusText: "INVALID WEBHOOK EVENT TYPE" } ); } - } catch { + } catch (error) { + console.log(error); return NextResponse.json( { result: "INVALID WEBHOOK EVENT BODY" }, { status: 400, statusText: "INVALID WEBHOOK EVENT BODY" } diff --git a/src/server/webhookHelpers.ts b/src/server/webhookHelpers.ts index 2e6c7f5..e6b51f1 100644 --- a/src/server/webhookHelpers.ts +++ b/src/server/webhookHelpers.ts @@ -2,6 +2,10 @@ import { eq } from "drizzle-orm"; import { db } from "./db"; import { rooms } from "./schema"; import { env } from "~/env.mjs"; +import { Welcome } from "~/components/templates/Welcome"; +import { Resend } from "resend"; + +const resend = new Resend(env.RESEND_API_KEY); export const onUserDeletedHandler = async (userId: string) => { try { @@ -13,7 +17,11 @@ export const onUserDeletedHandler = async (userId: string) => { } }; -export const onUserCreatedHandler = async (userId: string) => { +export const onUserCreatedHandler = async ( + userId: string, + userName: string, + userEmails: string[] +) => { const userUpdateResponse = await fetch( `https://api.clerk.com/v1/users/${userId}/metadata`, { @@ -33,5 +41,14 @@ export const onUserCreatedHandler = async (userId: string) => { } ); + userEmails.forEach((userEmail) => { + void resend.sendEmail({ + from: "no-reply@sprintpadawan.dev", + to: userEmail, + subject: "🎉 Welcome to Sprint Padawan! 🎉", + react: Welcome({ name: userName }), + }); + }); + return userUpdateResponse.ok; }; diff --git a/src/utils/types.ts b/src/utils/types.ts index a41fb24..1c3f2d9 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -23,14 +23,18 @@ export const WebhookEventBodySchema = z.object({ .array( z.object({ email_address: z.string().email(), - id: z.string(), - verification: z.object({ - status: z.string(), - strategy: z.string(), - }), + id: z.string().optional(), + verification: z + .object({ + status: z.string().optional(), + strategy: z.string().optional(), + }) + .optional(), }) ) .optional(), + first_name: z.string().optional(), + last_name: z.string().optional(), }), type: z.string(), });