import { Box, Chip, Paper, Typography } from '@mui/material' import { CheckCircle2, XCircle, Minus } from 'lucide-react' import type { Match } from '../../domain/match' import type { Property } from '../../domain/property' import type { Need } from '../../domain/need' type FitStatus = 'MATCH' | 'NO_MATCH' | 'PARTIAL' | 'UNKNOWN' interface AlignmentRow { label: string needValue: string resultValue: string fit: FitStatus } function fitIcon(fit: FitStatus) { if (fit === 'MATCH') return if (fit === 'NO_MATCH') return if (fit === 'PARTIAL') return return } function fitColor(fit: FitStatus): string { if (fit === 'MATCH') return '#f0fdf4' if (fit === 'NO_MATCH') return '#fef2f2' if (fit === 'PARTIAL') return '#fffbeb' return '#f8fafc' } function buildRows(need: Need, property: Property): AlignmentRow[] { const rows: AlignmentRow[] = [] // Area const areaSqm = property.areaSqm const areaFit: FitStatus = areaSqm >= need.requiredArea.min && areaSqm <= need.requiredArea.max ? 'MATCH' : areaSqm >= need.requiredArea.min * 0.85 ? 'PARTIAL' : 'NO_MATCH' rows.push({ label: 'Fläche', needValue: `${need.requiredArea.min}–${need.requiredArea.max} m²`, resultValue: `${areaSqm} m²`, fit: areaFit, }) // Location const locationFit: FitStatus = need.preferredLocations.some( l => l.toLowerCase() === property.location.city.toLowerCase() || l.toLowerCase() === property.location.district?.toLowerCase() ) ? 'MATCH' : 'PARTIAL' rows.push({ label: 'Standort', needValue: need.preferredLocations.join(', ') || '–', resultValue: property.location.city, fit: locationFit, }) // Budget const budgetFit: FitStatus = property.rentPricePerSqm <= need.budgetRange.maxPerSqm ? 'MATCH' : property.rentPricePerSqm <= need.budgetRange.maxPerSqm * 1.1 ? 'PARTIAL' : 'NO_MATCH' rows.push({ label: 'Budget', needValue: `max. CHF ${need.budgetRange.maxPerSqm}/m²`, resultValue: `CHF ${property.rentPricePerSqm}/m²`, fit: budgetFit, }) // Timing const availDate = property.availabilityDate const latestMoveIn = need.timing.latestMoveIn const timingFit: FitStatus = !availDate ? 'UNKNOWN' : availDate <= latestMoveIn ? 'MATCH' : 'PARTIAL' rows.push({ label: 'Verfügbarkeit', needValue: `bis ${need.timing.latestMoveIn}`, resultValue: availDate || 'unbekannt', fit: timingFit, }) return rows } interface Props { match: Match need: Need | null property: Property | null } export function NeedAlignmentPanel({ match: _match, need, property }: Props) { if (!need || !property) return null const rows = buildRows(need, property) const mustHaves = need.mustHaveCriteria ?? [] return ( Need-Alignment Gesucht: {need.companyName} · {need.assetType} {/* Comparison table */} Kriterium Gesucht Objekt Fit {rows.map((row, i) => ( {row.label} {row.needValue} {row.resultValue} {fitIcon(row.fit)} ))} {/* Must-haves */} {mustHaves.length > 0 && ( Must-have Kriterien {mustHaves.map((m, i) => ( ))} )} ) }