diff --git a/src/components/match-card/IntelligenceMatchCard.tsx b/src/components/match-card/IntelligenceMatchCard.tsx index c1ac62a..5b4b2b7 100644 --- a/src/components/match-card/IntelligenceMatchCard.tsx +++ b/src/components/match-card/IntelligenceMatchCard.tsx @@ -1,5 +1,6 @@ import { Box, Button, Chip, Divider, Typography } from '@mui/material' import { + AlertCircle, BarChart2, Briefcase, Building2, @@ -21,7 +22,7 @@ const RESULT_TYPE_META: Record = { VERIFIED_PORTFOLIO: { label: 'Verified Portfolio', color: '#1e3a5f' }, EXTERNAL_MARKET: { label: 'Direktinserat', color: '#d97706' }, MAISON_WORK: { label: 'Maison Work', color: '#0369a1' }, - FUTURE_AVAILABILITY: { label: 'Schattenmarkt', color: '#7c3aed' }, + FUTURE_AVAILABILITY: { label: 'Future Availability', color: '#7c3aed' }, } const SOURCE_META: Record = { @@ -80,23 +81,26 @@ function SignalQualityDots({ quality }: { quality: 'HIGH' | 'MEDIUM' | 'LOW' | u function FutureAvailabilityCard({ vm }: { vm: MatchCardViewModel }) { const isControlled = vm.signalIsControlled ?? false - const accentColor = isControlled ? '#1a7a4a' : '#1d4ed8' - const headerBg = isControlled ? '#f0fdf4' : '#f8fafc' - const badge = isControlled ? 'Pre-Market' : 'Market Signal' - const badgeBg = isControlled ? '#dcfce7' : '#dbeafe' - const badgeColor = isControlled ? '#1a7a4a' : '#1d4ed8' + + // PRE-MARKET VERIFIED: soft purple / institutional premium + // MARKET SIGNAL: slate blue / analytical + const accentColor = isControlled ? '#7c3aed' : '#1d4ed8' + const headerBg = isControlled ? '#faf5ff' : '#eff6ff' + const borderColor = isControlled ? '#e9d5ff' : '#bfdbfe' + const badgeBg = isControlled ? '#ede9fe' : '#dbeafe' + const badgeColor = isControlled ? '#5b21b6' : '#1e40af' const assetLabel = vm.assetType ? (ASSET_TYPE_LABELS[vm.assetType] ?? vm.assetType) : 'Fläche' - const headline = getOpportunityHeadline(vm.signalType, assetLabel) - - const tier = getScoreTier(vm.matchScore) + const headline = getOpportunityHeadline(vm.signalType, assetLabel) + const sourceMeta = vm.signalSourceType ? (SOURCE_META[vm.signalSourceType] ?? null) : null + const tier = getScoreTier(vm.matchScore) const theme = SCORE_THEME[tier] return ( - {/* Data Header */} - - {/* Asset type + location */} + {/* ── Data header ─────────────────────────────────────────────────────── */} + + + {/* Asset type · location + badge */} {assetLabel.toUpperCase()} · {vm.locationLabel?.split(',')[0]?.toUpperCase() ?? ''} - - {badge} + + {isControlled && } + + {isControlled ? 'PRE-MARKET VERIFIED' : 'MARKET SIGNAL'} + @@ -122,11 +130,11 @@ function FutureAvailabilityCard({ vm }: { vm: MatchCardViewModel }) { {headline} - {/* Key facts row */} - + {/* Key facts */} + {vm.signalAreaSqmEstimate ? ( - - ~{vm.signalAreaSqmEstimate.toLocaleString('de-CH')} m² + + {isControlled ? '' : '~'}{vm.signalAreaSqmEstimate.toLocaleString('de-CH')} m² ) : null} {vm.availabilityLabel && ( @@ -135,10 +143,23 @@ function FutureAvailabilityCard({ vm }: { vm: MatchCardViewModel }) { )} + + {/* Source attribution */} + {isControlled ? ( + + + Direkte Verwaltungsquelle + + ) : sourceMeta ? ( + + {sourceMeta.icon} + {sourceMeta.label} + + ) : null} - {/* Score + signal quality strip */} - + {/* ── Score + signal quality strip ────────────────────────────────────── */} + - {isControlled && ( - - - Verifiziert + {!isControlled && vm.signalProbability !== undefined && ( + + + {Math.round(vm.signalProbability * 100)}% Signalw. + )} - {/* Card body */} - + {/* ── Card body ───────────────────────────────────────────────────────── */} + - {/* CONTROLLED: Confirmed facts */} + {/* MARKET SIGNAL: probabilistic notice */} + {!isControlled && ( + + + + Probabilistischer Marktindikator — kein bestätigtes Objekt. Dient als strategischer Frühindikator. + + + )} + + {/* PRE-MARKET VERIFIED: confirmed facts */} {isControlled && (vm.signalConfirmedFacts?.length ?? 0) > 0 && ( - {(vm.signalConfirmedFacts ?? []).slice(0, 2).map((fact, i) => ( + {(vm.signalConfirmedFacts ?? []).slice(0, 3).map((fact, i) => ( {fact} @@ -172,13 +207,13 @@ function FutureAvailabilityCard({ vm }: { vm: MatchCardViewModel }) { )} - {/* MARKET SIGNAL: Market indicators */} + {/* MARKET SIGNAL: market indicators */} {!isControlled && (vm.signalMarketIndicators?.length ?? 0) > 0 && ( - <> + Erkannte Marktindikatoren - + {(vm.signalMarketIndicators ?? []).slice(0, 3).map((ind, i) => ( @@ -186,17 +221,17 @@ function FutureAvailabilityCard({ vm }: { vm: MatchCardViewModel }) { ))} - + )} - {/* Why relevant (match reasons) */} + {/* Why relevant — match reasons */} {vm.reasons.length > 0 && ( <> Warum relevant für Ihre Suche? - + {vm.reasons.slice(0, 3).map((r, i) => ( @@ -211,7 +246,7 @@ function FutureAvailabilityCard({ vm }: { vm: MatchCardViewModel }) { )} {/* Actions */} - + {vm.actions.map(a => (