import { useMemo } from 'react' import { useMarketLeads } from './useMarketLeads' import { useMarktHinweise } from './useMarktHinweise' import { useCrmLeads } from './useCrmLeads' import { LeadChannel } from '../domain/unifiedLead' import type { UnifiedLead } from '../domain/unifiedLead' import type { MarktHinweis } from '../domain/marktHinweis' import type { CrmLead } from '../domain/crmLead' import { CRM_LEAD_STAGE_LABELS } from '../domain/crmLead' import { ASSET_TYPE_LABELS } from '../lib/constants' import type { MarketLead } from './useMarketLeads' /** * Zusammengeführte Leadliste aller drei Kanäle (Runde 5, §12). * * Die drei Quellen bleiben getrennt erfasst — KI-Signale entstehen aus * Marktbeobachtung, Netzwerk-Hinweise aus Gesprächen, CRM-Leads aus dem * Vertriebssystem. Zusammengelegt werden sie erst hier, für die Anzeige, und * jeder Eintrag behält seine Kanalherkunft im Feld `channel`. * * Ein gemeinsamer Provider für alle drei wäre der falsche Weg: die Quellen * haben unterschiedliche Lebenszyklen und werden später von verschiedenen * Systemen bedient. */ function areaText(min?: number, max?: number): string | null { if (min != null && max != null && min !== max) return `${min}–${max} m²` if (max != null) return `${max} m²` if (min != null) return `${min} m²` return null } function fromMarketLead(lead: MarketLead): UnifiedLead { const { signal } = lead return { id: signal.id, channel: LeadChannel.KI_SIGNAL, title: signal.companyName ?? signal.locationHint, subtitle: signal.title ?? 'Erkanntes Nachfragesignal', meta: `${signal.locationHint} · Horizont ${signal.timeHorizonMonths} Mo.`, receivedAt: signal.updatedAt || signal.createdAt, signal, matchingProperties: lead.matchingProperties, } } function fromHinweis(hinweis: MarktHinweis): UnifiedLead { const displayName = !hinweis.isAnonymized && hinweis.companyName ? hinweis.companyName : 'Anonymer Hinweis' const area = areaText(hinweis.areaSqmMin, hinweis.areaSqmMax) const assetLabel = ASSET_TYPE_LABELS[hinweis.assetType] ?? hinweis.assetType return { id: hinweis.id, channel: LeadChannel.NETZWERK, title: displayName, subtitle: hinweis.direction === 'SUCHE' ? `Sucht ${assetLabel}` : `Fläche wird verfügbar — ${assetLabel}`, meta: [hinweis.locationHint, area, hinweis.createdBy].filter(Boolean).join(' · '), receivedAt: hinweis.createdAt, hinweis, } } function fromCrmLead(crmLead: CrmLead): UnifiedLead { const area = areaText(crmLead.areaSqmMin, crmLead.areaSqmMax) const assetLabel = ASSET_TYPE_LABELS[crmLead.assetType] ?? crmLead.assetType return { id: crmLead.id, channel: LeadChannel.CRM, title: crmLead.companyName, subtitle: `${CRM_LEAD_STAGE_LABELS[crmLead.stage]} — sucht ${assetLabel}`, meta: [crmLead.locationHint, area, crmLead.ownerName].filter(Boolean).join(' · '), receivedAt: crmLead.lastContactAt, crmLead, } } export function useUnifiedLeads(): { data: UnifiedLead[]; isLoading: boolean } { const { data: marketLeads, isLoading: marketLoading } = useMarketLeads() const { data: hinweise = [], isLoading: hinweiseLoading } = useMarktHinweise() const { data: crmLeads = [], isLoading: crmLoading } = useCrmLeads() const data = useMemo( () => [ ...marketLeads.map(fromMarketLead), ...hinweise.map(fromHinweis), ...crmLeads.map(fromCrmLead), ].sort((a, b) => b.receivedAt.localeCompare(a.receivedAt)), [marketLeads, hinweise, crmLeads], ) return { data, isLoading: marketLoading || hinweiseLoading || crmLoading } }