- 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>
65 lines
2.1 KiB
TypeScript
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 });
|
|
}
|
|
}
|