diff --git a/src/components/supply/PropertyIntelligenceCard.tsx b/src/components/supply/PropertyIntelligenceCard.tsx index 7e1937c..bcc7266 100644 --- a/src/components/supply/PropertyIntelligenceCard.tsx +++ b/src/components/supply/PropertyIntelligenceCard.tsx @@ -1,7 +1,7 @@ import { memo } from 'react' import { Box, Chip, LinearProgress, Tooltip, Typography } from '@mui/material' import { MapPin } from 'lucide-react' -import { getAssetTypeColor, getAssetTypeLabel, getAvailabilityLabel } from './propertyHelpers' +import { getAssetTypeColor, getAssetTypeLabel } from './propertyHelpers' import { DS_TEXT, DS_BORDER } from '../../lib/ds' import type { Property } from '../../domain/property' @@ -11,10 +11,37 @@ interface Props { inquiryCount?: number } -const AVAIL_STYLE: Record = { - AVAILABLE_NOW: { bg: '#dcfce7', text: '#1d6342' }, - AVAILABLE_SOON: { bg: '#fef9c3', text: '#a16207' }, -} +// Occupancy status — the property manager's primary lens +const STATUS_CONFIG = { + AVAILABLE_NOW: { + dot: '#b91c1c', + bg: '#fef2f2', + border:'#fecaca', + text: '#b91c1c', + label: 'Verfügbar', + }, + AVAILABLE_SOON: { + dot: '#a16207', + bg: '#fffbeb', + border:'#fde68a', + text: '#a16207', + label: 'Bald frei', + }, + OCCUPIED: { + dot: '#1d6342', + bg: '#f0fdf4', + border:'#bbf7d0', + text: '#1d6342', + label: 'Vermietet', + }, + FUTURE_SIGNAL: { + dot: '#5b3f8a', + bg: '#faf7ff', + border:'#e9d5ff', + text: '#5b3f8a', + label: 'Geplante Verfügbarkeit', + }, +} as const const FIT_OUT_META: Record = { SHELL: { label: 'Rohbau', tip: 'Keine Einbauten — volle Ausbauinvestition.' }, @@ -25,16 +52,16 @@ const FIT_OUT_META: Record = { 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 } + + const statusKey = p.availabilityStatus as keyof typeof STATUS_CONFIG + const status = STATUS_CONFIG[statusKey] ?? STATUS_CONFIG.OCCUPIED + + const availDate = p.availabilityDate + ? new Date(p.availabilityDate).toLocaleDateString('de-CH', { month: 'short', year: '2-digit' }) + : null return ( - {/* ── Image ── */} - + {/* ── Image — clean, no text overlay ── */} + {hasImage ? ( @@ -66,44 +93,29 @@ export const PropertyIntelligenceCard = memo(function PropertyIntelligenceCard({ )} - - - {/* Badges: asset type + availability */} - - - - {getAssetTypeLabel(p.assetType)} - - - - - {getAvailabilityLabel(p.availabilityStatus)} - - - - - {/* Bottom — annual rent hero */} - - - - Jahresmiete ca. - - - CHF {annualRent}k - - - - {p.rentPricePerSqm} CHF/m²/J + {/* Single neutral asset-type label */} + + + {getAssetTypeLabel(p.assetType)} {/* ── Body ── */} - + + + {/* ── Occupancy status — primary decision indicator ── */} + + + + {status.label} + {p.availabilityStatus === 'AVAILABLE_SOON' && availDate ? ` · ab ${availDate}` : ''} + + {/* Title + location */} @@ -118,9 +130,8 @@ export const PropertyIntelligenceCard = memo(function PropertyIntelligenceCard({ - {/* 3 key metrics: Fläche · Frei ab · Anfragen */} + {/* 3 key metrics: Fläche · Miete/m² · Anfragen */} - {/* Fläche */} Fläche @@ -130,21 +141,21 @@ export const PropertyIntelligenceCard = memo(function PropertyIntelligenceCard({ - {/* Frei ab */} - Frei ab + Miete - {p.availabilityDate - ? new Date(p.availabilityDate).toLocaleDateString('de-CH', { month: 'short', year: '2-digit' }) - : '—'} + {p.rentPricePerSqm} CHF/m²/J - {/* Anfragen */} - + Anfragen @@ -167,22 +178,16 @@ export const PropertyIntelligenceCard = memo(function PropertyIntelligenceCard({ ) })()} {p.contractDurationMonths && ( - + )} {p.softFactors?.publicTransportMinutes != null && ( - + )} - {/* Data completeness — tells the manager if their listing is ready to match */} + {/* Data completeness — tells manager if listing is visible to matching */} @@ -192,14 +197,9 @@ export const PropertyIntelligenceCard = memo(function PropertyIntelligenceCard({ {confPct}% - +