cdrdpyj/src/pages/api/admin/voluntarios/distinct.ts

59 lines
1.6 KiB
TypeScript

import type { APIRoute } from "astro";
import { prisma } from "../../lib/prisma";
import { Prisma } from "@prisma/client";
export const prerender = false;
const DISTINCT_FIELDS = new Set([
"ciudad",
"estado",
"profesion",
"nivel_academico",
"nacionalidad",
"pais",
]);
const SIMILARITY_THRESHOLD = 0.35;
export const GET: APIRoute = async ({ url }) => {
try {
const sp = url.searchParams;
const field = (sp.get("field") || "").trim();
const q = (sp.get("q") || "").trim();
const limit = Math.min(100, Math.max(1, parseInt(sp.get("limit") || "25", 10)));
if (!DISTINCT_FIELDS.has(field)) {
return Response.json(
{ success: false, message: "Campo no permitido" },
{ status: 400 }
);
}
const col = Prisma.raw(field);
const rows = await prisma.$queryRaw<{ value: string; count: number }[]>`
SELECT ${col} AS value, COUNT(*)::int AS count
FROM formularios
WHERE ${col} IS NOT NULL AND ${col} <> ''
${q.length >= 2 ? Prisma.sql`AND (similarity(lower(${col}), lower(${q})) > ${SIMILARITY_THRESHOLD} OR ${col} ILIKE ${`%${q}%`})` : Prisma.empty}
GROUP BY ${col}
ORDER BY count DESC
LIMIT ${limit}
`;
return Response.json({
success: true,
field,
data: rows.map((r) => ({ value: r.value, count: r.count })),
}, {
headers: { "Cache-Control": "private, max-age=300, stale-while-revalidate=600" },
});
} catch (error) {
console.error("Error en /api/admin/voluntarios/distinct:", error);
return Response.json(
{ success: false, message: "Error al obtener valores" },
{ status: 500 }
);
}
};