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:
Michilis
2026-06-25 07:12:59 +00:00
co-authored by Cursor
parent f0e2de2834
commit 613bd7be1d
75 changed files with 7702 additions and 5580 deletions
@@ -0,0 +1,131 @@
import toast from 'react-hot-toast';
import { PaymentOptionsConfig } from '@/lib/api';
import {
CreditCardIcon,
BanknotesIcon,
BoltIcon,
BuildingLibraryIcon,
} from '@heroicons/react/24/outline';
import type { PaymentMethod, BookingResult } from '../_types';
export const rucPattern = /^\d{6,10}$/;
/** Format RUC input: digits only, max 10. */
export function formatRuc(value: string): string {
return value.replace(/\D/g, '').slice(0, 10);
}
/** Truncate a long invoice string for display. */
export function truncateInvoice(invoice: string, chars: number = 20): string {
if (invoice.length <= chars * 2) return invoice;
return `${invoice.slice(0, chars)}...${invoice.slice(-chars)}`;
}
/** Copy a Lightning invoice to the clipboard with localized feedback. */
export function copyInvoiceToClipboard(invoice: string, locale: string): void {
navigator.clipboard.writeText(invoice).then(() => {
toast.success(locale === 'es' ? '¡Copiado!' : 'Copied!');
}).catch(() => {
toast.error(locale === 'es' ? 'Error al copiar' : 'Failed to copy');
});
}
export interface PaymentMethodOption {
id: PaymentMethod;
icon: typeof CreditCardIcon;
label: string;
description: string;
badge?: string;
}
/** Build the list of selectable payment methods from the event config. */
export function buildPaymentMethods(
paymentConfig: PaymentOptionsConfig | null,
locale: string
): PaymentMethodOption[] {
const paymentMethods: PaymentMethodOption[] = [];
if (paymentConfig?.lightningEnabled) {
paymentMethods.push({
id: 'lightning',
icon: BoltIcon,
label: 'Bitcoin Lightning',
description: locale === 'es' ? 'Pago instantáneo con Bitcoin' : 'Instant payment with Bitcoin',
badge: locale === 'es' ? 'Instantáneo' : 'Instant',
});
}
if (paymentConfig?.tpagoEnabled) {
paymentMethods.push({
id: 'tpago',
icon: CreditCardIcon,
label: locale === 'es' ? 'TPago / Tarjetas de Crédito' : 'TPago / Credit Cards',
description: locale === 'es' ? 'Pagá con tarjetas de crédito locales o internacionales' : 'Pay with local or international credit cards',
badge: locale === 'es' ? 'Manual' : 'Manual',
});
}
if (paymentConfig?.bankTransferEnabled) {
paymentMethods.push({
id: 'bank_transfer',
icon: BuildingLibraryIcon,
label: locale === 'es' ? 'Transferencia Bancaria Local' : 'Local Bank Transfer',
description: locale === 'es' ? 'Pago por transferencia bancaria en Paraguay' : 'Pay via Paraguayan bank transfer',
badge: locale === 'es' ? 'Manual' : 'Manual',
});
}
if (paymentConfig?.cashEnabled) {
paymentMethods.push({
id: 'cash',
icon: BanknotesIcon,
label: locale === 'es' ? 'Efectivo en el Evento' : 'Cash at Event',
description: locale === 'es' ? 'Paga cuando llegues al evento' : 'Pay when you arrive at the event',
badge: locale === 'es' ? 'Manual' : 'Manual',
});
}
return paymentMethods;
}
export interface SuccessContent {
title: string;
description: string;
iconColor: string;
iconTextColor: string;
}
/** Resolve the success-screen copy based on the payment method used. */
export function getSuccessContent(
bookingResult: BookingResult | null,
locale: string,
t: (key: string) => string
): SuccessContent {
if (bookingResult?.paymentMethod === 'cash') {
return {
title: locale === 'es' ? '¡Reserva Recibida!' : 'Reservation Received!',
description: locale === 'es'
? 'Tu lugar está reservado. El pago se realizará en el evento.'
: 'Your spot is reserved. Payment will be collected at the event.',
iconColor: 'bg-yellow-100',
iconTextColor: 'text-yellow-600',
};
}
if (bookingResult?.paymentMethod === 'lightning') {
// For Lightning, if we're on success step, payment was confirmed
return {
title: locale === 'es' ? '¡Pago Confirmado!' : 'Payment Confirmed!',
description: locale === 'es'
? '¡Tu reserva está confirmada! Te esperamos en el evento.'
: 'Your booking is confirmed! See you at the event.',
iconColor: 'bg-green-100',
iconTextColor: 'text-green-600',
};
}
return {
title: t('booking.success.title'),
description: t('booking.success.description'),
iconColor: 'bg-green-100',
iconTextColor: 'text-green-600',
};
}