diff --git a/src/components/supply/PropertyIntelligenceCard.tsx b/src/components/supply/PropertyIntelligenceCard.tsx index 8f3c79e..7e1937c 100644 --- a/src/components/supply/PropertyIntelligenceCard.tsx +++ b/src/components/supply/PropertyIntelligenceCard.tsx @@ -8,6 +8,7 @@ import type { Property } from '../../domain/property' interface Props { property: Property onSelect: (id: string) => void + inquiryCount?: number } const AVAIL_STYLE: Record = { @@ -22,13 +23,19 @@ const FIT_OUT_META: Record = { PREMIUM: { label: 'Premium-Ausbau', tip: 'Hochwertig, sofort bezugsfertig.' }, } -export const PropertyIntelligenceCard = memo(function PropertyIntelligenceCard({ property: p, onSelect }: Props) { +export const PropertyIntelligenceCard = memo(function PropertyIntelligenceCard({ property: p, onSelect, inquiryCount }: Props) { const confPct = Math.round(p.confidenceScore * 100) const annualRent = Math.round(p.areaSqm * p.rentPricePerSqm / 1000) const availStyle = AVAIL_STYLE[p.availabilityStatus] ?? { bg: '#f4f3f0', text: '#9a9a9a' } const assetColor = getAssetTypeColor(p.assetType) const hasImage = !!p.images?.[0] + // Inquiry count style — highlight if there's active interest + const hasInquiries = (inquiryCount ?? 0) > 0 + const inquiryStyle = hasInquiries + ? { bg: '#fffbeb', text: '#a16207', border: '#fde68a' } + : { bg: '#f9f8f6', text: '#9a9a9a', border: DS_BORDER.muted } + return ( onSelect(p.id)} @@ -59,10 +66,9 @@ export const PropertyIntelligenceCard = memo(function PropertyIntelligenceCard({ )} - {/* Dark overlay for legibility */} - {/* Top badges — asset type + availability */} + {/* Badges: asset type + availability */} @@ -76,7 +82,7 @@ export const PropertyIntelligenceCard = memo(function PropertyIntelligenceCard({ - {/* Bottom — CHF hero + per-sqm */} + {/* Bottom — annual rent hero */} @@ -91,7 +97,7 @@ export const PropertyIntelligenceCard = memo(function PropertyIntelligenceCard({ - {p.rentPricePerSqm} /m²/J + {p.rentPricePerSqm} CHF/m²/J @@ -112,33 +118,45 @@ export const PropertyIntelligenceCard = memo(function PropertyIntelligenceCard({ - {/* Metric boxes */} + {/* 3 key metrics: Fläche · Frei ab · Anfragen */} - {[ - { icon: '↗', label: 'FLÄCHE', value: `${p.areaSqm.toLocaleString('de-CH')} m²` }, - ...(p.availabilityDate ? [{ icon: '📅', label: 'AB', value: new Date(p.availabilityDate).toLocaleDateString('de-CH', { month: 'short', year: '2-digit' }) }] : []), - ...(p.softFactors?.prestige != null ? [{ icon: '↗', label: 'PRESTIGE', value: String(p.softFactors.prestige) }] : []), - ].map(({ label, value }) => ( - - - {label} + {/* Fläche */} + + + Fläche + + + {p.areaSqm.toLocaleString('de-CH')} m² + + + + {/* Frei ab */} + + + Frei ab + + + {p.availabilityDate + ? new Date(p.availabilityDate).toLocaleDateString('de-CH', { month: 'short', year: '2-digit' }) + : '—'} + + + + {/* Anfragen */} + + + + Anfragen - - {value} + + {inquiryCount ?? 0} - ))} + - {/* Chips */} + {/* Property spec chips */} - {p.softFactors?.publicTransportMinutes != null && ( - - )} {p.hardFacts?.fitOut && (() => { const meta = FIT_OUT_META[p.hardFacts!.fitOut!] ?? { label: p.hardFacts!.fitOut!, tip: '' } return ( @@ -149,16 +167,26 @@ export const PropertyIntelligenceCard = memo(function PropertyIntelligenceCard({ ) })()} {p.contractDurationMonths && ( - + + )} + {p.softFactors?.publicTransportMinutes != null && ( + )} - {/* Confidence bar */} + {/* Data completeness — tells the manager if their listing is ready to match */} - Datenkonfidenz + Datenvollständigkeit = 0.75 ? '#b8975a' : DS_TEXT.muted }}> {confPct}% diff --git a/src/pages/supply/Properties.tsx b/src/pages/supply/Properties.tsx index e94f8f8..14a47e1 100644 --- a/src/pages/supply/Properties.tsx +++ b/src/pages/supply/Properties.tsx @@ -5,6 +5,7 @@ import { ChevronDown, ChevronUp } from 'lucide-react' import { PageHeader } from '../../components/layout' import { ViewToggle } from '../../components/shared' import { useProperties } from '../../hooks/useProperties' +import { useActiveInquiries } from '../../hooks/useInquiries' import { PropertyFilterBar, PropertyTable, PropertyDetailView, PropertyIntelligenceCard } from '../../components/supply' import type { PropertyTableFilters } from '../../components/supply' import type { Property } from '../../domain/property' @@ -61,6 +62,15 @@ export default function Properties() { ) const { data: properties = [], isLoading, isError } = useProperties() + const { data: inquiries = [] } = useActiveInquiries() + + const inquiryCountByProperty = useMemo(() => { + const map = new Map() + for (const inq of inquiries) { + if (inq.propertyId) map.set(inq.propertyId, (map.get(inq.propertyId) ?? 0) + 1) + } + return map + }, [inquiries]) const filtered = useMemo(() => applyFilters(properties, filters), [properties, filters]) @@ -193,7 +203,7 @@ export default function Properties() { {view === 'grid' ? ( {filtered.map(p => ( - + ))} ) : (