first commit
This commit is contained in:
675
backend/src/lib/emailTemplates.ts
Normal file
675
backend/src/lib/emailTemplates.ts
Normal file
@@ -0,0 +1,675 @@
|
||||
// Email templates for Spanglish platform
|
||||
// These are the default templates that get seeded into the database
|
||||
|
||||
export interface EmailVariable {
|
||||
name: string;
|
||||
description: string;
|
||||
example: string;
|
||||
}
|
||||
|
||||
export interface DefaultTemplate {
|
||||
name: string;
|
||||
slug: string;
|
||||
subject: string;
|
||||
subjectEs: string;
|
||||
bodyHtml: string;
|
||||
bodyHtmlEs: string;
|
||||
bodyText: string;
|
||||
bodyTextEs: string;
|
||||
description: string;
|
||||
variables: EmailVariable[];
|
||||
isSystem: boolean;
|
||||
}
|
||||
|
||||
// Common variables available in all templates
|
||||
export const commonVariables: EmailVariable[] = [
|
||||
{ name: 'siteName', description: 'Website name', example: 'Spanglish' },
|
||||
{ name: 'siteUrl', description: 'Website URL', example: 'https://spanglish.com' },
|
||||
{ name: 'currentYear', description: 'Current year', example: '2026' },
|
||||
{ name: 'supportEmail', description: 'Support email address', example: 'hello@spanglish.com' },
|
||||
];
|
||||
|
||||
// Booking-specific variables
|
||||
export const bookingVariables: EmailVariable[] = [
|
||||
{ name: 'attendeeName', description: 'Attendee full name', example: 'John Doe' },
|
||||
{ name: 'attendeeEmail', description: 'Attendee email', example: 'john@example.com' },
|
||||
{ name: 'ticketId', description: 'Unique ticket ID', example: 'TKT-ABC123' },
|
||||
{ name: 'qrCode', description: 'QR code for check-in', example: 'data:image/png;base64,...' },
|
||||
{ name: 'eventTitle', description: 'Event title', example: 'Spanglish Night - January Edition' },
|
||||
{ name: 'eventDate', description: 'Event date formatted', example: 'January 28, 2026' },
|
||||
{ name: 'eventTime', description: 'Event time', example: '7:00 PM' },
|
||||
{ name: 'eventLocation', description: 'Event location', example: 'Casa Cultural, Asunción' },
|
||||
{ name: 'eventLocationUrl', description: 'Google Maps link', example: 'https://maps.google.com/...' },
|
||||
{ name: 'eventPrice', description: 'Event price with currency', example: '50,000 PYG' },
|
||||
];
|
||||
|
||||
// Payment-specific variables
|
||||
export const paymentVariables: EmailVariable[] = [
|
||||
{ name: 'paymentAmount', description: 'Payment amount with currency', example: '50,000 PYG' },
|
||||
{ name: 'paymentMethod', description: 'Payment method used', example: 'Lightning' },
|
||||
{ name: 'paymentReference', description: 'Payment reference ID', example: 'PAY-XYZ789' },
|
||||
{ name: 'paymentDate', description: 'Payment date', example: 'January 28, 2026' },
|
||||
];
|
||||
|
||||
// Base HTML wrapper for all emails
|
||||
export const baseEmailWrapper = `
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{lang}}">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{subject}}</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.container {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
.header {
|
||||
background-color: #1a1a1a;
|
||||
padding: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
.header h1 {
|
||||
margin: 0;
|
||||
color: #fff;
|
||||
font-size: 24px;
|
||||
}
|
||||
.header h1 span {
|
||||
color: #f4d03f;
|
||||
}
|
||||
.content {
|
||||
padding: 32px 24px;
|
||||
}
|
||||
.content h2 {
|
||||
color: #1a1a1a;
|
||||
margin-top: 0;
|
||||
}
|
||||
.event-card {
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.event-card h3 {
|
||||
margin-top: 0;
|
||||
color: #1a1a1a;
|
||||
}
|
||||
.event-detail {
|
||||
display: flex;
|
||||
margin: 8px 0;
|
||||
}
|
||||
.event-detail strong {
|
||||
min-width: 80px;
|
||||
color: #666;
|
||||
}
|
||||
.ticket-box {
|
||||
background-color: #f4d03f;
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
text-align: center;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.ticket-box p {
|
||||
margin: 4px 0;
|
||||
font-weight: 600;
|
||||
color: #1a1a1a;
|
||||
}
|
||||
.ticket-id {
|
||||
font-size: 20px;
|
||||
font-family: monospace;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
.btn {
|
||||
display: inline-block;
|
||||
background-color: #f4d03f;
|
||||
color: #1a1a1a;
|
||||
text-decoration: none;
|
||||
padding: 12px 24px;
|
||||
border-radius: 6px;
|
||||
font-weight: 600;
|
||||
margin: 16px 0;
|
||||
}
|
||||
.btn:hover {
|
||||
background-color: #e6c230;
|
||||
}
|
||||
.footer {
|
||||
background-color: #f5f5f5;
|
||||
padding: 24px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
.footer a {
|
||||
color: #333;
|
||||
}
|
||||
.qr-code {
|
||||
text-align: center;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.qr-code img {
|
||||
max-width: 150px;
|
||||
height: auto;
|
||||
}
|
||||
.divider {
|
||||
height: 1px;
|
||||
background-color: #eee;
|
||||
margin: 24px 0;
|
||||
}
|
||||
.note {
|
||||
background-color: #fff9e6;
|
||||
border-left: 4px solid #f4d03f;
|
||||
padding: 12px 16px;
|
||||
margin: 16px 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
.content {
|
||||
padding: 24px 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1>Span<span>glish</span></h1>
|
||||
</div>
|
||||
<div class="content">
|
||||
{{content}}
|
||||
</div>
|
||||
<div class="footer">
|
||||
<p>{{siteName}} - Language Exchange Community in Asunción</p>
|
||||
<p><a href="{{siteUrl}}">{{siteUrl}}</a></p>
|
||||
<p>Questions? Contact us at <a href="mailto:{{supportEmail}}">{{supportEmail}}</a></p>
|
||||
<p>© {{currentYear}} {{siteName}}. All rights reserved.</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
// Default templates
|
||||
export const defaultTemplates: DefaultTemplate[] = [
|
||||
{
|
||||
name: 'Booking Confirmation',
|
||||
slug: 'booking-confirmation',
|
||||
subject: 'Your Spanglish ticket is confirmed 🎉',
|
||||
subjectEs: 'Tu entrada de Spanglish está confirmada 🎉',
|
||||
bodyHtml: `
|
||||
<h2>Your Booking is Confirmed!</h2>
|
||||
<p>Hi {{attendeeName}},</p>
|
||||
<p>Great news! Your spot for <strong>{{eventTitle}}</strong> has been confirmed. We can't wait to see you there!</p>
|
||||
|
||||
<div class="event-card">
|
||||
<h3>📅 Event Details</h3>
|
||||
<div class="event-detail"><strong>Event:</strong> {{eventTitle}}</div>
|
||||
<div class="event-detail"><strong>Date:</strong> {{eventDate}}</div>
|
||||
<div class="event-detail"><strong>Time:</strong> {{eventTime}}</div>
|
||||
<div class="event-detail"><strong>Location:</strong> {{eventLocation}}</div>
|
||||
{{#if eventLocationUrl}}
|
||||
<p><a href="{{eventLocationUrl}}" class="btn">📍 View on Map</a></p>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<div class="ticket-box">
|
||||
<p>Your Ticket ID</p>
|
||||
<p class="ticket-id">{{ticketId}}</p>
|
||||
</div>
|
||||
|
||||
{{#if qrCode}}
|
||||
<div class="qr-code">
|
||||
<p><strong>Show this QR code at check-in:</strong></p>
|
||||
<img src="{{qrCode}}" alt="Check-in QR Code" />
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="note">
|
||||
<strong>💡 Important:</strong> Please arrive 10-15 minutes early for check-in. Bring your ticket ID or show this email.
|
||||
</div>
|
||||
|
||||
<p>See you at Spanglish!</p>
|
||||
<p>The Spanglish Team</p>
|
||||
`,
|
||||
bodyHtmlEs: `
|
||||
<h2>¡Tu Reserva está Confirmada!</h2>
|
||||
<p>Hola {{attendeeName}},</p>
|
||||
<p>¡Excelentes noticias! Tu lugar para <strong>{{eventTitle}}</strong> ha sido confirmado. ¡No podemos esperar a verte ahí!</p>
|
||||
|
||||
<div class="event-card">
|
||||
<h3>📅 Detalles del Evento</h3>
|
||||
<div class="event-detail"><strong>Evento:</strong> {{eventTitle}}</div>
|
||||
<div class="event-detail"><strong>Fecha:</strong> {{eventDate}}</div>
|
||||
<div class="event-detail"><strong>Hora:</strong> {{eventTime}}</div>
|
||||
<div class="event-detail"><strong>Ubicación:</strong> {{eventLocation}}</div>
|
||||
{{#if eventLocationUrl}}
|
||||
<p><a href="{{eventLocationUrl}}" class="btn">📍 Ver en el Mapa</a></p>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<div class="ticket-box">
|
||||
<p>Tu ID de Ticket</p>
|
||||
<p class="ticket-id">{{ticketId}}</p>
|
||||
</div>
|
||||
|
||||
{{#if qrCode}}
|
||||
<div class="qr-code">
|
||||
<p><strong>Muestra este código QR en el check-in:</strong></p>
|
||||
<img src="{{qrCode}}" alt="Código QR de Check-in" />
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="note">
|
||||
<strong>💡 Importante:</strong> Por favor llega 10-15 minutos antes para el check-in. Trae tu ID de ticket o muestra este email.
|
||||
</div>
|
||||
|
||||
<p>¡Nos vemos en Spanglish!</p>
|
||||
<p>El Equipo de Spanglish</p>
|
||||
`,
|
||||
bodyText: `Your Booking is Confirmed!
|
||||
|
||||
Hi {{attendeeName}},
|
||||
|
||||
Great news! Your spot for {{eventTitle}} has been confirmed.
|
||||
|
||||
Event Details:
|
||||
- Event: {{eventTitle}}
|
||||
- Date: {{eventDate}}
|
||||
- Time: {{eventTime}}
|
||||
- Location: {{eventLocation}}
|
||||
|
||||
Your Ticket ID: {{ticketId}}
|
||||
|
||||
Important: Please arrive 10-15 minutes early for check-in. Bring your ticket ID or show this email.
|
||||
|
||||
See you at Spanglish!
|
||||
The Spanglish Team`,
|
||||
bodyTextEs: `¡Tu Reserva está Confirmada!
|
||||
|
||||
Hola {{attendeeName}},
|
||||
|
||||
¡Excelentes noticias! Tu lugar para {{eventTitle}} ha sido confirmado.
|
||||
|
||||
Detalles del Evento:
|
||||
- Evento: {{eventTitle}}
|
||||
- Fecha: {{eventDate}}
|
||||
- Hora: {{eventTime}}
|
||||
- Ubicación: {{eventLocation}}
|
||||
|
||||
Tu ID de Ticket: {{ticketId}}
|
||||
|
||||
Importante: Por favor llega 10-15 minutos antes para el check-in. Trae tu ID de ticket o muestra este email.
|
||||
|
||||
¡Nos vemos en Spanglish!
|
||||
El Equipo de Spanglish`,
|
||||
description: 'Sent automatically when a booking is confirmed after payment',
|
||||
variables: [...commonVariables, ...bookingVariables],
|
||||
isSystem: true,
|
||||
},
|
||||
{
|
||||
name: 'Payment Receipt',
|
||||
slug: 'payment-receipt',
|
||||
subject: 'Payment Receipt - Spanglish',
|
||||
subjectEs: 'Recibo de Pago - Spanglish',
|
||||
bodyHtml: `
|
||||
<h2>Payment Received</h2>
|
||||
<p>Hi {{attendeeName}},</p>
|
||||
<p>Thank you for your payment! Here's your receipt for your records.</p>
|
||||
|
||||
<div class="event-card">
|
||||
<h3>💳 Payment Details</h3>
|
||||
<div class="event-detail"><strong>Amount:</strong> {{paymentAmount}}</div>
|
||||
<div class="event-detail"><strong>Method:</strong> {{paymentMethod}}</div>
|
||||
<div class="event-detail"><strong>Reference:</strong> {{paymentReference}}</div>
|
||||
<div class="event-detail"><strong>Date:</strong> {{paymentDate}}</div>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<div class="event-card">
|
||||
<h3>📅 Event</h3>
|
||||
<div class="event-detail"><strong>Event:</strong> {{eventTitle}}</div>
|
||||
<div class="event-detail"><strong>Date:</strong> {{eventDate}}</div>
|
||||
<div class="event-detail"><strong>Ticket ID:</strong> {{ticketId}}</div>
|
||||
</div>
|
||||
|
||||
<p>Keep this email as your payment confirmation.</p>
|
||||
<p>The Spanglish Team</p>
|
||||
`,
|
||||
bodyHtmlEs: `
|
||||
<h2>Pago Recibido</h2>
|
||||
<p>Hola {{attendeeName}},</p>
|
||||
<p>¡Gracias por tu pago! Aquí está tu recibo para tus registros.</p>
|
||||
|
||||
<div class="event-card">
|
||||
<h3>💳 Detalles del Pago</h3>
|
||||
<div class="event-detail"><strong>Monto:</strong> {{paymentAmount}}</div>
|
||||
<div class="event-detail"><strong>Método:</strong> {{paymentMethod}}</div>
|
||||
<div class="event-detail"><strong>Referencia:</strong> {{paymentReference}}</div>
|
||||
<div class="event-detail"><strong>Fecha:</strong> {{paymentDate}}</div>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<div class="event-card">
|
||||
<h3>📅 Evento</h3>
|
||||
<div class="event-detail"><strong>Evento:</strong> {{eventTitle}}</div>
|
||||
<div class="event-detail"><strong>Fecha:</strong> {{eventDate}}</div>
|
||||
<div class="event-detail"><strong>ID de Ticket:</strong> {{ticketId}}</div>
|
||||
</div>
|
||||
|
||||
<p>Guarda este email como tu confirmación de pago.</p>
|
||||
<p>El Equipo de Spanglish</p>
|
||||
`,
|
||||
bodyText: `Payment Received
|
||||
|
||||
Hi {{attendeeName}},
|
||||
|
||||
Thank you for your payment! Here's your receipt:
|
||||
|
||||
Payment Details:
|
||||
- Amount: {{paymentAmount}}
|
||||
- Method: {{paymentMethod}}
|
||||
- Reference: {{paymentReference}}
|
||||
- Date: {{paymentDate}}
|
||||
|
||||
Event: {{eventTitle}}
|
||||
Date: {{eventDate}}
|
||||
Ticket ID: {{ticketId}}
|
||||
|
||||
Keep this email as your payment confirmation.
|
||||
|
||||
The Spanglish Team`,
|
||||
bodyTextEs: `Pago Recibido
|
||||
|
||||
Hola {{attendeeName}},
|
||||
|
||||
¡Gracias por tu pago! Aquí está tu recibo:
|
||||
|
||||
Detalles del Pago:
|
||||
- Monto: {{paymentAmount}}
|
||||
- Método: {{paymentMethod}}
|
||||
- Referencia: {{paymentReference}}
|
||||
- Fecha: {{paymentDate}}
|
||||
|
||||
Evento: {{eventTitle}}
|
||||
Fecha: {{eventDate}}
|
||||
ID de Ticket: {{ticketId}}
|
||||
|
||||
Guarda este email como tu confirmación de pago.
|
||||
|
||||
El Equipo de Spanglish`,
|
||||
description: 'Sent automatically after payment is processed',
|
||||
variables: [...commonVariables, ...bookingVariables, ...paymentVariables],
|
||||
isSystem: true,
|
||||
},
|
||||
{
|
||||
name: 'Event Update',
|
||||
slug: 'event-update',
|
||||
subject: 'Important Update: {{eventTitle}}',
|
||||
subjectEs: 'Actualización Importante: {{eventTitle}}',
|
||||
bodyHtml: `
|
||||
<h2>Important Event Update</h2>
|
||||
<p>Hi {{attendeeName}},</p>
|
||||
<p>We have an important update regarding <strong>{{eventTitle}}</strong>.</p>
|
||||
|
||||
<div class="event-card">
|
||||
<h3>📢 Message</h3>
|
||||
<p>{{customMessage}}</p>
|
||||
</div>
|
||||
|
||||
<div class="event-card">
|
||||
<h3>📅 Event Details</h3>
|
||||
<div class="event-detail"><strong>Event:</strong> {{eventTitle}}</div>
|
||||
<div class="event-detail"><strong>Date:</strong> {{eventDate}}</div>
|
||||
<div class="event-detail"><strong>Time:</strong> {{eventTime}}</div>
|
||||
<div class="event-detail"><strong>Location:</strong> {{eventLocation}}</div>
|
||||
</div>
|
||||
|
||||
<p>If you have any questions, please don't hesitate to contact us.</p>
|
||||
<p>The Spanglish Team</p>
|
||||
`,
|
||||
bodyHtmlEs: `
|
||||
<h2>Actualización Importante del Evento</h2>
|
||||
<p>Hola {{attendeeName}},</p>
|
||||
<p>Tenemos una actualización importante sobre <strong>{{eventTitle}}</strong>.</p>
|
||||
|
||||
<div class="event-card">
|
||||
<h3>📢 Mensaje</h3>
|
||||
<p>{{customMessage}}</p>
|
||||
</div>
|
||||
|
||||
<div class="event-card">
|
||||
<h3>📅 Detalles del Evento</h3>
|
||||
<div class="event-detail"><strong>Evento:</strong> {{eventTitle}}</div>
|
||||
<div class="event-detail"><strong>Fecha:</strong> {{eventDate}}</div>
|
||||
<div class="event-detail"><strong>Hora:</strong> {{eventTime}}</div>
|
||||
<div class="event-detail"><strong>Ubicación:</strong> {{eventLocation}}</div>
|
||||
</div>
|
||||
|
||||
<p>Si tienes alguna pregunta, no dudes en contactarnos.</p>
|
||||
<p>El Equipo de Spanglish</p>
|
||||
`,
|
||||
bodyText: `Important Event Update
|
||||
|
||||
Hi {{attendeeName}},
|
||||
|
||||
We have an important update regarding {{eventTitle}}.
|
||||
|
||||
Message:
|
||||
{{customMessage}}
|
||||
|
||||
Event Details:
|
||||
- Event: {{eventTitle}}
|
||||
- Date: {{eventDate}}
|
||||
- Time: {{eventTime}}
|
||||
- Location: {{eventLocation}}
|
||||
|
||||
If you have any questions, please don't hesitate to contact us.
|
||||
|
||||
The Spanglish Team`,
|
||||
bodyTextEs: `Actualización Importante del Evento
|
||||
|
||||
Hola {{attendeeName}},
|
||||
|
||||
Tenemos una actualización importante sobre {{eventTitle}}.
|
||||
|
||||
Mensaje:
|
||||
{{customMessage}}
|
||||
|
||||
Detalles del Evento:
|
||||
- Evento: {{eventTitle}}
|
||||
- Fecha: {{eventDate}}
|
||||
- Hora: {{eventTime}}
|
||||
- Ubicación: {{eventLocation}}
|
||||
|
||||
Si tienes alguna pregunta, no dudes en contactarnos.
|
||||
|
||||
El Equipo de Spanglish`,
|
||||
description: 'Template for sending event updates to attendees (sent manually)',
|
||||
variables: [
|
||||
...commonVariables,
|
||||
...bookingVariables,
|
||||
{ name: 'customMessage', description: 'Custom message from admin', example: 'The venue has changed...' }
|
||||
],
|
||||
isSystem: true,
|
||||
},
|
||||
{
|
||||
name: 'Post-Event Follow-Up',
|
||||
slug: 'post-event-followup',
|
||||
subject: 'Thanks for joining {{eventTitle}}! 🙏',
|
||||
subjectEs: '¡Gracias por asistir a {{eventTitle}}! 🙏',
|
||||
bodyHtml: `
|
||||
<h2>Thank You for Joining Us!</h2>
|
||||
<p>Hi {{attendeeName}},</p>
|
||||
<p>Thank you so much for being part of <strong>{{eventTitle}}</strong>! We hope you had a great time practicing languages and meeting new people.</p>
|
||||
|
||||
<div class="event-card">
|
||||
<h3>💬 Share Your Experience</h3>
|
||||
<p>{{customMessage}}</p>
|
||||
</div>
|
||||
|
||||
{{#if nextEventTitle}}
|
||||
<div class="event-card">
|
||||
<h3>📅 Next Event</h3>
|
||||
<div class="event-detail"><strong>Event:</strong> {{nextEventTitle}}</div>
|
||||
<div class="event-detail"><strong>Date:</strong> {{nextEventDate}}</div>
|
||||
<p style="text-align: center; margin-top: 16px;">
|
||||
<a href="{{nextEventUrl}}" class="btn">Reserve Your Spot</a>
|
||||
</p>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<p>Follow us on social media for updates and photos from the event!</p>
|
||||
<p>See you at the next Spanglish!</p>
|
||||
<p>The Spanglish Team</p>
|
||||
`,
|
||||
bodyHtmlEs: `
|
||||
<h2>¡Gracias por Unirte!</h2>
|
||||
<p>Hola {{attendeeName}},</p>
|
||||
<p>¡Muchas gracias por ser parte de <strong>{{eventTitle}}</strong>! Esperamos que hayas pasado un gran momento practicando idiomas y conociendo gente nueva.</p>
|
||||
|
||||
<div class="event-card">
|
||||
<h3>💬 Comparte tu Experiencia</h3>
|
||||
<p>{{customMessage}}</p>
|
||||
</div>
|
||||
|
||||
{{#if nextEventTitle}}
|
||||
<div class="event-card">
|
||||
<h3>📅 Próximo Evento</h3>
|
||||
<div class="event-detail"><strong>Evento:</strong> {{nextEventTitle}}</div>
|
||||
<div class="event-detail"><strong>Fecha:</strong> {{nextEventDate}}</div>
|
||||
<p style="text-align: center; margin-top: 16px;">
|
||||
<a href="{{nextEventUrl}}" class="btn">Reserva tu Lugar</a>
|
||||
</p>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<p>¡Síguenos en redes sociales para actualizaciones y fotos del evento!</p>
|
||||
<p>¡Nos vemos en el próximo Spanglish!</p>
|
||||
<p>El Equipo de Spanglish</p>
|
||||
`,
|
||||
bodyText: `Thank You for Joining Us!
|
||||
|
||||
Hi {{attendeeName}},
|
||||
|
||||
Thank you so much for being part of {{eventTitle}}! We hope you had a great time.
|
||||
|
||||
{{customMessage}}
|
||||
|
||||
Follow us on social media for updates and photos from the event!
|
||||
|
||||
See you at the next Spanglish!
|
||||
The Spanglish Team`,
|
||||
bodyTextEs: `¡Gracias por Unirte!
|
||||
|
||||
Hola {{attendeeName}},
|
||||
|
||||
¡Muchas gracias por ser parte de {{eventTitle}}! Esperamos que hayas pasado un gran momento.
|
||||
|
||||
{{customMessage}}
|
||||
|
||||
¡Síguenos en redes sociales para actualizaciones y fotos del evento!
|
||||
|
||||
¡Nos vemos en el próximo Spanglish!
|
||||
El Equipo de Spanglish`,
|
||||
description: 'Template for post-event follow-up emails (sent manually)',
|
||||
variables: [
|
||||
...commonVariables,
|
||||
...bookingVariables,
|
||||
{ name: 'customMessage', description: 'Custom message from admin', example: 'We would love to hear your feedback!' },
|
||||
{ name: 'nextEventTitle', description: 'Next event title (optional)', example: 'Spanglish Night - February' },
|
||||
{ name: 'nextEventDate', description: 'Next event date (optional)', example: 'February 25, 2026' },
|
||||
{ name: 'nextEventUrl', description: 'Next event booking URL (optional)', example: 'https://spanglish.com/book/...' },
|
||||
],
|
||||
isSystem: true,
|
||||
},
|
||||
{
|
||||
name: 'Custom Email',
|
||||
slug: 'custom-email',
|
||||
subject: '{{customSubject}}',
|
||||
subjectEs: '{{customSubject}}',
|
||||
bodyHtml: `
|
||||
<h2>{{customTitle}}</h2>
|
||||
<p>Hi {{attendeeName}},</p>
|
||||
|
||||
<div class="event-card">
|
||||
{{customMessage}}
|
||||
</div>
|
||||
|
||||
<p>The Spanglish Team</p>
|
||||
`,
|
||||
bodyHtmlEs: `
|
||||
<h2>{{customTitle}}</h2>
|
||||
<p>Hola {{attendeeName}},</p>
|
||||
|
||||
<div class="event-card">
|
||||
{{customMessage}}
|
||||
</div>
|
||||
|
||||
<p>El Equipo de Spanglish</p>
|
||||
`,
|
||||
bodyText: `{{customTitle}}
|
||||
|
||||
Hi {{attendeeName}},
|
||||
|
||||
{{customMessage}}
|
||||
|
||||
The Spanglish Team`,
|
||||
bodyTextEs: `{{customTitle}}
|
||||
|
||||
Hola {{attendeeName}},
|
||||
|
||||
{{customMessage}}
|
||||
|
||||
El Equipo de Spanglish`,
|
||||
description: 'Blank template for fully custom emails',
|
||||
variables: [
|
||||
...commonVariables,
|
||||
{ name: 'attendeeName', description: 'Recipient name', example: 'John Doe' },
|
||||
{ name: 'customSubject', description: 'Email subject', example: 'Special Announcement' },
|
||||
{ name: 'customTitle', description: 'Email title/heading', example: 'Special Announcement' },
|
||||
{ name: 'customMessage', description: 'Email body content (supports HTML)', example: '<p>Your message here...</p>' },
|
||||
],
|
||||
isSystem: true,
|
||||
},
|
||||
];
|
||||
|
||||
// Helper function to replace template variables
|
||||
export function replaceTemplateVariables(template: string, variables: Record<string, any>): string {
|
||||
let result = template;
|
||||
|
||||
// Handle conditional blocks {{#if variable}}...{{/if}}
|
||||
const conditionalRegex = /\{\{#if\s+(\w+)\}\}([\s\S]*?)\{\{\/if\}\}/g;
|
||||
result = result.replace(conditionalRegex, (match, varName, content) => {
|
||||
return variables[varName] ? content : '';
|
||||
});
|
||||
|
||||
// Replace simple variables {{variable}}
|
||||
const variableRegex = /\{\{(\w+)\}\}/g;
|
||||
result = result.replace(variableRegex, (match, varName) => {
|
||||
return variables[varName] !== undefined ? String(variables[varName]) : match;
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Helper to wrap content in the base template
|
||||
export function wrapInBaseTemplate(content: string, variables: Record<string, any>): string {
|
||||
const wrappedContent = baseEmailWrapper.replace('{{content}}', content);
|
||||
return replaceTemplateVariables(wrappedContent, variables);
|
||||
}
|
||||
|
||||
// Get all available variables for a template by slug
|
||||
export function getTemplateVariables(slug: string): EmailVariable[] {
|
||||
const template = defaultTemplates.find(t => t.slug === slug);
|
||||
return template?.variables || commonVariables;
|
||||
}
|
||||
Reference in New Issue
Block a user