- {isCreating || isUpdating ? "Saving..." : (editingTreatment ? "Update" : "Create")}
+ {isCreating || isUpdating ? "Speichern..." : (editingTreatment ? "Aktualisieren" : "Erstellen")}
@@ -202,19 +202,19 @@ export function AdminTreatments() {
- Treatment
+ Behandlung
|
- Category
+ Kategorie
|
- Duration
+ Dauer
|
- Price
+ Preis
|
- Actions
+ Aktionen
|
@@ -231,17 +231,17 @@ export function AdminTreatments() {
{treatment.category}
- {treatment.duration} min
+ {treatment.duration} Min
|
- ${(treatment.price / 100).toFixed(2)}
+ {(treatment.price / 100).toFixed(2)} €
|
|
diff --git a/src/server/lib/email-templates.ts b/src/server/lib/email-templates.ts
index d4520b0..f121ee3 100644
--- a/src/server/lib/email-templates.ts
+++ b/src/server/lib/email-templates.ts
@@ -62,6 +62,10 @@ export async function renderBookingConfirmedHTML(params: { name: string; date: s
Hallo ${name},
wir haben deinen Termin am ${date} um ${time} bestätigt.
Wir freuen uns auf dich!
+
+
📋 Wichtiger Hinweis:
+
Die Allgemeinen Geschäftsbedingungen (AGB) findest du im Anhang dieser E-Mail. Bitte lies sie vor deinem Termin durch.
+
Liebe Grüße,
Stargirlnails Kiel
`;
return renderBrandedEmail("Termin bestätigt", inner);
diff --git a/src/server/lib/email.ts b/src/server/lib/email.ts
index 71a0ed7..14ba5d5 100644
--- a/src/server/lib/email.ts
+++ b/src/server/lib/email.ts
@@ -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
";
+// Cache for AGB PDF to avoid reading it multiple times
+let cachedAGBPDF: string | null = null;
+
+async function getAGBPDFBase64(): Promise {
+ 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);
+}
+
diff --git a/src/server/rpc/bookings.ts b/src/server/rpc/bookings.ts
index 41966b3..ff7d3ab 100644
--- a/src/server/rpc/bookings.ts
+++ b/src/server/rpc/bookings.ts
@@ -3,7 +3,7 @@ import { z } from "zod";
import { randomUUID } from "crypto";
import { createKV } from "@/server/lib/create-kv";
import { createKV as createAvailabilityKV } from "@/server/lib/create-kv";
-import { sendEmail } from "@/server/lib/email";
+import { sendEmail, sendEmailWithAGB } from "@/server/lib/email";
import { renderBookingPendingHTML, renderBookingConfirmedHTML, renderBookingCancelledHTML } from "@/server/lib/email-templates";
const BookingSchema = z.object({
@@ -146,10 +146,10 @@ const updateStatus = os
try {
if (input.status === "confirmed") {
const html = await renderBookingConfirmedHTML({ name: booking.customerName, date: booking.appointmentDate, time: booking.appointmentTime });
- await sendEmail({
+ await sendEmailWithAGB({
to: booking.customerEmail,
- subject: "Dein Termin wurde bestätigt",
- text: `Hallo ${booking.customerName},\n\nwir haben deinen Termin am ${booking.appointmentDate} um ${booking.appointmentTime} bestätigt.\n\nBis bald!\nStargirlnails Kiel`,
+ subject: "Dein Termin wurde bestätigt - AGB im Anhang",
+ text: `Hallo ${booking.customerName},\n\nwir haben deinen Termin am ${booking.appointmentDate} um ${booking.appointmentTime} bestätigt.\n\nWichtiger Hinweis: Die Allgemeinen Geschäftsbedingungen (AGB) findest du im Anhang dieser E-Mail. Bitte lies sie vor deinem Termin durch.\n\nBis bald!\nStargirlnails Kiel`,
html,
cc: process.env.ADMIN_EMAIL ? [process.env.ADMIN_EMAIL] : undefined,
});