fitaiProto/apps/admin/src/lib/email.ts
2026-03-11 01:43:19 +01:00

149 lines
3.5 KiB
TypeScript

import { Resend } from "resend";
import { render } from "@react-email/render";
import log from "./logger";
/**
* Email service using Resend
*
* Environment variables required:
* - RESEND_API_KEY: API key from Resend dashboard
* - EMAIL_FROM: Sender email address (e.g., "FitAI <noreply@fitai.com>")
* - EMAIL_REPLY_TO: Reply-to email address (optional)
*/
const resend = new Resend(process.env.RESEND_API_KEY);
const DEFAULT_FROM = process.env.EMAIL_FROM || "FitAI <noreply@fitai.com>";
const DEFAULT_REPLY_TO = process.env.EMAIL_REPLY_TO;
export interface SendEmailOptions {
to: string | string[];
subject: string;
react: React.ReactElement;
from?: string;
replyTo?: string;
}
/**
* Send an email using Resend
*
* @param options - Email options including recipient, subject, and React component
* @returns Response from Resend API
*
* @example
* ```tsx
* import { WelcomeEmail } from '@/emails/welcome-email';
*
* await sendEmail({
* to: 'user@example.com',
* subject: 'Welcome to FitAI',
* react: <WelcomeEmail name="John" />
* });
* ```
*/
export async function sendEmail({
to,
subject,
react,
from = DEFAULT_FROM,
replyTo = DEFAULT_REPLY_TO,
}: SendEmailOptions) {
try {
// Check if email is configured
if (!process.env.RESEND_API_KEY) {
log.warn("RESEND_API_KEY not configured. Email not sent.", {
to,
subject,
});
return { success: false, error: "Email not configured" };
}
const { data, error } = await resend.emails.send({
from,
to,
subject,
react,
...(replyTo && { replyTo }),
});
if (error) {
log.error("Failed to send email", error, { to, subject });
return { success: false, error: error.message };
}
log.info("Email sent successfully", { to, subject, emailId: data?.id });
return { success: true, data };
} catch (error) {
log.error("Email service error", error, { to, subject });
return { success: false, error: "Email service error" };
}
}
/**
* Send a welcome email to a new user
*/
export async function sendWelcomeEmail(email: string, name: string) {
const { WelcomeEmail } = await import("@/emails/welcome-email");
return sendEmail({
to: email,
subject: "Welcome to FitAI!",
react: WelcomeEmail({ name }),
});
}
/**
* Send an invitation email to a new user
*/
export async function sendInvitationEmail(
email: string,
role: string,
inviteUrl: string,
) {
const { UserInvitationEmail } = await import(
"@/emails/user-invitation-email"
);
return sendEmail({
to: email,
subject: "You've been invited to join FitAI",
react: UserInvitationEmail({ email, role, inviteUrl }),
});
}
/**
* Send a trainer assignment notification email
*/
export async function sendTrainerAssignmentEmail(
clientEmail: string,
clientName: string,
trainerName: string,
) {
const { TrainerAssignmentEmail } = await import(
"@/emails/trainer-assignment-email"
);
return sendEmail({
to: clientEmail,
subject: "You've been assigned a trainer",
react: TrainerAssignmentEmail({ clientName, trainerName }),
});
}
/**
* Send a recommendation notification email to a client
*/
export async function sendRecommendationEmail(
clientEmail: string,
clientName: string,
recommendationText: string,
) {
const { RecommendationEmail } = await import("@/emails/recommendation-email");
return sendEmail({
to: clientEmail,
subject: "New fitness recommendation from your trainer",
react: RecommendationEmail({ clientName, recommendationText }),
});
}