import { Box, Chip, CircularProgress, Divider, Paper, Skeleton, Typography, } from '@mui/material' import { AlertCircle, BarChart2, Briefcase, Building2, CheckCircle2, FileText, Newspaper, Target, TrendingUp, Users, } from 'lucide-react' import { useNavigate } from 'react-router' import { useMarketLeads } from '../../hooks/useMarketLeads' import { DecisionContextPanel } from '../../components/ui' import type { MarketLead } from '../../hooks/useMarketLeads' import type { Property } from '../../domain/property' // ── Source meta ────────────────────────────────────────────────────────────── const SOURCE_META: Record = { JOB_POSTING: { label: 'Stelleninserate', icon: }, PRESS: { label: 'Pressebericht', icon: }, COMPANY_REPORT: { label: 'Geschäftsbericht',icon: }, MARKET_DATA: { label: 'Marktdaten', icon: }, } const QUALITY_META: Record = { HIGH: { label: 'Hohe Signalqualität', color: '#1a7a4a' }, MEDIUM: { label: 'Mittlere Signalqualität', color: '#d97706' }, LOW: { label: 'Niedrige Signalqualität', color: '#c0392b' }, } function signalQuality(probability: number): 'HIGH' | 'MEDIUM' | 'LOW' { return probability >= 0.70 ? 'HIGH' : probability >= 0.50 ? 'MEDIUM' : 'LOW' } // ── Property match chip ─────────────────────────────────────────────────────── function PropertyMatchRow({ p }: { p: Property }) { const navigate = useNavigate() return ( navigate('/supply/properties')} sx={{ display: 'flex', alignItems: 'center', gap: 1, px: 1.25, py: 0.75, borderRadius: 1, bgcolor: '#f0fdf4', border: '1px solid #bbf7d0', cursor: 'pointer', '&:hover': { bgcolor: '#dcfce7' }, }} > {p.title} {p.areaSqm.toLocaleString('de-CH')} m² ) } // ── Lead card ───────────────────────────────────────────────────────────────── function LeadCard({ lead }: { lead: MarketLead }) { const { signal, matchingProperties } = lead const probPct = Math.round(signal.probability * 100) const qual = signalQuality(signal.probability) const qualMeta = QUALITY_META[qual] const sourceMeta = SOURCE_META[signal.source.type] ?? null return ( {/* Header */} {signal.companyName ?? signal.locationHint} {signal.title} {/* Key facts strip */} {signal.areaSqmEstimate && ( Flächenbedarf ~{signal.areaSqmEstimate.toLocaleString('de-CH')} m² )} Zeithorizont ~{signal.timeHorizonMonths} Monate Wahrscheinlichkeit {probPct}% Standort {signal.locationHint} {sourceMeta && ( Quelle {sourceMeta.icon} {sourceMeta.label} )} {/* Market indicators */} {signal.marketIndicators && signal.marketIndicators.length > 0 && ( Erkannte Nachfragesignale {signal.marketIndicators.map((ind, i) => ( {ind} ))} )} {/* Confirmed / unconfirmed facts */} {((signal.confirmedFacts?.length ?? 0) > 0 || (signal.unconfirmedFacts?.length ?? 0) > 0) && ( {(signal.confirmedFacts ?? []).map((f, i) => ( {f} ))} {(signal.unconfirmedFacts ?? []).map((f, i) => ( {f} ))} )} {/* Portfolio matches */} Passende Objekte im Portfolio ({matchingProperties.length}) {matchingProperties.length === 0 ? ( Kein passendes Portfolioobjekt gefunden — manuell prüfen empfohlen ) : ( {matchingProperties.slice(0, 3).map(p => ( ))} {matchingProperties.length > 3 && ( +{matchingProperties.length - 3} weitere Objekte )} )} {/* Disclaimer */} {signal.disclaimer} ) } // ── Loading skeleton ────────────────────────────────────────────────────────── function LeadSkeleton() { return ( ) } // ── Page ────────────────────────────────────────────────────────────────────── export default function MarketLeads() { const { data: leads, isLoading } = useMarketLeads() const leadsWithMatch = leads.filter(l => l.matchingProperties.length > 0) return ( {/* Header */} Markt-Leads Erkannte Unternehmen mit aktivem Flächenbedarf — potenzielle Mieter für Ihr Portfolio {!isLoading && ( )} {/* Decision context */} {!isLoading && leads.length > 0 && ( 0 ? [{ label: 'mit passendem Objekt', value: leadsWithMatch.length, severity: 'positive' as const }] : []), ]} risks={leads.length - leadsWithMatch.length > 0 ? [`${leads.length - leadsWithMatch.length} Leads ohne direkten Portfolio-Match — Leerstandsanalyse empfohlen`] : [] } actions={[]} /> )} {isLoading ? ( <> ) : leads.length === 0 ? ( Keine aktiven Markt-Leads gefunden. Signale werden laufend aus öffentlichen Quellen erkannt. ) : ( leads.map(lead => ) )} ) }