Compare commits
2 Commits
91137a6f40
...
d30e57f006
| Author | SHA1 | Date |
|---|---|---|
|
|
d30e57f006 | |
|
|
a9ca3f59f3 |
10
.env
10
.env
|
|
@ -18,8 +18,6 @@ EMAIL_API_KEY=9UShpS8oh5Iun92TJSfevElI3Lp99TCv
|
|||
# server with the prisma dev CLI command, when not choosing any non-default ports or settings. The API key, unlike the
|
||||
# one found in a remote Prisma Postgres URL, does not contain any sensitive information.
|
||||
|
||||
DATABASE_URL="file:./dev.db"
|
||||
|
||||
N8N_WEBHOOK_URL="https://flows2.carpa.com/webhook/news-summary"
|
||||
N8N_API_KEY="sk_live_JwjpTdZrLVvijCKuWylWZbUuhBm6zPDH"
|
||||
|
||||
|
|
@ -33,3 +31,11 @@ TURNSTILE_SITE_KEY=0x4AAAAAAD9IYWC6HPflpneO
|
|||
# Cloudflare Turnstile — secret key (server-side, keep safe!)
|
||||
# In production, set this as a Gitea Actions secret named TURNSTILE_SECRET_KEY
|
||||
TURNSTILE_SECRET_KEY=0x4AAAAAAD9IYXASjQSpmo2iS902SDoXnT4
|
||||
|
||||
# Supabase PostgreSQL
|
||||
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/postgres?schema=public"
|
||||
DIRECT_URL="postgresql://postgres:postgres@localhost:5432/postgres?schema=public"
|
||||
SUPABASE_URL="http://localhost:8000"
|
||||
SUPABASE_ANON_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE"
|
||||
SUPABASE_SERVICE_ROLE_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q"
|
||||
POSTGRES_PASSWORD=postgres
|
||||
|
|
|
|||
|
|
@ -4,3 +4,10 @@ TURNSTILE_SITE_KEY=0x4AA...
|
|||
# Cloudflare Turnstile — secret key (server-side, keep safe!)
|
||||
# In production, set this as a Gitea Actions secret named TURNSTILE_SECRET_KEY
|
||||
TURNSTILE_SECRET_KEY=0x4AA...
|
||||
|
||||
# Supabase PostgreSQL
|
||||
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/postgres?schema=public"
|
||||
DIRECT_URL="postgresql://postgres:postgres@localhost:5432/postgres?schema=public"
|
||||
SUPABASE_URL="http://localhost:8000"
|
||||
SUPABASE_ANON_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE"
|
||||
SUPABASE_SERVICE_ROLE_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q"
|
||||
|
|
|
|||
|
|
@ -30,3 +30,7 @@ prisma/dev.db
|
|||
opencode/
|
||||
.opencode/
|
||||
docs/
|
||||
|
||||
# scripts de migración (locales, no en producción)
|
||||
scripts/migrate-sheets-to-db.ts
|
||||
scripts/seed-form-config.ts
|
||||
|
|
|
|||
|
|
@ -7,7 +7,10 @@
|
|||
"build": "astro build",
|
||||
"postbuild": "node scripts/send-to-n8n.js",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro"
|
||||
"astro": "astro",
|
||||
"db:migrate-sheets": "npx tsx scripts/migrate-sheets-to-db.ts",
|
||||
"db:seed-form-config": "npx tsx scripts/seed-form-config.ts",
|
||||
"db:setup": "npx tsx scripts/seed-form-config.ts && npx tsx scripts/migrate-sheets-to-db.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/markdoc": "^2.0.3",
|
||||
|
|
|
|||
|
|
@ -11,6 +11,6 @@ export default defineConfig({
|
|||
},
|
||||
engine: "classic",
|
||||
datasource: {
|
||||
url: env("DATABASE_URL"),
|
||||
url: env("DIRECT_URL") || env("DATABASE_URL"),
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
# Please do not edit this file manually
|
||||
# It should be added in your version-control system (e.g., Git)
|
||||
provider = "sqlite"
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "Contact" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"nombre" TEXT NOT NULL,
|
||||
"email" TEXT NOT NULL,
|
||||
"mensaje" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "Contact_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Contact_email_key" ON "Contact"("email");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Contact_email_createdAt_idx" ON "Contact"("email", "createdAt");
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the `Contact` table. If the table is not empty, all the data it contains will be lost.
|
||||
|
||||
*/
|
||||
-- DropTable
|
||||
DROP TABLE "Contact";
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "contact" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"nombre" TEXT NOT NULL,
|
||||
"email" TEXT NOT NULL,
|
||||
"mensaje" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "contact_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "formularios" (
|
||||
"id" UUID NOT NULL,
|
||||
"numero_voluntario" SERIAL NOT NULL,
|
||||
"nombre" TEXT NOT NULL,
|
||||
"segundo_nombre" TEXT,
|
||||
"apellido" TEXT NOT NULL,
|
||||
"documento_nro" TEXT,
|
||||
"documento_tipo" TEXT,
|
||||
"correo" TEXT NOT NULL,
|
||||
"fecha_nacimiento" DATE,
|
||||
"nacionalidad" TEXT,
|
||||
"sexo" TEXT,
|
||||
"direccion" TEXT,
|
||||
"ciudad" TEXT,
|
||||
"estado" TEXT,
|
||||
"pais" TEXT,
|
||||
"codigo_postal" TEXT,
|
||||
"telefono" TEXT,
|
||||
"whatsapp" TEXT,
|
||||
"profesion" TEXT,
|
||||
"lugar_trabajo" TEXT,
|
||||
"nivel_academico" TEXT,
|
||||
"status" TEXT NOT NULL DEFAULT 'pendiente',
|
||||
"form_version" TEXT,
|
||||
"email_sent_at" TIMESTAMPTZ,
|
||||
"submitted_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMPTZ NOT NULL,
|
||||
|
||||
CONSTRAINT "formularios_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "respuestas" (
|
||||
"id" UUID NOT NULL,
|
||||
"formulario_id" UUID NOT NULL,
|
||||
"key" TEXT NOT NULL,
|
||||
"value" TEXT NOT NULL,
|
||||
"seccion" TEXT NOT NULL DEFAULT '',
|
||||
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "respuestas_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "secciones" (
|
||||
"id" UUID NOT NULL,
|
||||
"title_key" TEXT NOT NULL,
|
||||
"title" TEXT,
|
||||
"orden" INTEGER NOT NULL DEFAULT 0,
|
||||
"columns" INTEGER NOT NULL DEFAULT 1,
|
||||
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "secciones_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "campos" (
|
||||
"id" UUID NOT NULL,
|
||||
"key" TEXT NOT NULL,
|
||||
"label_key" TEXT NOT NULL,
|
||||
"tipo" TEXT NOT NULL,
|
||||
"seccion_id" UUID,
|
||||
"required" BOOLEAN NOT NULL DEFAULT false,
|
||||
"orden" INTEGER NOT NULL DEFAULT 0,
|
||||
"options" JSONB,
|
||||
"source" TEXT,
|
||||
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "campos_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "form_versions" (
|
||||
"id" UUID NOT NULL,
|
||||
"version" TEXT NOT NULL,
|
||||
"config" JSONB NOT NULL,
|
||||
"active" BOOLEAN NOT NULL DEFAULT false,
|
||||
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "form_versions_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "admins" (
|
||||
"id" UUID NOT NULL,
|
||||
"auth_user_id" UUID NOT NULL,
|
||||
"email" TEXT NOT NULL,
|
||||
"nombre" TEXT NOT NULL,
|
||||
"rol" TEXT NOT NULL DEFAULT 'coordinador',
|
||||
"activo" BOOLEAN NOT NULL DEFAULT true,
|
||||
"ultimo_acceso" TIMESTAMPTZ,
|
||||
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "admins_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "contact_email_key" ON "contact"("email");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "contact_email_createdAt_idx" ON "contact"("email", "createdAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "formularios_numero_voluntario_key" ON "formularios"("numero_voluntario");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "formularios_correo_idx" ON "formularios"("correo");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "formularios_status_idx" ON "formularios"("status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "formularios_pais_idx" ON "formularios"("pais");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "formularios_submitted_at_idx" ON "formularios"("submitted_at");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "respuestas_formulario_id_idx" ON "respuestas"("formulario_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "respuestas_key_idx" ON "respuestas"("key");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "respuestas_seccion_idx" ON "respuestas"("seccion");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "secciones_orden_idx" ON "secciones"("orden");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "campos_key_key" ON "campos"("key");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "campos_seccion_id_idx" ON "campos"("seccion_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "campos_tipo_idx" ON "campos"("tipo");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "admins_auth_user_id_key" ON "admins"("auth_user_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "admins_email_key" ON "admins"("email");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "admins_email_idx" ON "admins"("email");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "respuestas" ADD CONSTRAINT "respuestas_formulario_id_fkey" FOREIGN KEY ("formulario_id") REFERENCES "formularios"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "campos" ADD CONSTRAINT "campos_seccion_id_fkey" FOREIGN KEY ("seccion_id") REFERENCES "secciones"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
# Please do not edit this file manually
|
||||
# It should be added in your version-control system (e.g., Git)
|
||||
provider = "sqlite"
|
||||
provider = "postgresql"
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@ generator client {
|
|||
}
|
||||
|
||||
datasource db {
|
||||
provider = "sqlite"
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
directUrl = env("DIRECT_URL")
|
||||
}
|
||||
|
||||
model Contact {
|
||||
|
|
@ -16,4 +17,115 @@ model Contact {
|
|||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([email, createdAt])
|
||||
@@map("contact")
|
||||
}
|
||||
|
||||
model Formulario {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
numero_voluntario Int @unique @default(autoincrement())
|
||||
nombre String
|
||||
segundo_nombre String?
|
||||
apellido String
|
||||
documento_nro String?
|
||||
documento_tipo String?
|
||||
correo String
|
||||
fecha_nacimiento DateTime? @db.Date
|
||||
nacionalidad String?
|
||||
sexo String?
|
||||
direccion String?
|
||||
ciudad String?
|
||||
estado String?
|
||||
pais String?
|
||||
codigo_postal String?
|
||||
telefono String?
|
||||
whatsapp String?
|
||||
profesion String?
|
||||
lugar_trabajo String?
|
||||
nivel_academico String?
|
||||
status String @default("pendiente")
|
||||
form_version String?
|
||||
email_sent_at DateTime? @db.Timestamptz
|
||||
submitted_at DateTime @default(now()) @db.Timestamptz
|
||||
updated_at DateTime @updatedAt @db.Timestamptz
|
||||
|
||||
respuestas Respuesta[]
|
||||
|
||||
@@index([correo])
|
||||
@@index([status])
|
||||
@@index([pais])
|
||||
@@index([submitted_at])
|
||||
@@map("formularios")
|
||||
}
|
||||
|
||||
model Respuesta {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
formulario_id String @db.Uuid
|
||||
key String
|
||||
value String
|
||||
seccion String @default("")
|
||||
created_at DateTime @default(now()) @db.Timestamptz
|
||||
|
||||
formulario Formulario @relation(fields: [formulario_id], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([formulario_id])
|
||||
@@index([key])
|
||||
@@index([seccion])
|
||||
@@map("respuestas")
|
||||
}
|
||||
|
||||
model Seccion {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
title_key String
|
||||
title String?
|
||||
orden Int @default(0)
|
||||
columns Int @default(1)
|
||||
created_at DateTime @default(now()) @db.Timestamptz
|
||||
|
||||
campos Campo[]
|
||||
|
||||
@@index([orden])
|
||||
@@map("secciones")
|
||||
}
|
||||
|
||||
model Campo {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
key String @unique
|
||||
label_key String
|
||||
tipo String
|
||||
seccion_id String? @db.Uuid
|
||||
required Boolean @default(false)
|
||||
orden Int @default(0)
|
||||
options Json? @db.JsonB
|
||||
source String?
|
||||
created_at DateTime @default(now()) @db.Timestamptz
|
||||
|
||||
seccion Seccion? @relation(fields: [seccion_id], references: [id], onDelete: SetNull)
|
||||
|
||||
@@index([seccion_id])
|
||||
@@index([tipo])
|
||||
@@map("campos")
|
||||
}
|
||||
|
||||
model FormVersion {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
version String
|
||||
config Json @db.JsonB
|
||||
active Boolean @default(false)
|
||||
created_at DateTime @default(now()) @db.Timestamptz
|
||||
|
||||
@@map("form_versions")
|
||||
}
|
||||
|
||||
model Admin {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
auth_user_id String @unique @db.Uuid
|
||||
email String @unique
|
||||
nombre String
|
||||
rol String @default("coordinador")
|
||||
activo Boolean @default(true)
|
||||
ultimo_acceso DateTime? @db.Timestamptz
|
||||
created_at DateTime @default(now()) @db.Timestamptz
|
||||
|
||||
@@index([email])
|
||||
@@map("admins")
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import type { APIRoute } from "astro";
|
||||
import { appendToSheet, emailExists } from "../lib/googleSheets";
|
||||
import { sendEmailCf } from "../lib/email";
|
||||
import { prisma } from "../lib/prisma";
|
||||
export const prerender = false;
|
||||
|
||||
export const POST: APIRoute = async ({ request }) => {
|
||||
|
|
@ -41,10 +42,22 @@ export const POST: APIRoute = async ({ request }) => {
|
|||
new Date().toLocaleString()
|
||||
];
|
||||
|
||||
// 🔹 Enviar correo (Cloudflare) y guardar en Google Sheets
|
||||
// 🔹 Enviar correo (Cloudflare), guardar en Google Sheets y en PostgreSQL
|
||||
await Promise.all([
|
||||
sendEmailCf({ nombres, apellidos }, email, "CENTRO_DEL_REINO_PAZ_Y_JUSTICIA_POSTULACION"),
|
||||
appendToSheet(valuesForSheets)
|
||||
appendToSheet(valuesForSheets),
|
||||
prisma.formulario.create({
|
||||
data: {
|
||||
nombre: nombres!,
|
||||
apellido: apellidos!,
|
||||
pais: pais || null,
|
||||
ciudad: lugar || null,
|
||||
direccion: direccion || null,
|
||||
telefono: telefono || null,
|
||||
correo: email!,
|
||||
status: "legacy",
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
// 🔹 Redirección elegante después de enviar
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import type { APIRoute } from "astro";
|
||||
import { appendRegistrationToSheet } from "../lib/googleSheets";
|
||||
import { sendEmailCf } from "../lib/email";
|
||||
import { saveFormularioToSupabase } from "../lib/formularioDb";
|
||||
export const prerender = false;
|
||||
|
||||
const COLUMNS = [
|
||||
|
|
@ -101,6 +102,11 @@ export const POST: APIRoute = async ({ request }) => {
|
|||
timeZone: "America/Puerto_Rico",
|
||||
});
|
||||
|
||||
const form = await saveFormularioToSupabase(
|
||||
formData,
|
||||
body.responses || []
|
||||
);
|
||||
|
||||
const row = COLUMNS.map((key) => flattenValue(formData[key]));
|
||||
row.push(timestamp);
|
||||
|
||||
|
|
@ -111,7 +117,10 @@ export const POST: APIRoute = async ({ request }) => {
|
|||
apellidos: formData.apellido,
|
||||
}, formData.correo, "CENTRO_DEL_REINO_PAZ_Y_JUSTICIA_POSTULACION");
|
||||
|
||||
return Response.json(result);
|
||||
return Response.json({
|
||||
...result,
|
||||
numero_voluntario: form.numero_voluntario,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error en /api/formulario/send:", error);
|
||||
return Response.json(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,103 @@
|
|||
import { prisma } from "./prisma";
|
||||
|
||||
type FormData = Record<string, unknown>;
|
||||
type RespuestaPayload = {
|
||||
key: string;
|
||||
value: unknown;
|
||||
section_id?: string;
|
||||
};
|
||||
|
||||
const CORE_KEYS = new Set([
|
||||
"nombre",
|
||||
"segundo_nombre",
|
||||
"apellido",
|
||||
"documentos",
|
||||
"correo",
|
||||
"fecha_nacimiento",
|
||||
"nacionalidad",
|
||||
"sexo",
|
||||
"direccion_completa",
|
||||
"ciudad",
|
||||
"estado",
|
||||
"pais",
|
||||
"postal",
|
||||
"telefono",
|
||||
"whatsapp",
|
||||
"profesion",
|
||||
"lugar_trabajo_actual",
|
||||
"nivel_academico",
|
||||
"nombre_completo",
|
||||
"confirmar_nombre",
|
||||
"confirmar_firma",
|
||||
]);
|
||||
|
||||
function isBlank(v: unknown): boolean {
|
||||
return v === undefined || v === null || v === "";
|
||||
}
|
||||
|
||||
export async function saveFormularioToSupabase(
|
||||
formData: FormData,
|
||||
responses: RespuestaPayload[]
|
||||
) {
|
||||
const core = {
|
||||
nombre: (formData.nombre as string) ?? "",
|
||||
segundo_nombre: (formData.segundo_nombre as string) || null,
|
||||
apellido: (formData.apellido as string) ?? "",
|
||||
documento_nro: (formData.documentos as string) || null,
|
||||
correo: (formData.correo as string) ?? "",
|
||||
fecha_nacimiento: formData.fecha_nacimiento
|
||||
? new Date(formData.fecha_nacimiento as string)
|
||||
: null,
|
||||
nacionalidad: (formData.nacionalidad as string) || null,
|
||||
sexo: (formData.sexo as string) || null,
|
||||
direccion: (formData.direccion_completa as string) || null,
|
||||
ciudad: (formData.ciudad as string) || null,
|
||||
estado: (formData.estado as string) || null,
|
||||
pais: (formData.pais as string) || null,
|
||||
codigo_postal: (formData.postal as string) || null,
|
||||
telefono: (formData.telefono as string) || null,
|
||||
whatsapp: (formData.whatsapp as string) || null,
|
||||
profesion: (formData.profesion as string) || null,
|
||||
lugar_trabajo: (formData.lugar_trabajo_actual as string) || null,
|
||||
nivel_academico: (formData.nivel_academico as string) || null,
|
||||
};
|
||||
|
||||
const respRows: {
|
||||
key: string;
|
||||
value: string;
|
||||
seccion: string;
|
||||
}[] = [];
|
||||
|
||||
for (const r of responses || []) {
|
||||
if (CORE_KEYS.has(r.key)) continue;
|
||||
if (isBlank(r.value)) continue;
|
||||
|
||||
if (Array.isArray(r.value)) {
|
||||
for (const v of r.value) {
|
||||
if (!isBlank(v)) {
|
||||
respRows.push({
|
||||
key: r.key,
|
||||
value: String(v),
|
||||
seccion: r.section_id ?? "",
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
respRows.push({
|
||||
key: r.key,
|
||||
value: String(r.value),
|
||||
seccion: r.section_id ?? "",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return prisma.$transaction(async (tx) => {
|
||||
const form = await tx.formulario.create({ data: core });
|
||||
if (respRows.length) {
|
||||
await tx.respuesta.createMany({
|
||||
data: respRows.map((r) => ({ ...r, formulario_id: form.id })),
|
||||
});
|
||||
}
|
||||
return form;
|
||||
});
|
||||
}
|
||||
|
|
@ -7,4 +7,4 @@ const globalForPrisma = globalThis as unknown as {
|
|||
export const prisma =
|
||||
globalForPrisma.prisma ?? new PrismaClient();
|
||||
|
||||
if (import.meta.env.DEV) globalForPrisma.prisma = prisma;
|
||||
if (import.meta.env?.DEV) globalForPrisma.prisma = prisma;
|
||||
Loading…
Reference in New Issue