feat: add lead qualification workflow

This commit is contained in:
2026-06-04 16:09:47 +02:00
parent 15d8bfeb66
commit 59824b7336
19 changed files with 2833 additions and 78 deletions

View File

@@ -29,7 +29,7 @@ export type ReviewQueueItem = {
detail: string;
};
export type LeadPriority = "high" | "medium" | "low" | "defer";
export type LeadPriority = "high" | "medium" | "low" | "defer" | "blocked";
export type LeadContactStatus =
| "new"
@@ -41,6 +41,11 @@ export type LeadContactStatus =
| "do_not_contact";
export type LeadBlacklistStatus = "clear" | "blocked";
export type LeadDuplicateStatus =
| "unchecked"
| "unique"
| "possible_duplicate"
| "duplicate";
export type OutreachApprovalStatus = "draft" | "approved" | "rejected";
export type OutreachSendStatus = "not_sent" | "queued" | "sent" | "failed";
@@ -151,14 +156,15 @@ export const leadFunnelStages: LeadFunnelStage[] = [
},
];
const priorityLabels: Record<LeadPriority, string> = {
export const leadPriorityLabels: Record<LeadPriority, string> = {
high: "Hoch",
medium: "Mittel",
low: "Niedrig",
defer: "Zurückstellen",
blocked: "Gesperrt",
};
const contactStatusLabels: Record<LeadContactStatus, string> = {
export const leadContactStatusLabels: Record<LeadContactStatus, string> = {
new: "Neu",
missing_contact: "Kontakt fehlt",
audit_ready: "Audit bereit",
@@ -168,6 +174,61 @@ const contactStatusLabels: Record<LeadContactStatus, string> = {
do_not_contact: "Nicht kontaktieren",
};
export const leadDuplicateStatusLabels: Record<LeadDuplicateStatus, string> = {
unchecked: "Noch nicht geprüft",
unique: "Einzigartig",
possible_duplicate: "Möglicher Doppelter",
duplicate: "Duplikat",
};
export const leadBlacklistStatusLabels: Record<LeadBlacklistStatus, string> = {
clear: "Offen",
blocked: "Gesperrt",
};
export const leadPriorityOptions: LeadPriority[] = [
"high",
"medium",
"low",
"defer",
"blocked",
];
export const leadContactStatusOptions: LeadContactStatus[] = [
"new",
"missing_contact",
"audit_ready",
"outreach_ready",
"contacted",
"replied",
"do_not_contact",
];
export const leadDuplicateStatusOptions: LeadDuplicateStatus[] = [
"unchecked",
"unique",
"possible_duplicate",
"duplicate",
];
export const leadBlacklistStatusOptions: LeadBlacklistStatus[] = ["clear", "blocked"];
export function getLeadPriorityLabel(priority: LeadPriority): string {
return leadPriorityLabels[priority];
}
export function getLeadContactStatusLabel(status: LeadContactStatus): string {
return leadContactStatusLabels[status];
}
export function getLeadDuplicateStatusLabel(status: LeadDuplicateStatus): string {
return leadDuplicateStatusLabels[status];
}
export function getLeadBlacklistStatusLabel(status: LeadBlacklistStatus): string {
return leadBlacklistStatusLabels[status];
}
export function toLeadFunnelCard(lead: LeadFunnelInput): LeadFunnelCard {
return {
id: lead.id,
@@ -175,8 +236,8 @@ export function toLeadFunnelCard(lead: LeadFunnelInput): LeadFunnelCard {
company: lead.companyName,
niche: lead.niche ?? "Nische offen",
location: formatLeadLocation(lead),
priorityLabel: priorityLabels[lead.priority],
contactStatusLabel: contactStatusLabels[lead.contactStatus],
priorityLabel: getLeadPriorityLabel(lead.priority),
contactStatusLabel: getLeadContactStatusLabel(lead.contactStatus),
nextAction: getLeadNextAction(lead),
websiteDomain: lead.websiteDomain,
contactDetail: formatContactDetail(lead),
@@ -198,6 +259,7 @@ function getLeadFunnelStageId(lead: LeadFunnelInput): LeadFunnelStageId {
if (
lead.blacklistStatus === "blocked" ||
lead.priority === "defer" ||
lead.priority === "blocked" ||
lead.contactStatus === "do_not_contact"
) {
return "deferred";