Initial commit: ANOUMA website with Payload CMS, WebRTC meetings, and booking system
- Next.js 16 App Router site with the ANOUMA design system - Payload CMS (PostgreSQL) for offers, events, posts and page content - WebRTC video-call system with custom signaling server - SMTP email reminders and booking-request notifications - Customer accounts, calendar-based availability, and booking workflow
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
export type ReminderEmailData = {
|
||||
recipientName: string;
|
||||
eventTitle: string;
|
||||
dateLabel: string;
|
||||
timeLabel: string;
|
||||
joinUrl: string;
|
||||
meetingPassword: string;
|
||||
minutesBefore: number;
|
||||
};
|
||||
|
||||
const colors = {
|
||||
mauveDark: "#8b616d",
|
||||
plum: "#66505f",
|
||||
cream: "#f2e2d6",
|
||||
creamLight: "#fbf6f1",
|
||||
};
|
||||
|
||||
/** Table-based HTML email (inline styles only) matching the ANOUMA design. */
|
||||
export function renderReminderEmailHtml(data: ReminderEmailData): string {
|
||||
const { recipientName, eventTitle, dateLabel, timeLabel, joinUrl, meetingPassword, minutesBefore } = data;
|
||||
|
||||
return `<!doctype html>
|
||||
<html lang="de">
|
||||
<body style="margin:0;padding:0;background:${colors.creamLight};font-family:Georgia,'Times New Roman',serif;">
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background:${colors.creamLight};padding:32px 16px;">
|
||||
<tr>
|
||||
<td align="center">
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="max-width:480px;background:#ffffff;border-radius:24px;overflow:hidden;">
|
||||
<tr>
|
||||
<td style="background:${colors.mauveDark};padding:28px 32px;text-align:center;">
|
||||
<span style="color:#ffffff;font-size:22px;letter-spacing:0.12em;font-weight:600;">ANOUMA</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding:32px;">
|
||||
<p style="margin:0 0 20px;color:${colors.plum};font-size:16px;line-height:1.6;">
|
||||
Hallo ${escapeHtml(recipientName)},
|
||||
</p>
|
||||
<p style="margin:0 0 24px;color:${colors.plum};font-size:18px;line-height:1.6;font-style:italic;">
|
||||
Dein Online-Termin bei ANOUMA beginnt in ${minutesBefore} Minuten.
|
||||
</p>
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background:${colors.cream};border-radius:16px;">
|
||||
<tr>
|
||||
<td style="padding:20px 24px;">
|
||||
<p style="margin:0 0 12px;color:${colors.plum};font-size:14px;">
|
||||
<strong>Termin:</strong><br />${escapeHtml(eventTitle)}
|
||||
</p>
|
||||
<p style="margin:0 0 12px;color:${colors.plum};font-size:14px;">
|
||||
<strong>Datum:</strong><br />${escapeHtml(dateLabel)}
|
||||
</p>
|
||||
<p style="margin:0;color:${colors.plum};font-size:14px;">
|
||||
<strong>Uhrzeit:</strong><br />${escapeHtml(timeLabel)} Uhr
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table role="presentation" cellpadding="0" cellspacing="0" style="margin:28px auto;">
|
||||
<tr>
|
||||
<td style="border-radius:999px;background:${colors.mauveDark};">
|
||||
<a href="${joinUrl}" style="display:inline-block;padding:14px 32px;color:#ffffff;text-decoration:none;font-size:14px;font-weight:600;letter-spacing:0.02em;">
|
||||
Meeting betreten
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p style="margin:0 0 4px;color:${colors.plum};font-size:14px;">
|
||||
<strong>Meeting-Passwort:</strong>
|
||||
</p>
|
||||
<p style="margin:0 0 20px;color:${colors.plum};font-size:20px;letter-spacing:0.08em;font-family:'Courier New',monospace;">
|
||||
${escapeHtml(meetingPassword)}
|
||||
</p>
|
||||
<p style="margin:0;color:${colors.plum};font-size:13px;line-height:1.6;">
|
||||
Bitte halte dein Passwort bereit. Beim Betreten des Meetings wirst du außerdem nach deinem Namen gefragt.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding:20px 32px;background:${colors.cream};text-align:center;">
|
||||
<span style="color:${colors.plum};font-size:12px;">Räume für Verbindung — mit dir selbst, miteinander und mit der Natur.</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>`;
|
||||
}
|
||||
|
||||
export function renderReminderEmailText(data: ReminderEmailData): string {
|
||||
const { recipientName, eventTitle, dateLabel, timeLabel, joinUrl, meetingPassword, minutesBefore } = data;
|
||||
return [
|
||||
`Hallo ${recipientName},`,
|
||||
"",
|
||||
`Dein Online-Termin bei ANOUMA beginnt in ${minutesBefore} Minuten.`,
|
||||
"",
|
||||
`Termin: ${eventTitle}`,
|
||||
`Datum: ${dateLabel}`,
|
||||
`Uhrzeit: ${timeLabel} Uhr`,
|
||||
"",
|
||||
`Meeting betreten: ${joinUrl}`,
|
||||
`Meeting-Passwort: ${meetingPassword}`,
|
||||
"",
|
||||
"Bitte halte dein Passwort bereit. Beim Betreten des Meetings wirst du außerdem nach deinem Namen gefragt.",
|
||||
].join("\n");
|
||||
}
|
||||
|
||||
function escapeHtml(value: string): string {
|
||||
return value
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """);
|
||||
}
|
||||
Reference in New Issue
Block a user