Files
Gesti-n-Reservas-Naturcalab…/apps/api/scripts/send-test-teneriffa-variants.mjs
Kilian 4ce80b8fc0 feat: horarios opcionales en reservas, calendarios en lunes y emails filtrados
- Reservas: campos opcionales start_time/end_time (migración 011, schema natur_reservas)
  + toggle en el modal y detección de solapamiento por horario cuando ambas reservas
  los tienen definidos. Permite encajar varios eventos el mismo día.
- Calendario mensual y anual ahora empiezan en lunes; vista móvil incluida.
- Celdas con varios eventos el mismo día se dividen en franjas horizontales
  mostrando el horario; las reservas multi-día siguen ocupando la celda completa.
- Modal: reset de campos vacíos (client_name, fechas, factura) para evitar que el
  nombre de la última reserva se filtre al crear una nueva.
- Emails: las modificaciones solo disparan correo cuando cambian fechas u horas;
  el correo a Teneriffa pasa a formato reducido (solo fechas + propiedad) mientras
  que Natur sigue recibiendo el detalle completo. Mantenimiento sin cambios.
- CLAUDE.md con guía operativa (schema natur_reservas, stack, convenciones).
- Scripts de preview/envío de emails para pruebas.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 11:53:34 +01:00

51 lines
2.6 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Envía 3 ejemplos del correo minimalista de Teneriffa: nueva, modificada, cancelada.
// Uso: N8N_EMAIL_WEBHOOK_URL=... node apps/api/scripts/send-test-teneriffa-variants.mjs <destino>
const WEBHOOK = process.env.N8N_EMAIL_WEBHOOK_URL;
const FROM = process.env.EMAIL_FROM ?? 'Naturcalabacera <reservas@naturcalabacera.com>';
const TO = process.argv[2] ?? 'kilian.parraga@gmail.com';
if (!WEBHOOK) { console.error('Falta N8N_EMAIL_WEBHOOK_URL'); process.exit(1); }
function renderTeneriffaMinimal(actionLabel, dateRange, property, cancelled = false) {
const accent = cancelled ? '#ef4444' : actionLabel === 'Nueva Reserva' ? '#3b82f6' : '#f59e0b';
return `<!DOCTYPE html>
<html lang="es"><head><meta charset="UTF-8"></head>
<body style="font-family:Arial,sans-serif;background:#f4f4f4;margin:0;padding:24px;">
<div style="max-width:520px;margin:0 auto;background:#fff;border-radius:12px;overflow:hidden;box-shadow:0 2px 8px rgba(0,0,0,0.08);">
<div style="background:${accent};color:#fff;padding:20px 24px;">
<p style="margin:0;font-size:11px;text-transform:uppercase;letter-spacing:0.1em;opacity:0.85;font-weight:700;">${actionLabel}</p>
</div>
<div style="padding:24px;">
<p style="margin:0 0 6px;font-size:11px;text-transform:uppercase;letter-spacing:0.06em;color:#9ca3af;font-weight:700;">Fechas</p>
<p style="margin:0 0 18px;font-size:18px;font-weight:800;color:#111;">${dateRange}</p>
<p style="margin:0 0 6px;font-size:11px;text-transform:uppercase;letter-spacing:0.06em;color:#9ca3af;font-weight:700;">Propiedad</p>
<p style="margin:0;font-size:16px;font-weight:700;color:#111;">${property}</p>
</div>
</div>
</body></html>`;
}
async function send(subject, html) {
const res = await fetch(WEBHOOK, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ to: TO, subject, html, from: FROM }),
});
const text = await res.text().catch(() => '');
return { ok: res.ok, status: res.status, body: text.slice(0, 200) };
}
const cases = [
{ tag: 'NUEVA RESERVA', label: 'Nueva Reserva', range: '03 jul 2026 10 jul 2026', prop: 'La Esquinita' },
{ tag: 'MODIFICADA', label: 'Reserva Modificada', range: '03 jul 2026 12 jul 2026', prop: 'La Esquinita' },
{ tag: 'CANCELADA', label: 'Reserva Cancelada', range: '03 jul 2026 12 jul 2026', prop: 'La Esquinita', cancelled: true },
];
for (const c of cases) {
const subject = `[${c.tag}] ${c.range} · ${c.prop}`;
const html = renderTeneriffaMinimal(c.label, c.range, c.prop, c.cancelled);
const r = await send(subject, html);
console.log(c.tag.padEnd(15), r);
}