Files
manoon-headless/src/lib/resend.ts
Unchained 5576946829
Some checks failed
Build and Deploy / build (push) Has been cancelled
feat(emails): implement transactional email system with Resend
- Add Resend email integration with @react-email/render
- Create email templates: OrderConfirmation, OrderShipped, OrderCancelled, OrderPaid
- Implement webhook handler for ORDER_CREATED and other events
- Add multi-language support for customer emails
- Admin emails in English with order details
- Update checkout page with auto-scroll on order completion
- Configure DASHBOARD_URL environment variable
2026-03-25 14:13:34 +02:00

107 lines
2.0 KiB
TypeScript

import { Resend } from "resend";
import { render } from "@react-email/render";
let resendClient: Resend | null = null;
function getResendClient(): Resend {
if (!resendClient) {
if (!process.env.RESEND_API_KEY) {
throw new Error("RESEND_API_KEY environment variable is not set");
}
resendClient = new Resend(process.env.RESEND_API_KEY);
}
return resendClient;
}
export const ADMIN_EMAILS = ["me@hytham.me", "tamara@hytham.me"];
export async function sendEmail({
to,
subject,
react,
text,
tags,
idempotencyKey,
}: {
to: string | string[];
subject: string;
react: React.ReactNode;
text?: string;
tags?: { name: string; value: string }[];
idempotencyKey?: string;
}) {
const resend = getResendClient();
// Render React component to HTML
const html = await render(react, {
pretty: true,
});
const { data, error } = await resend.emails.send({
from: "ManoonOils <support@mail.manoonoils.com>",
replyTo: "support@manoonoils.com",
to: Array.isArray(to) ? to : [to],
subject,
html,
text,
tags,
...(idempotencyKey && { idempotencyKey }),
});
if (error) {
console.error("Failed to send email:", error);
throw error;
}
return data;
}
export async function sendEmailToCustomer({
to,
subject,
react,
text,
language,
idempotencyKey,
}: {
to: string;
subject: string;
react: React.ReactNode;
text?: string;
language: string;
idempotencyKey?: string;
}) {
const tag = `customer-${language}`;
return sendEmail({
to,
subject,
react,
text,
tags: [{ name: "type", value: tag }],
idempotencyKey,
});
}
export async function sendEmailToAdmin({
subject,
react,
text,
eventType,
orderId,
}: {
subject: string;
react: React.ReactNode;
text?: string;
eventType: string;
orderId: string;
}) {
return sendEmail({
to: ADMIN_EMAILS,
subject: `[Admin] ${subject}`,
react,
text,
tags: [{ name: "type", value: "admin-notification" }],
idempotencyKey: `admin-${eventType}/${orderId}`,
});
}