Files
property-match/src/components/match-detail/PropertyOverviewPanel.tsx
T
Benjamin Sutter f487435a94 fix: correct rent unit labels and monthly/annual calculation consistency
- NeedAlignmentPanel: display budget row in monthly (CHF/m²/Mt.) to match
  the Preis section, use exact division (no Math.round) to avoid 13×12≠152
- MatchDetailPropertySections + PropertyDetailPublicSections: replace
  Math.round(rentPricePerSqm/12) with exact division; show 2 decimal places
  when monthly is not a whole number (e.g. CHF 12.67 instead of CHF 13)
- Add /Jahr suffix to all 15 displays showing rentPricePerSqm or maxPerSqm
  without a time unit across results, compare, match-detail, supply, and
  anfragencenter components

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 14:35:20 +02:00

68 lines
3.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Box, Chip, Paper, Typography } from '@mui/material'
import { Banknote, Calendar, MapPin, Maximize2, Tag } from 'lucide-react'
import type { Match } from '../../domain/match'
import type { Property } from '../../domain/property'
import type { FutureSignal } from '../../domain/futureSignal'
interface FactRowProps {
icon: React.ReactNode
label: string
value: string
}
function FactRow({ icon, label, value }: FactRowProps) {
return (
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5, py: 1, borderBottom: '1px solid #f1f5f9' }}>
<Box sx={{ color: '#64748b', flexShrink: 0 }}>{icon}</Box>
<Typography variant="body2" color="text.secondary" sx={{ minWidth: 140 }}>{label}</Typography>
<Typography variant="body2" sx={{ fontWeight: 500 }}>{value}</Typography>
</Box>
)
}
interface Props {
match: Match
property: Property | null
signal: FutureSignal | null
}
export function PropertyOverviewPanel({ match, property, signal }: Props) {
if (!property && !signal) return null
const isFuture = match.resultType === 'FUTURE_AVAILABILITY'
const rows: FactRowProps[] = isFuture ? [
{ icon: <MapPin size={15} />, label: 'Standorthinweis', value: signal?.locationHint ?? '' },
{ icon: <Maximize2 size={15} />, label: 'Flächenschätzung', value: signal?.areaSqmEstimate ? `~${signal.areaSqmEstimate}` : 'unbekannt' },
{ icon: <Calendar size={15} />, label: 'Zeithorizont', value: signal?.timeHorizonMonths ? `~${signal.timeHorizonMonths} Monate` : '' },
{ icon: <Tag size={15} />, label: 'Wahrscheinlichkeit', value: signal?.probability ? `${Math.round(signal.probability * 100)}%` : '' },
] : [
{ icon: <MapPin size={15} />, label: 'Standort', value: property ? `${property.location.city}${property.location.district ? `, ${property.location.district}` : ''}` : '' },
{ icon: <Maximize2 size={15} />, label: 'Nutzfläche', value: property ? `${property.areaSqm}` : '' },
{ icon: <Banknote size={15} />, label: 'Mietpreis', value: property?.rentPricePerSqm ? `CHF ${property.rentPricePerSqm}/m²/Jahr` : '' },
{ icon: <Calendar size={15} />, label: 'Verfügbar ab', value: property?.availabilityDate ?? '' },
{ icon: <Tag size={15} />, label: 'Objekttyp', value: property?.assetType ?? '' },
]
return (
<Paper sx={{ p: 2.5, mb: 2 }}>
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', mb: 1.5 }}>
<Typography variant="h6" sx={{ fontWeight: 700 }}>
{isFuture ? 'Signal-Übersicht' : 'Objekt-Übersicht'}
</Typography>
{property?.status && (
<Chip label={property.status} size="small" variant="outlined" />
)}
</Box>
{rows.map((row, i) => (
<FactRow key={i} {...row} />
))}
{property?.description && (
<Typography variant="body2" color="text.secondary" sx={{ mt: 1.5, fontStyle: 'italic' }}>
{property.description}
</Typography>
)}
</Paper>
)
}