Add full SEO optimization for Spanglish social and language events
- Add comprehensive metadata to root layout with Open Graph, Twitter cards - Create dynamic sitemap.ts for all pages and events - Create robots.ts with proper allow/disallow rules - Add JSON-LD Event structured data to event detail pages - Add page-specific metadata to events, community, contact, FAQ pages - Add FAQ structured data schema - Update footer with local SEO text for Asunción, Paraguay - Add web manifest for mobile SEO - Create 404 page with proper noindex - Optimize image alt text and add lazy loading - Add NEXT_PUBLIC_SITE_URL env variable - Add about/ folder to gitignore
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
// Email service for Spanglish platform
|
||||
// Supports multiple email providers: Resend, SMTP (Nodemailer)
|
||||
|
||||
import { db, emailTemplates, emailLogs, events, tickets, payments, users } from '../db/index.js';
|
||||
import { db, emailTemplates, emailLogs, events, tickets, payments, users, paymentOptions, eventPaymentOverrides } from '../db/index.js';
|
||||
import { eq, and } from 'drizzle-orm';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { getNow } from './utils.js';
|
||||
@@ -372,17 +372,17 @@ export const emailService = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Seed default templates if they don't exist
|
||||
* Seed default templates if they don't exist, and update system templates with latest content
|
||||
*/
|
||||
async seedDefaultTemplates(): Promise<void> {
|
||||
console.log('[Email] Checking for default templates...');
|
||||
|
||||
for (const template of defaultTemplates) {
|
||||
const existing = await this.getTemplate(template.slug);
|
||||
const now = getNow();
|
||||
|
||||
if (!existing) {
|
||||
console.log(`[Email] Creating template: ${template.name}`);
|
||||
const now = getNow();
|
||||
|
||||
await (db as any).insert(emailTemplates).values({
|
||||
id: nanoid(),
|
||||
@@ -401,6 +401,24 @@ export const emailService = {
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
});
|
||||
} else if (existing.isSystem) {
|
||||
// Update system templates with latest content from defaults
|
||||
console.log(`[Email] Updating system template: ${template.name}`);
|
||||
|
||||
await (db as any)
|
||||
.update(emailTemplates)
|
||||
.set({
|
||||
subject: template.subject,
|
||||
subjectEs: template.subjectEs,
|
||||
bodyHtml: template.bodyHtml,
|
||||
bodyHtmlEs: template.bodyHtmlEs,
|
||||
bodyText: template.bodyText,
|
||||
bodyTextEs: template.bodyTextEs,
|
||||
description: template.description,
|
||||
variables: JSON.stringify(template.variables),
|
||||
updatedAt: now,
|
||||
})
|
||||
.where(eq((emailTemplates as any).slug, template.slug));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -615,6 +633,159 @@ export const emailService = {
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Get merged payment configuration for an event (global + overrides)
|
||||
*/
|
||||
async getPaymentConfig(eventId: string): Promise<Record<string, any>> {
|
||||
// Get global options
|
||||
const globalOptions = await (db as any)
|
||||
.select()
|
||||
.from(paymentOptions)
|
||||
.get();
|
||||
|
||||
// Get event overrides
|
||||
const overrides = await (db as any)
|
||||
.select()
|
||||
.from(eventPaymentOverrides)
|
||||
.where(eq((eventPaymentOverrides as any).eventId, eventId))
|
||||
.get();
|
||||
|
||||
// Defaults
|
||||
const defaults = {
|
||||
tpagoEnabled: false,
|
||||
tpagoLink: null,
|
||||
tpagoInstructions: null,
|
||||
tpagoInstructionsEs: null,
|
||||
bankTransferEnabled: false,
|
||||
bankName: null,
|
||||
bankAccountHolder: null,
|
||||
bankAccountNumber: null,
|
||||
bankAlias: null,
|
||||
bankPhone: null,
|
||||
bankNotes: null,
|
||||
bankNotesEs: null,
|
||||
};
|
||||
|
||||
const global = globalOptions || defaults;
|
||||
|
||||
// Merge: override values take precedence if they're not null/undefined
|
||||
return {
|
||||
tpagoEnabled: overrides?.tpagoEnabled ?? global.tpagoEnabled,
|
||||
tpagoLink: overrides?.tpagoLink ?? global.tpagoLink,
|
||||
tpagoInstructions: overrides?.tpagoInstructions ?? global.tpagoInstructions,
|
||||
tpagoInstructionsEs: overrides?.tpagoInstructionsEs ?? global.tpagoInstructionsEs,
|
||||
bankTransferEnabled: overrides?.bankTransferEnabled ?? global.bankTransferEnabled,
|
||||
bankName: overrides?.bankName ?? global.bankName,
|
||||
bankAccountHolder: overrides?.bankAccountHolder ?? global.bankAccountHolder,
|
||||
bankAccountNumber: overrides?.bankAccountNumber ?? global.bankAccountNumber,
|
||||
bankAlias: overrides?.bankAlias ?? global.bankAlias,
|
||||
bankPhone: overrides?.bankPhone ?? global.bankPhone,
|
||||
bankNotes: overrides?.bankNotes ?? global.bankNotes,
|
||||
bankNotesEs: overrides?.bankNotesEs ?? global.bankNotesEs,
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Send payment instructions email (for TPago or Bank Transfer)
|
||||
* This email is sent immediately after user clicks "Continue to Payment"
|
||||
*/
|
||||
async sendPaymentInstructions(ticketId: string): Promise<{ success: boolean; error?: string }> {
|
||||
// Get ticket
|
||||
const ticket = await (db as any)
|
||||
.select()
|
||||
.from(tickets)
|
||||
.where(eq((tickets as any).id, ticketId))
|
||||
.get();
|
||||
|
||||
if (!ticket) {
|
||||
return { success: false, error: 'Ticket not found' };
|
||||
}
|
||||
|
||||
// Get event
|
||||
const event = await (db as any)
|
||||
.select()
|
||||
.from(events)
|
||||
.where(eq((events as any).id, ticket.eventId))
|
||||
.get();
|
||||
|
||||
if (!event) {
|
||||
return { success: false, error: 'Event not found' };
|
||||
}
|
||||
|
||||
// Get payment
|
||||
const payment = await (db as any)
|
||||
.select()
|
||||
.from(payments)
|
||||
.where(eq((payments as any).ticketId, ticketId))
|
||||
.get();
|
||||
|
||||
if (!payment) {
|
||||
return { success: false, error: 'Payment not found' };
|
||||
}
|
||||
|
||||
// Only send for manual payment methods
|
||||
if (!['bank_transfer', 'tpago'].includes(payment.provider)) {
|
||||
return { success: false, error: 'Payment instructions email only for bank_transfer or tpago' };
|
||||
}
|
||||
|
||||
// Get merged payment config for this event
|
||||
const paymentConfig = await this.getPaymentConfig(event.id);
|
||||
|
||||
const locale = ticket.preferredLanguage || 'en';
|
||||
const eventTitle = locale === 'es' && event.titleEs ? event.titleEs : event.title;
|
||||
const attendeeFullName = `${ticket.attendeeFirstName} ${ticket.attendeeLastName || ''}`.trim();
|
||||
|
||||
// Generate a payment reference using ticket ID
|
||||
const paymentReference = `SPG-${ticket.id.substring(0, 8).toUpperCase()}`;
|
||||
|
||||
// Generate the booking URL for returning to payment page
|
||||
const frontendUrl = process.env.FRONTEND_URL || 'https://spanglish.com';
|
||||
const bookingUrl = `${frontendUrl}/booking/${ticket.id}?step=payment`;
|
||||
|
||||
// Determine which template to use
|
||||
const templateSlug = payment.provider === 'tpago'
|
||||
? 'payment-instructions-tpago'
|
||||
: 'payment-instructions-bank-transfer';
|
||||
|
||||
// Build variables based on payment method
|
||||
const variables: Record<string, any> = {
|
||||
attendeeName: attendeeFullName,
|
||||
attendeeEmail: ticket.attendeeEmail,
|
||||
ticketId: ticket.id,
|
||||
eventTitle,
|
||||
eventDate: this.formatDate(event.startDatetime, locale),
|
||||
eventTime: this.formatTime(event.startDatetime, locale),
|
||||
eventLocation: event.location,
|
||||
eventLocationUrl: event.locationUrl || '',
|
||||
paymentAmount: this.formatCurrency(event.price, event.currency),
|
||||
paymentReference,
|
||||
bookingUrl,
|
||||
};
|
||||
|
||||
// Add payment-method specific variables
|
||||
if (payment.provider === 'tpago') {
|
||||
variables.tpagoLink = paymentConfig.tpagoLink || '';
|
||||
} else {
|
||||
// Bank transfer
|
||||
variables.bankName = paymentConfig.bankName || '';
|
||||
variables.bankAccountHolder = paymentConfig.bankAccountHolder || '';
|
||||
variables.bankAccountNumber = paymentConfig.bankAccountNumber || '';
|
||||
variables.bankAlias = paymentConfig.bankAlias || '';
|
||||
variables.bankPhone = paymentConfig.bankPhone || '';
|
||||
}
|
||||
|
||||
console.log(`[Email] Sending payment instructions email (${payment.provider}) to ${ticket.attendeeEmail}`);
|
||||
|
||||
return this.sendTemplateEmail({
|
||||
templateSlug,
|
||||
to: ticket.attendeeEmail,
|
||||
toName: attendeeFullName,
|
||||
locale,
|
||||
eventId: event.id,
|
||||
variables,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Send custom email to event attendees
|
||||
*/
|
||||
|
||||
@@ -51,6 +51,16 @@ export const paymentVariables: EmailVariable[] = [
|
||||
{ name: 'paymentDate', description: 'Payment date', example: 'January 28, 2026' },
|
||||
];
|
||||
|
||||
// Payment instructions variables (for manual payment methods)
|
||||
export const paymentInstructionsVariables: EmailVariable[] = [
|
||||
{ name: 'tpagoLink', description: 'TPago payment link', example: 'https://tpago.com.py/...' },
|
||||
{ name: 'bankName', description: 'Bank name', example: 'Banco Itaú' },
|
||||
{ name: 'bankAccountHolder', description: 'Account holder name', example: 'Spanglish SRL' },
|
||||
{ name: 'bankAccountNumber', description: 'Bank account number', example: '1234567890' },
|
||||
{ name: 'bankAlias', description: 'Bank alias or phone', example: '0981-123-456' },
|
||||
{ name: 'bankPhone', description: 'Bank phone number', example: '0981-123-456' },
|
||||
];
|
||||
|
||||
// Base HTML wrapper for all emails
|
||||
export const baseEmailWrapper = `
|
||||
<!DOCTYPE html>
|
||||
@@ -641,6 +651,319 @@ El Equipo de Spanglish`,
|
||||
],
|
||||
isSystem: true,
|
||||
},
|
||||
{
|
||||
name: 'Payment Instructions - TPago',
|
||||
slug: 'payment-instructions-tpago',
|
||||
subject: 'Complete your payment for Spanglish',
|
||||
subjectEs: 'Completa tu pago para Spanglish',
|
||||
bodyHtml: `
|
||||
<h2>You're Almost In! 🎉</h2>
|
||||
<p>Hi {{attendeeName}},</p>
|
||||
<p>To complete your booking for:</p>
|
||||
|
||||
<div class="event-card">
|
||||
<h3>{{eventTitle}}</h3>
|
||||
<div class="event-detail"><strong>📅 Date:</strong> {{eventDate}}</div>
|
||||
<div class="event-detail"><strong>📍 Location:</strong> {{eventLocation}}</div>
|
||||
<div class="event-detail"><strong>💰 Amount:</strong> {{paymentAmount}}</div>
|
||||
</div>
|
||||
|
||||
<p>Please complete your payment using TPago at the link below:</p>
|
||||
|
||||
<p style="text-align: center; margin: 24px 0;">
|
||||
<a href="{{tpagoLink}}" class="btn" style="background-color: #3b82f6;">👉 Pay with Card</a>
|
||||
</p>
|
||||
<p style="text-align: center; font-size: 12px; color: #6b7280; margin-top: -16px;">
|
||||
If the button doesn't work: <a href="{{tpagoLink}}" style="color: #3b82f6; word-break: break-all;">{{tpagoLink}}</a>
|
||||
</p>
|
||||
|
||||
<div class="note">
|
||||
<strong>After completing the payment:</strong><br>
|
||||
Return to the website and click <strong>"I have paid"</strong> or click the button below to notify us.
|
||||
</div>
|
||||
|
||||
<p style="text-align: center; margin: 24px 0;">
|
||||
<a href="{{bookingUrl}}" class="btn">✓ I Have Paid</a>
|
||||
</p>
|
||||
<p style="text-align: center; font-size: 12px; color: #6b7280; margin-top: -16px;">
|
||||
Or use this link: <a href="{{bookingUrl}}" style="color: #f59e0b; word-break: break-all;">{{bookingUrl}}</a>
|
||||
</p>
|
||||
|
||||
<p>Your spot will be confirmed once we verify the payment.</p>
|
||||
|
||||
<p>If you have any questions, just reply to this email.</p>
|
||||
<p>See you soon,<br>Spanglish</p>
|
||||
`,
|
||||
bodyHtmlEs: `
|
||||
<h2>¡Ya Casi Estás! 🎉</h2>
|
||||
<p>Hola {{attendeeName}},</p>
|
||||
<p>Para completar tu reserva para:</p>
|
||||
|
||||
<div class="event-card">
|
||||
<h3>{{eventTitle}}</h3>
|
||||
<div class="event-detail"><strong>📅 Fecha:</strong> {{eventDate}}</div>
|
||||
<div class="event-detail"><strong>📍 Ubicación:</strong> {{eventLocation}}</div>
|
||||
<div class="event-detail"><strong>💰 Monto:</strong> {{paymentAmount}}</div>
|
||||
</div>
|
||||
|
||||
<p>Por favor completa tu pago usando TPago en el siguiente enlace:</p>
|
||||
|
||||
<p style="text-align: center; margin: 24px 0;">
|
||||
<a href="{{tpagoLink}}" class="btn" style="background-color: #3b82f6;">👉 Pagar con Tarjeta</a>
|
||||
</p>
|
||||
<p style="text-align: center; font-size: 12px; color: #6b7280; margin-top: -16px;">
|
||||
Si el botón no funciona: <a href="{{tpagoLink}}" style="color: #3b82f6; word-break: break-all;">{{tpagoLink}}</a>
|
||||
</p>
|
||||
|
||||
<div class="note">
|
||||
<strong>Después de completar el pago:</strong><br>
|
||||
Vuelve al sitio web y haz clic en <strong>"Ya pagué"</strong> o haz clic en el botón de abajo para notificarnos.
|
||||
</div>
|
||||
|
||||
<p style="text-align: center; margin: 24px 0;">
|
||||
<a href="{{bookingUrl}}" class="btn">✓ Ya Pagué</a>
|
||||
</p>
|
||||
<p style="text-align: center; font-size: 12px; color: #6b7280; margin-top: -16px;">
|
||||
O usa este enlace: <a href="{{bookingUrl}}" style="color: #f59e0b; word-break: break-all;">{{bookingUrl}}</a>
|
||||
</p>
|
||||
|
||||
<p>Tu lugar será confirmado una vez que verifiquemos el pago.</p>
|
||||
|
||||
<p>Si tienes alguna pregunta, simplemente responde a este email.</p>
|
||||
<p>¡Nos vemos pronto!<br>Spanglish</p>
|
||||
`,
|
||||
bodyText: `You're Almost In!
|
||||
|
||||
Hi {{attendeeName}},
|
||||
|
||||
To complete your booking for:
|
||||
|
||||
{{eventTitle}}
|
||||
📅 Date: {{eventDate}}
|
||||
📍 Location: {{eventLocation}}
|
||||
💰 Amount: {{paymentAmount}}
|
||||
|
||||
Please complete your payment using TPago at the link below:
|
||||
|
||||
👉 Pay with card: {{tpagoLink}}
|
||||
|
||||
After completing the payment, return to the website and click "I have paid" or use this link to notify us:
|
||||
|
||||
{{bookingUrl}}
|
||||
|
||||
Your spot will be confirmed once we verify the payment.
|
||||
|
||||
If you have any questions, just reply to this email.
|
||||
|
||||
See you soon,
|
||||
Spanglish`,
|
||||
bodyTextEs: `¡Ya Casi Estás!
|
||||
|
||||
Hola {{attendeeName}},
|
||||
|
||||
Para completar tu reserva para:
|
||||
|
||||
{{eventTitle}}
|
||||
📅 Fecha: {{eventDate}}
|
||||
📍 Ubicación: {{eventLocation}}
|
||||
💰 Monto: {{paymentAmount}}
|
||||
|
||||
Por favor completa tu pago usando TPago en el siguiente enlace:
|
||||
|
||||
👉 Pagar con tarjeta: {{tpagoLink}}
|
||||
|
||||
Después de completar el pago, vuelve al sitio web y haz clic en "Ya pagué" o usa este enlace para notificarnos:
|
||||
|
||||
{{bookingUrl}}
|
||||
|
||||
Tu lugar será confirmado una vez que verifiquemos el pago.
|
||||
|
||||
Si tienes alguna pregunta, simplemente responde a este email.
|
||||
|
||||
¡Nos vemos pronto!
|
||||
Spanglish`,
|
||||
description: 'Sent when user selects TPago payment and clicks continue to payment',
|
||||
variables: [
|
||||
...commonVariables,
|
||||
...bookingVariables,
|
||||
{ name: 'paymentAmount', description: 'Payment amount with currency', example: '50,000 PYG' },
|
||||
{ name: 'tpagoLink', description: 'TPago payment link', example: 'https://tpago.com.py/...' },
|
||||
{ name: 'bookingUrl', description: 'URL to return to payment page', example: 'https://spanglish.com/booking/abc123?step=payment' },
|
||||
],
|
||||
isSystem: true,
|
||||
},
|
||||
{
|
||||
name: 'Payment Instructions - Bank Transfer',
|
||||
slug: 'payment-instructions-bank-transfer',
|
||||
subject: 'Bank transfer details for your Spanglish booking',
|
||||
subjectEs: 'Datos de transferencia para tu reserva en Spanglish',
|
||||
bodyHtml: `
|
||||
<h2>Thanks for Joining Spanglish! 🙂</h2>
|
||||
<p>Hi {{attendeeName}},</p>
|
||||
<p>Here are the bank transfer details for your booking:</p>
|
||||
|
||||
<div class="event-card">
|
||||
<h3>{{eventTitle}}</h3>
|
||||
<div class="event-detail"><strong>📅 Date:</strong> {{eventDate}}</div>
|
||||
<div class="event-detail"><strong>💰 Amount:</strong> {{paymentAmount}}</div>
|
||||
</div>
|
||||
|
||||
<div class="event-card" style="background-color: #ecfdf5; border: 1px solid #10b981;">
|
||||
<h3 style="color: #059669; margin-top: 0;">🏦 Bank Transfer Details</h3>
|
||||
{{#if bankName}}
|
||||
<div class="event-detail"><strong>Bank:</strong> {{bankName}}</div>
|
||||
{{/if}}
|
||||
{{#if bankAccountHolder}}
|
||||
<div class="event-detail"><strong>Account Holder:</strong> {{bankAccountHolder}}</div>
|
||||
{{/if}}
|
||||
{{#if bankAccountNumber}}
|
||||
<div class="event-detail"><strong>Account Number:</strong> <span style="font-family: monospace;">{{bankAccountNumber}}</span></div>
|
||||
{{/if}}
|
||||
{{#if bankAlias}}
|
||||
<div class="event-detail"><strong>Alias:</strong> {{bankAlias}}</div>
|
||||
{{/if}}
|
||||
{{#if bankPhone}}
|
||||
<div class="event-detail"><strong>Phone:</strong> {{bankPhone}}</div>
|
||||
{{/if}}
|
||||
<div class="event-detail"><strong>Reference:</strong> <span style="font-family: monospace; background: #fff; padding: 2px 6px; border-radius: 4px;">{{paymentReference}}</span></div>
|
||||
</div>
|
||||
|
||||
<div class="note">
|
||||
<strong>After making the transfer:</strong><br>
|
||||
Return to the website and click <strong>"I have paid"</strong> or click the button below to notify us.
|
||||
</div>
|
||||
|
||||
<p style="text-align: center; margin: 24px 0;">
|
||||
<a href="{{bookingUrl}}" class="btn">✓ I Have Paid</a>
|
||||
</p>
|
||||
<p style="text-align: center; font-size: 12px; color: #6b7280; margin-top: -16px;">
|
||||
Or use this link: <a href="{{bookingUrl}}" style="color: #f59e0b; word-break: break-all;">{{bookingUrl}}</a>
|
||||
</p>
|
||||
|
||||
<p>We'll confirm your spot as soon as the payment is received.</p>
|
||||
|
||||
<p>If you need help, reply to this email.</p>
|
||||
<p>See you at the event,<br>Spanglish</p>
|
||||
`,
|
||||
bodyHtmlEs: `
|
||||
<h2>¡Gracias por unirte a Spanglish! 🙂</h2>
|
||||
<p>Hola {{attendeeName}},</p>
|
||||
<p>Aquí están los datos de transferencia para tu reserva:</p>
|
||||
|
||||
<div class="event-card">
|
||||
<h3>{{eventTitle}}</h3>
|
||||
<div class="event-detail"><strong>📅 Fecha:</strong> {{eventDate}}</div>
|
||||
<div class="event-detail"><strong>💰 Monto:</strong> {{paymentAmount}}</div>
|
||||
</div>
|
||||
|
||||
<div class="event-card" style="background-color: #ecfdf5; border: 1px solid #10b981;">
|
||||
<h3 style="color: #059669; margin-top: 0;">🏦 Datos de Transferencia</h3>
|
||||
{{#if bankName}}
|
||||
<div class="event-detail"><strong>Banco:</strong> {{bankName}}</div>
|
||||
{{/if}}
|
||||
{{#if bankAccountHolder}}
|
||||
<div class="event-detail"><strong>Titular:</strong> {{bankAccountHolder}}</div>
|
||||
{{/if}}
|
||||
{{#if bankAccountNumber}}
|
||||
<div class="event-detail"><strong>Nro. Cuenta:</strong> <span style="font-family: monospace;">{{bankAccountNumber}}</span></div>
|
||||
{{/if}}
|
||||
{{#if bankAlias}}
|
||||
<div class="event-detail"><strong>Alias:</strong> {{bankAlias}}</div>
|
||||
{{/if}}
|
||||
{{#if bankPhone}}
|
||||
<div class="event-detail"><strong>Teléfono:</strong> {{bankPhone}}</div>
|
||||
{{/if}}
|
||||
<div class="event-detail"><strong>Referencia:</strong> <span style="font-family: monospace; background: #fff; padding: 2px 6px; border-radius: 4px;">{{paymentReference}}</span></div>
|
||||
</div>
|
||||
|
||||
<div class="note">
|
||||
<strong>Después de realizar la transferencia:</strong><br>
|
||||
Vuelve al sitio web y haz clic en <strong>"Ya pagué"</strong> o haz clic en el botón de abajo para notificarnos.
|
||||
</div>
|
||||
|
||||
<p style="text-align: center; margin: 24px 0;">
|
||||
<a href="{{bookingUrl}}" class="btn">✓ Ya Pagué</a>
|
||||
</p>
|
||||
<p style="text-align: center; font-size: 12px; color: #6b7280; margin-top: -16px;">
|
||||
O usa este enlace: <a href="{{bookingUrl}}" style="color: #f59e0b; word-break: break-all;">{{bookingUrl}}</a>
|
||||
</p>
|
||||
|
||||
<p>Confirmaremos tu lugar tan pronto como recibamos el pago.</p>
|
||||
|
||||
<p>Si necesitas ayuda, responde a este email.</p>
|
||||
<p>¡Nos vemos en el evento!<br>Spanglish</p>
|
||||
`,
|
||||
bodyText: `Thanks for Joining Spanglish!
|
||||
|
||||
Hi {{attendeeName}},
|
||||
|
||||
Here are the bank transfer details for your booking:
|
||||
|
||||
{{eventTitle}}
|
||||
📅 Date: {{eventDate}}
|
||||
💰 Amount: {{paymentAmount}}
|
||||
|
||||
Bank Transfer Details:
|
||||
- Bank: {{bankName}}
|
||||
- Account Holder: {{bankAccountHolder}}
|
||||
- Account Number: {{bankAccountNumber}}
|
||||
- Alias: {{bankAlias}}
|
||||
- Phone: {{bankPhone}}
|
||||
- Reference: {{paymentReference}}
|
||||
|
||||
After making the transfer, return to the website and click "I have paid" or use this link to notify us:
|
||||
|
||||
{{bookingUrl}}
|
||||
|
||||
We'll confirm your spot as soon as the payment is received.
|
||||
|
||||
If you need help, reply to this email.
|
||||
|
||||
See you at the event,
|
||||
Spanglish`,
|
||||
bodyTextEs: `¡Gracias por unirte a Spanglish!
|
||||
|
||||
Hola {{attendeeName}},
|
||||
|
||||
Aquí están los datos de transferencia para tu reserva:
|
||||
|
||||
{{eventTitle}}
|
||||
📅 Fecha: {{eventDate}}
|
||||
💰 Monto: {{paymentAmount}}
|
||||
|
||||
Datos de Transferencia:
|
||||
- Banco: {{bankName}}
|
||||
- Titular: {{bankAccountHolder}}
|
||||
- Nro. Cuenta: {{bankAccountNumber}}
|
||||
- Alias: {{bankAlias}}
|
||||
- Teléfono: {{bankPhone}}
|
||||
- Referencia: {{paymentReference}}
|
||||
|
||||
Después de realizar la transferencia, vuelve al sitio web y haz clic en "Ya pagué" o usa este enlace para notificarnos:
|
||||
|
||||
{{bookingUrl}}
|
||||
|
||||
Confirmaremos tu lugar tan pronto como recibamos el pago.
|
||||
|
||||
Si necesitas ayuda, responde a este email.
|
||||
|
||||
¡Nos vemos en el evento!
|
||||
Spanglish`,
|
||||
description: 'Sent when user selects bank transfer payment and clicks continue to payment',
|
||||
variables: [
|
||||
...commonVariables,
|
||||
...bookingVariables,
|
||||
{ name: 'paymentAmount', description: 'Payment amount with currency', example: '50,000 PYG' },
|
||||
{ name: 'paymentReference', description: 'Unique payment reference', example: 'SPG-ABC123' },
|
||||
{ name: 'bankName', description: 'Bank name', example: 'Banco Itaú' },
|
||||
{ name: 'bankAccountHolder', description: 'Account holder name', example: 'Spanglish SRL' },
|
||||
{ name: 'bankAccountNumber', description: 'Bank account number', example: '1234567890' },
|
||||
{ name: 'bankAlias', description: 'Bank alias', example: 'spanglish.py' },
|
||||
{ name: 'bankPhone', description: 'Bank phone number', example: '0981-123-456' },
|
||||
{ name: 'bookingUrl', description: 'URL to return to payment page', example: 'https://spanglish.com/booking/abc123?step=payment' },
|
||||
],
|
||||
isSystem: true,
|
||||
},
|
||||
];
|
||||
|
||||
// Helper function to replace template variables
|
||||
|
||||
Reference in New Issue
Block a user