import { NextRequest, NextResponse } from "next/server"; import { apiRoute } from "../../../../lib/server/apiRoute"; import { isDatabaseConfigured } from "../../../../lib/server/env"; import { prisma } from "../../../../lib/server/db"; import { dbUnavailable, notFound, unauthorized } from "../../../../lib/server/responses"; import { isWorkshopInquiryAdmin } from "../../../../lib/server/workshopInquiryAdmin"; function csvCell(value: string): string { if (/[",\n]/.test(value)) return `"${value.replace(/"/g, '""')}"`; return value; } export const GET = apiRoute("workshop-inquiries.export", async (_request: NextRequest) => { if (!(await isWorkshopInquiryAdmin())) { return process.env.WORKSHOP_INQUIRY_ADMIN_TOKEN?.trim() ? unauthorized() : notFound(); } if (!isDatabaseConfigured()) return dbUnavailable(); const rows = await prisma.workshopInquiry.findMany({ orderBy: { createdAt: "desc" }, }); const header = [ "id", "createdAt", "organizationName", "organizationKind", "memberCount", "largeOrganization", "routeSuggestion", "contactName", "email", "role", "challenges", "challengeOther", "unspokenQuestion", "sourcePage", "sourceUrl", ]; const lines = [header.join(",")]; for (const row of rows) { lines.push( [ row.id, row.createdAt.toISOString(), row.organizationName, row.organizationKind, row.memberCount, row.largeOrganization ? "yes" : "no", row.routeSuggestion, row.contactName, row.email, row.role ?? "", row.challenges.join("; "), row.challengeOther ?? "", row.unspokenQuestion ?? "", row.sourcePage, row.sourceUrl ?? "", ] .map((cell) => csvCell(String(cell))) .join(","), ); } return new NextResponse(lines.join("\n"), { status: 200, headers: { "content-type": "text/csv; charset=utf-8", "content-disposition": "attachment; filename=\"workshop-inquiries.csv\"", }, }); });