Refactor monolithic modules and harden booking, email, and auth infrastructure.
Split oversized frontend API client, email service, and admin/booking pages into focused modules while preserving import surfaces, and add Redis-backed queues, stale booking cleanup, stronger auth, and scale deployment configs. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
// Shared formatting helpers and common template variables for emails.
|
||||
|
||||
import { db, dbGet, siteSettings } from '../../db/index.js';
|
||||
import { getCache } from '../stores/cache.js';
|
||||
|
||||
/**
|
||||
* Get common variables for all emails
|
||||
*/
|
||||
export function getCommonVariables(): Record<string, string> {
|
||||
return {
|
||||
siteName: 'Spanglish',
|
||||
siteUrl: process.env.FRONTEND_URL || 'https://spanglish.com',
|
||||
currentYear: new Date().getFullYear().toString(),
|
||||
supportEmail: process.env.EMAIL_FROM || 'hello@spanglish.com',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the site timezone from settings (cached for performance).
|
||||
* Cached for a short TTL via the cache abstraction (in-memory or Redis).
|
||||
*/
|
||||
export async function getSiteTimezone(): Promise<string> {
|
||||
const cached = await getCache().get<string>('site:timezone');
|
||||
if (cached) return cached;
|
||||
|
||||
const settings = await dbGet<any>(
|
||||
(db as any).select().from(siteSettings).limit(1)
|
||||
);
|
||||
const timezone = settings?.timezone || 'America/Asuncion';
|
||||
await getCache().set('site:timezone', timezone, 60);
|
||||
return timezone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format date for emails using site timezone
|
||||
*/
|
||||
export function formatDate(dateStr: string, locale: string = 'en', timezone: string = 'America/Asuncion'): string {
|
||||
const date = new Date(dateStr);
|
||||
return date.toLocaleDateString(locale === 'es' ? 'es-ES' : 'en-US', {
|
||||
weekday: 'long',
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
timeZone: timezone,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Format time for emails using site timezone
|
||||
*/
|
||||
export function formatTime(dateStr: string, locale: string = 'en', timezone: string = 'America/Asuncion'): string {
|
||||
const date = new Date(dateStr);
|
||||
return date.toLocaleTimeString(locale === 'es' ? 'es-ES' : 'en-US', {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
timeZone: timezone,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Format currency for emails. Kept distinct from lib/utils.ts formatCurrency
|
||||
* because the email output format ("12.345 PYG" / "$10.00 USD") must not change.
|
||||
*/
|
||||
export function formatCurrency(amount: number, currency: string = 'PYG'): string {
|
||||
if (currency === 'PYG') {
|
||||
return `${amount.toLocaleString('es-PY')} PYG`;
|
||||
}
|
||||
return `$${amount.toFixed(2)} ${currency}`;
|
||||
}
|
||||
Reference in New Issue
Block a user