Files
lead-scraper/app/api/leads/bulk/route.ts
Timo Uttenweiler 042fbeb672 feat: LeadVault - zentrale Lead-Datenbank mit CRM-Funktionen
- Prisma-Schema: Lead + LeadEvent Modelle (Migration 20260320)
- lib/services/leadVault.ts: sinkLeadsToVault mit Deduplizierung
- Auto-Sync: alle 4 Pipelines schreiben Leads in LeadVault
- GET /api/leads: Filter, Sortierung, Pagination (Server-side)
- PATCH/DELETE /api/leads/[id]: Status, Priorität, Tags, Notizen
- POST /api/leads/bulk: Bulk-Aktionen für mehrere Leads
- GET /api/leads/stats: Statistiken + 7-Tage-Sparkline
- POST /api/leads/quick-serp: SERP-Capture ohne Enrichment
- GET /api/leads/export: CSV-Export mit allen Feldern
- app/leadvault/page.tsx: vollständige UI mit Stats, Quick SERP,
  Filter-Leiste, sortierbare Tabelle, Bulk-Aktionen, Side Panel
- Sidebar: LeadVault-Eintrag mit Live-Badge (neue Leads)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 17:33:12 +01:00

65 lines
2.1 KiB
TypeScript

import { NextRequest, NextResponse } from "next/server";
import { prisma } from "@/lib/db";
export async function POST(req: NextRequest) {
try {
const body = await req.json() as {
ids: string[];
action: "status" | "priority" | "tag" | "delete";
value: string;
};
const { ids, action, value } = body;
if (!ids?.length) return NextResponse.json({ error: "No IDs provided" }, { status: 400 });
if (action === "delete") {
const { count } = await prisma.lead.deleteMany({ where: { id: { in: ids } } });
return NextResponse.json({ updated: count });
}
if (action === "status") {
const { count } = await prisma.lead.updateMany({
where: { id: { in: ids } },
data: { status: value },
});
// Create events for status change
for (const id of ids) {
await prisma.leadEvent.create({
data: { leadId: id, event: `Status geändert zu "${value}" (Bulk)` },
}).catch(() => {}); // ignore if lead was deleted
}
return NextResponse.json({ updated: count });
}
if (action === "priority") {
const { count } = await prisma.lead.updateMany({
where: { id: { in: ids } },
data: { priority: value },
});
return NextResponse.json({ updated: count });
}
if (action === "tag") {
// Add tag to each lead's tags JSON array
const leads = await prisma.lead.findMany({ where: { id: { in: ids } }, select: { id: true, tags: true } });
let count = 0;
for (const lead of leads) {
const existing: string[] = JSON.parse(lead.tags || "[]");
if (!existing.includes(value)) {
await prisma.lead.update({
where: { id: lead.id },
data: { tags: JSON.stringify([...existing, value]) },
});
count++;
}
}
return NextResponse.json({ updated: count });
}
return NextResponse.json({ error: "Unknown action" }, { status: 400 });
} catch (err) {
console.error("POST /api/leads/bulk error:", err);
return NextResponse.json({ error: "Bulk action failed" }, { status: 500 });
}
}