feat: Add AGB PDF attachment to booking confirmation emails
- Extend email system to support file attachments - Add sendEmailWithAGB() function that automatically attaches AGB.pdf - Implement AGB PDF caching for better performance - Update booking confirmation email template with AGB notice - Add visual highlight box in HTML email with AGB information - Update email subject to indicate AGB attachment - Include AGB reference in both HTML and text versions - Ensure legal compliance by automatically sending terms with confirmations Changes: - email.ts: Add attachment support and AGB PDF integration - email-templates.ts: Add AGB notice to confirmation emails - bookings.ts: Use sendEmailWithAGB for confirmed bookings - German localization for admin treatments component
This commit is contained in:
@@ -62,6 +62,10 @@ export async function renderBookingConfirmedHTML(params: { name: string; date: s
|
||||
<p>Hallo ${name},</p>
|
||||
<p>wir haben deinen Termin am <strong>${date}</strong> um <strong>${time}</strong> bestätigt.</p>
|
||||
<p>Wir freuen uns auf dich!</p>
|
||||
<div style="background-color: #f8fafc; border-left: 4px solid #db2777; padding: 16px; margin: 20px 0; border-radius: 4px;">
|
||||
<p style="margin: 0; font-weight: 600; color: #db2777;">📋 Wichtiger Hinweis:</p>
|
||||
<p style="margin: 8px 0 0 0; color: #475569;">Die Allgemeinen Geschäftsbedingungen (AGB) findest du im Anhang dieser E-Mail. Bitte lies sie vor deinem Termin durch.</p>
|
||||
</div>
|
||||
<p>Liebe Grüße,<br/>Stargirlnails Kiel</p>
|
||||
`;
|
||||
return renderBrandedEmail("Termin bestätigt", inner);
|
||||
|
@@ -6,11 +6,39 @@ type SendEmailParams = {
|
||||
from?: string;
|
||||
cc?: string | string[];
|
||||
bcc?: string | string[];
|
||||
attachments?: Array<{
|
||||
filename: string;
|
||||
content: string; // base64 encoded
|
||||
type?: string;
|
||||
}>;
|
||||
};
|
||||
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { dirname, resolve } from "node:path";
|
||||
|
||||
const RESEND_API_KEY = process.env.RESEND_API_KEY;
|
||||
const DEFAULT_FROM = process.env.EMAIL_FROM || "Stargirlnails <no-reply@stargirlnails.de>";
|
||||
|
||||
// Cache for AGB PDF to avoid reading it multiple times
|
||||
let cachedAGBPDF: string | null = null;
|
||||
|
||||
async function getAGBPDFBase64(): Promise<string | null> {
|
||||
if (cachedAGBPDF) return cachedAGBPDF;
|
||||
|
||||
try {
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
const agbPath = resolve(__dirname, "../../../AGB.pdf");
|
||||
const buf = await readFile(agbPath);
|
||||
cachedAGBPDF = buf.toString('base64');
|
||||
return cachedAGBPDF;
|
||||
} catch (error) {
|
||||
console.warn("Could not read AGB.pdf:", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function sendEmail(params: SendEmailParams): Promise<{ success: boolean }> {
|
||||
if (!RESEND_API_KEY) {
|
||||
// In development or if not configured, skip sending but don't fail the flow
|
||||
@@ -32,6 +60,7 @@ export async function sendEmail(params: SendEmailParams): Promise<{ success: boo
|
||||
html: params.html,
|
||||
cc: params.cc ? (Array.isArray(params.cc) ? params.cc : [params.cc]) : undefined,
|
||||
bcc: params.bcc ? (Array.isArray(params.bcc) ? params.bcc : [params.bcc]) : undefined,
|
||||
attachments: params.attachments,
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -43,4 +72,21 @@ export async function sendEmail(params: SendEmailParams): Promise<{ success: boo
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
export async function sendEmailWithAGB(params: SendEmailParams): Promise<{ success: boolean }> {
|
||||
const agbBase64 = await getAGBPDFBase64();
|
||||
|
||||
if (agbBase64) {
|
||||
params.attachments = [
|
||||
...(params.attachments || []),
|
||||
{
|
||||
filename: "AGB_Stargirlnails_Kiel.pdf",
|
||||
content: agbBase64,
|
||||
type: "application/pdf"
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
return sendEmail(params);
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user