staging #75
|
|
@ -29,3 +29,4 @@ prisma/dev.db
|
||||||
# opencode - agentes y scripts locales (no subir a producción)
|
# opencode - agentes y scripts locales (no subir a producción)
|
||||||
opencode/
|
opencode/
|
||||||
.opencode/
|
.opencode/
|
||||||
|
docs/
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -9,17 +9,17 @@ const { props } = Astro.props;
|
||||||
<div class="container mx-auto">
|
<div class="container mx-auto">
|
||||||
<div class="grid md:grid-cols-2 min-w-0">
|
<div class="grid md:grid-cols-2 min-w-0">
|
||||||
<div class="bg-[#EBE5D0] p-6 md:p-12 lg:p-24 grid lg:grid-cols-2 min-w-0">
|
<div class="bg-[#EBE5D0] p-6 md:p-12 lg:p-24 grid lg:grid-cols-2 min-w-0">
|
||||||
<div class="flex flex-col justify-between min-h-full break-all">
|
<div class="flex flex-col justify-between min-h-full min-w-0">
|
||||||
<h2 class="text-5xl font-secondary text-tertiary font-bold">{tl("values.justice.title")}</h2>
|
<h2 class="text-3xl lg:text-2xl xl:text-3xl 2xl:text-5xl font-secondary text-tertiary font-bold wrap-break-word">{tl("values.justice.title")}</h2>
|
||||||
<p class="text-lg text-tertiary break-words">{tl("values.justice.text")}</p>
|
<p class="text-lg text-tertiary break-words">{tl("values.justice.text")}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-end justify-end min-h-full">
|
<div class="flex items-end justify-end min-h-full min-w-0 max-w-full">
|
||||||
<Icon name="icon_justice_1" class="text-6xl md:text-9xl text-tertiary" />
|
<Icon name="icon_justice_1" class="text-6xl md:text-9xl text-tertiary max-w-full h-auto" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-tertiary p-6 md:p-12 lg:p-24 grid lg:grid-cols-2 min-w-0">
|
<div class="bg-tertiary p-6 md:p-12 lg:p-24 grid lg:grid-cols-2 min-w-0">
|
||||||
<div class="flex flex-col justify-between min-h-full min-w-0 max-w-full">
|
<div class="flex flex-col justify-between min-h-full min-w-0 max-w-full">
|
||||||
<h2 class="text-5xl font-secondary font-bold text-[#CBA16A] break-all">{tl("values.integrity.title")}</h2>
|
<h2 class="text-3xl lg:text-2xl xl:text-3xl 2xl:text-5xl font-secondary font-bold text-[#CBA16A] wrap-break-word">{tl("values.integrity.title")}</h2>
|
||||||
<p class="text-[#CBA16A] text-lg break-words">{tl("values.integrity.text")}</p>
|
<p class="text-[#CBA16A] text-lg break-words">{tl("values.integrity.text")}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-end justify-end min-h-full min-w-0 max-w-full">
|
<div class="flex items-end justify-end min-h-full min-w-0 max-w-full">
|
||||||
|
|
@ -28,17 +28,17 @@ const { props } = Astro.props;
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid lg:grid-cols-3">
|
<div class="grid lg:grid-cols-3">
|
||||||
<div class="bg-tertiary p-12 xl:p-20 2xl:p-24 flex justify-between flex-col min-h-full lg:aspect-square">
|
<div class="bg-tertiary p-12 xl:p-20 2xl:p-24 flex justify-between flex-col min-h-full lg:aspect-square min-w-0">
|
||||||
<h2 class="text-3xl xl:text-5xl font-secondary font-bold text-white">{tl("values.service.title")}</h2>
|
<h2 class="text-3xl 2xl:text-5xl font-secondary font-bold text-white wrap-break-word">{tl("values.service.title")}</h2>
|
||||||
<p class="text-xl text-[#EBE5D0]">{tl("values.service.text")}</p>
|
<p class="text-xl text-[#EBE5D0] wrap-break-word">{tl("values.service.text")}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-[#BEA48D] p-12 xl:p-20 2xl:p-24 flex justify-between flex-col min-h-full lg:aspect-square">
|
<div class="bg-[#BEA48D] p-12 xl:p-20 2xl:p-24 flex justify-between flex-col min-h-full lg:aspect-square min-w-0">
|
||||||
<h2 class="text-3xl xl:text-5xl font-secondary font-bold text-tertiary">{tl("values.excellence.title")}</h2>
|
<h2 class="text-3xl 2xl:text-5xl font-secondary font-bold text-tertiary wrap-break-word">{tl("values.excellence.title")}</h2>
|
||||||
<p class="text-xl text-tertiary">{tl("values.excellence.text")}</p>
|
<p class="text-xl text-tertiary wrap-break-word">{tl("values.excellence.text")}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-[#22523F] p-12 xl:p-20 2xl:p-24 flex justify-between flex-col min-h-full lg:aspect-square">
|
<div class="bg-[#22523F] p-12 xl:p-20 2xl:p-24 flex justify-between flex-col min-h-full lg:aspect-square min-w-0">
|
||||||
<h2 class="text-3xl xl:text-5xl font-secondary font-bold text-white">{tl("values.dialogue.title")}</h2>
|
<h2 class="text-3xl 2xl:text-5xl font-secondary font-bold text-white wrap-break-word">{tl("values.dialogue.title")}</h2>
|
||||||
<p class="text-white text-xl">{tl("values.dialogue.text")}</p>
|
<p class="text-white text-xl wrap-break-word">{tl("values.dialogue.text")}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import type { APIRoute } from "astro";
|
import type { APIRoute } from "astro";
|
||||||
import { prisma } from "../lib/prisma";
|
import { prisma } from "../lib/prisma";
|
||||||
|
import { sendEmailCf } from "../lib/email";
|
||||||
|
|
||||||
export const prerender = false;
|
export const prerender = false;
|
||||||
|
|
||||||
|
|
@ -64,32 +65,11 @@ export const POST: APIRoute = async ({ request }) => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const emailApiKey = import.meta.env.EMAIL_API_KEY;
|
await sendEmailCf(
|
||||||
|
{ nombre, email, mensaje },
|
||||||
const emailResponse = await fetch("https://flows2.carpa.com/webhook/email/send", {
|
"joseperez@centrodelreinodepazyjusticia.com",
|
||||||
method: "POST",
|
"CENTRO_DEL_REINO_PAZ_Y_JUSTICIA_INFO",
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"x-api-key": emailApiKey!,
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
type: "CENTRO_DEL_REINO_PAZ_Y_JUSTICIA_INFO",
|
|
||||||
data: {
|
|
||||||
nombre,
|
|
||||||
email,
|
|
||||||
mensaje,
|
|
||||||
senderName : "Centro del Reino de Paz y Justicia",
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!emailResponse.ok) {
|
|
||||||
console.error("Error enviando correo");
|
|
||||||
return new Response(
|
|
||||||
JSON.stringify({ error: "Error en servicio de correo" }),
|
|
||||||
{ status: 500 }
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
return new Response(null, {
|
return new Response(null, {
|
||||||
status: 302,
|
status: 302,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import type { APIRoute } from "astro";
|
import type { APIRoute } from "astro";
|
||||||
import { appendToSheet, emailExists } from "../lib/googleSheets";
|
import { appendToSheet, emailExists } from "../lib/googleSheets";
|
||||||
|
import { sendEmailCf } from "../lib/email";
|
||||||
export const prerender = false;
|
export const prerender = false;
|
||||||
|
|
||||||
export const POST: APIRoute = async ({ request }) => {
|
export const POST: APIRoute = async ({ request }) => {
|
||||||
|
|
@ -29,17 +30,6 @@ export const POST: APIRoute = async ({ request }) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const dataSend = {
|
|
||||||
nombres,
|
|
||||||
apellidos,
|
|
||||||
pais,
|
|
||||||
lugar,
|
|
||||||
direccion,
|
|
||||||
telefono,
|
|
||||||
email
|
|
||||||
};
|
|
||||||
const emailApiKey = import.meta.env.EMAIL_API_KEY;
|
|
||||||
|
|
||||||
const valuesForSheets = [
|
const valuesForSheets = [
|
||||||
nombres,
|
nombres,
|
||||||
apellidos,
|
apellidos,
|
||||||
|
|
@ -51,31 +41,12 @@ export const POST: APIRoute = async ({ request }) => {
|
||||||
new Date().toLocaleString()
|
new Date().toLocaleString()
|
||||||
];
|
];
|
||||||
|
|
||||||
// 🔹 Enviar a tu backend real
|
// 🔹 Enviar correo (Cloudflare) y guardar en Google Sheets
|
||||||
const [emailResponse] = await Promise.all([
|
await Promise.all([
|
||||||
fetch("http://155.138.215.11:3050/email/send", {
|
sendEmailCf({ nombres, apellidos }, email, "CENTRO_DEL_REINO_PAZ_Y_JUSTICIA_POSTULACION"),
|
||||||
method: "POST",
|
appendToSheet(valuesForSheets)
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"x-api-key": emailApiKey!,
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
type: "CENTRO_DEL_REINO_PAZ_Y_JUSTICIA_POSTULACION",
|
|
||||||
data: dataSend,
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
appendToSheet(valuesForSheets) // Guardar en Google Sheets
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (!emailResponse.ok) {
|
|
||||||
return new Response(null, {
|
|
||||||
status: 302,
|
|
||||||
headers: {
|
|
||||||
Location: "/",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 🔹 Redirección elegante después de enviar
|
// 🔹 Redirección elegante después de enviar
|
||||||
return new Response(null, {
|
return new Response(null, {
|
||||||
status: 302,
|
status: 302,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import type { APIRoute } from "astro";
|
import type { APIRoute } from "astro";
|
||||||
import { appendRegistrationToSheet } from "../lib/googleSheets";
|
import { appendRegistrationToSheet } from "../lib/googleSheets";
|
||||||
import { sendEmail } from "../lib/email";
|
import { sendEmailCf } from "../lib/email";
|
||||||
export const prerender = false;
|
export const prerender = false;
|
||||||
|
|
||||||
const COLUMNS = [
|
const COLUMNS = [
|
||||||
|
|
@ -106,10 +106,9 @@ export const POST: APIRoute = async ({ request }) => {
|
||||||
|
|
||||||
const result = await appendRegistrationToSheet(row);
|
const result = await appendRegistrationToSheet(row);
|
||||||
|
|
||||||
await sendEmail({
|
await sendEmailCf({
|
||||||
nombres: formData.nombre,
|
nombres: formData.nombre_completo,
|
||||||
apellidos: formData.apellido,
|
apellidos: formData.apellido,
|
||||||
locale: formData.locale,
|
|
||||||
}, formData.correo, "CENTRO_DEL_REINO_PAZ_Y_JUSTICIA_POSTULACION");
|
}, formData.correo, "CENTRO_DEL_REINO_PAZ_Y_JUSTICIA_POSTULACION");
|
||||||
|
|
||||||
return Response.json(result);
|
return Response.json(result);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// import Cloudflare from "cloudflare";
|
import Cloudflare from "cloudflare";
|
||||||
|
|
||||||
type TypeEmailData = "CENTRO_DEL_REINO_PAZ_Y_JUSTICIA_INFO" | "CENTRO_DEL_REINO_PAZ_Y_JUSTICIA_POSTULACION";
|
type TypeEmailData = "CENTRO_DEL_REINO_PAZ_Y_JUSTICIA_INFO" | "CENTRO_DEL_REINO_PAZ_Y_JUSTICIA_POSTULACION";
|
||||||
|
|
||||||
|
|
@ -32,74 +32,74 @@ export async function sendEmail(data: object, to: string, type: TypeEmailData) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ═══════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════
|
||||||
// CÓDIGO COMENTADO — Cloudflare (Email Workers)
|
// Cloudflare (Email Sending)
|
||||||
// Descomentar para volver a Cloudflare en lugar de n8n/Brevo
|
// Usar sendEmailCf() en lugar de sendEmail() (n8n/Brevo)
|
||||||
// ═══════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
// const TEMPLATE_URLS: Record<TypeEmailData, { subject: string; url: string }> = {
|
const TEMPLATE_URLS: Record<TypeEmailData, { subject: string; url: string }> = {
|
||||||
// CENTRO_DEL_REINO_PAZ_Y_JUSTICIA_POSTULACION: {
|
CENTRO_DEL_REINO_PAZ_Y_JUSTICIA_POSTULACION: {
|
||||||
// subject: "Confirmación de inscripción al voluntariado",
|
subject: "Confirmación de inscripción al voluntariado",
|
||||||
// url: "https://pub-910ed90860804520b9202194cf43c0a6.r2.dev/centro_del_reino_paz_y_justicia_postulacion_user.html",
|
url: "https://assets.centrodelreinodepazyjusticia.com/centro_del_reino_paz_y_justicia_postulacion_user.html",
|
||||||
// },
|
},
|
||||||
// CENTRO_DEL_REINO_PAZ_Y_JUSTICIA_INFO: {
|
CENTRO_DEL_REINO_PAZ_Y_JUSTICIA_INFO: {
|
||||||
// subject: "Notificación de contacto institucional",
|
subject: "Notificación de contacto institucional",
|
||||||
// url: "https://pub-910ed90860804520b9202194cf43c0a6.r2.dev/centro_del_reino_paz_y_justicia_info.html",
|
url: "https://assets.centrodelreinodepazyjusticia.com/centro_del_reino_paz_y_justicia_info.html",
|
||||||
// },
|
},
|
||||||
// };
|
};
|
||||||
|
|
||||||
// const TEMPLATE_CACHE = new Map<string, string>();
|
const TEMPLATE_CACHE = new Map<string, string>();
|
||||||
|
|
||||||
// async function fetchTemplate(type: TypeEmailData): Promise<string> {
|
async function fetchTemplate(type: TypeEmailData): Promise<string> {
|
||||||
// const cached = TEMPLATE_CACHE.get(type);
|
const cached = TEMPLATE_CACHE.get(type);
|
||||||
// if (cached) return cached;
|
if (cached) return cached;
|
||||||
|
|
||||||
// const { url } = TEMPLATE_URLS[type];
|
const { url } = TEMPLATE_URLS[type];
|
||||||
// const res = await fetch(url);
|
const res = await fetch(url);
|
||||||
// if (!res.ok) {
|
if (!res.ok) {
|
||||||
// throw new Error(`Error descargando template ${type}: HTTP ${res.status}`);
|
throw new Error(`Error descargando template ${type}: HTTP ${res.status}`);
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const html = await res.text();
|
const html = await res.text();
|
||||||
// TEMPLATE_CACHE.set(type, html);
|
TEMPLATE_CACHE.set(type, html);
|
||||||
// return html;
|
return html;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// function renderTemplate(template: string, data: Record<string, string>): string {
|
function renderTemplate(template: string, data: Record<string, string>): string {
|
||||||
// let html = template;
|
let html = template;
|
||||||
// for (const [key, value] of Object.entries(data)) {
|
for (const [key, value] of Object.entries(data)) {
|
||||||
// html = html.replaceAll(new RegExp(`\\{\\{${key}\\}\\}`, "g"), value ?? "");
|
html = html.replaceAll(new RegExp(`\\{\\{${key}\\}\\}`, "g"), value ?? "");
|
||||||
// }
|
}
|
||||||
// return html;
|
return html;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// function stripHtml(html: string): string {
|
function stripHtml(html: string): string {
|
||||||
// return html.replace(/<[^>]*>/g, "").replace(/\s+/g, " ").trim();
|
return html.replace(/<[^>]*>/g, "").replace(/\s+/g, " ").trim();
|
||||||
// }
|
}
|
||||||
|
|
||||||
// export async function sendEmailCf(data: Record<string, string>, to: string, type: TypeEmailData) {
|
export async function sendEmailCf(data: Record<string, string>, to: string, type: TypeEmailData) {
|
||||||
// const apiToken = import.meta.env.CLOUDFLARE_API_TOKEN;
|
const apiToken = import.meta.env.CLOUDFLARE_API_TOKEN;
|
||||||
// const accountId = import.meta.env.CLOUDFLARE_ACCOUNT_ID;
|
const accountId = import.meta.env.CLOUDFLARE_ACCOUNT_ID;
|
||||||
|
|
||||||
// const client = new Cloudflare({ apiToken });
|
const client = new Cloudflare({ apiToken });
|
||||||
// const { subject } = TEMPLATE_URLS[type];
|
const { subject } = TEMPLATE_URLS[type];
|
||||||
// const rawHtml = await fetchTemplate(type);
|
const rawHtml = await fetchTemplate(type);
|
||||||
// const html = renderTemplate(rawHtml, data);
|
const html = renderTemplate(rawHtml, data);
|
||||||
// const text = stripHtml(html);
|
const text = stripHtml(html);
|
||||||
|
|
||||||
// const response = await client.emailSending.send({
|
const response = await client.emailSending.send({
|
||||||
// account_id: accountId,
|
account_id: accountId,
|
||||||
// from: "welcome@mail.centrodelreinodepazyjusticia.com",
|
from: "welcome@mail.centrodelreinodepazyjusticia.com",
|
||||||
// to,
|
to,
|
||||||
// subject,
|
subject,
|
||||||
// html,
|
html,
|
||||||
// text,
|
text,
|
||||||
// });
|
});
|
||||||
|
|
||||||
// if (!response.delivered) {
|
if (response.permanent_bounces.includes(to)) {
|
||||||
// console.error("Cloudflare email not delivered", response);
|
console.error("Cloudflare email not delivered", response);
|
||||||
// throw new Error("El correo no fue entregado");
|
throw new Error("El correo no fue entregado");
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// ═══════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════
|
||||||
// ALTERNATIVA: Brevo (SDK directo)
|
// ALTERNATIVA: Brevo (SDK directo)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue