diff --git a/src/components/anfragencenter/MockPdfPreview.tsx b/src/components/anfragencenter/MockPdfPreview.tsx
index 16990f1..c0270d4 100644
--- a/src/components/anfragencenter/MockPdfPreview.tsx
+++ b/src/components/anfragencenter/MockPdfPreview.tsx
@@ -73,7 +73,7 @@ export function MockPdfPreview({ fields, fallbackFields }: MockPdfPreviewProps)
variant="body2"
sx={{ fontSize: '0.875rem', mb: 0.5, lineHeight: 1.5 }}
>
- {p.title} — {p.location.city}, {p.areaSqm.toLocaleString('de-CH')} m², CHF {p.rentPricePerSqm}/m²
+ {p.title} — {p.location.city}, {p.areaSqm.toLocaleString('de-CH')} m², CHF {p.rentPricePerSqm}/m²/Jahr
))}
{properties.length === 0 && (
diff --git a/src/components/anfragencenter/RelatedPropertyCardPanel.tsx b/src/components/anfragencenter/RelatedPropertyCardPanel.tsx
index 9ba6f3b..6905bc9 100644
--- a/src/components/anfragencenter/RelatedPropertyCardPanel.tsx
+++ b/src/components/anfragencenter/RelatedPropertyCardPanel.tsx
@@ -94,7 +94,7 @@ export function RelatedPropertyCardPanel({ propertyId, inquiryId }: RelatedPrope
- {property.areaSqm.toLocaleString('de-CH')} m² · CHF {property.rentPricePerSqm}/m²
+ {property.areaSqm.toLocaleString('de-CH')} m² · CHF {property.rentPricePerSqm}/m²/Jahr
@@ -190,7 +190,7 @@ function AdditionalMatchCard({ match }: { match: AdditionalPropertyMatch }) {
- {match.location} · {match.areaSqm.toLocaleString('de-CH')} m² · CHF {match.rentPricePerSqm}/m²
+ {match.location} · {match.areaSqm.toLocaleString('de-CH')} m² · CHF {match.rentPricePerSqm}/m²/Jahr
{match.reasons.length > 0 && (
diff --git a/src/components/compare/CompareColumnHeader.tsx b/src/components/compare/CompareColumnHeader.tsx
index e94a82d..eeab57d 100644
--- a/src/components/compare/CompareColumnHeader.tsx
+++ b/src/components/compare/CompareColumnHeader.tsx
@@ -43,7 +43,7 @@ export function CompareColumnHeader({ item, onRemove }: Props) {
propertyId: prop?.id,
propertyAddress: prop ? `${title}, ${subtitle}${district ? `, ${district}` : ''}` : undefined,
areaLabel: prop?.areaSqm ? `${prop.areaSqm.toLocaleString('de-CH')} m²` : undefined,
- rentLabel: prop?.rentPricePerSqm ? `CHF ${prop.rentPricePerSqm}/m²` : undefined,
+ rentLabel: prop?.rentPricePerSqm ? `CHF ${prop.rentPricePerSqm}/m²/Jahr` : undefined,
availabilityLabel: prop?.availabilityDate ?? undefined,
})
}
diff --git a/src/components/compare/CompareTableBody.tsx b/src/components/compare/CompareTableBody.tsx
index fa83728..c3a8006 100644
--- a/src/components/compare/CompareTableBody.tsx
+++ b/src/components/compare/CompareTableBody.tsx
@@ -155,7 +155,7 @@ export function CompareTableBody({
return (
- CHF {prop.rentPricePerSqm}/m²
+ CHF {prop.rentPricePerSqm}/m²/Jahr
{prop.totalRentMonthly && (
diff --git a/src/components/demand/CriteriaReviewPanel.tsx b/src/components/demand/CriteriaReviewPanel.tsx
index 113f159..d031e7b 100644
--- a/src/components/demand/CriteriaReviewPanel.tsx
+++ b/src/components/demand/CriteriaReviewPanel.tsx
@@ -38,7 +38,7 @@ function displayAreaRange(v: ParsedNeedCriteria['areaRange']): string {
return v ? `${v.min}–${v.max} m²` : ''
}
function displayBudget(v: ParsedNeedCriteria['budgetRange']): string {
- return v ? `CHF ${v.maxPerSqm}/m²` : ''
+ return v ? `CHF ${v.maxPerSqm}/m²/Jahr` : ''
}
function displayTiming(v: ParsedNeedCriteria['timing']): string {
if (!v) return ''
diff --git a/src/components/demand/NeedCardPreview.tsx b/src/components/demand/NeedCardPreview.tsx
index 77efd59..40ea99e 100644
--- a/src/components/demand/NeedCardPreview.tsx
+++ b/src/components/demand/NeedCardPreview.tsx
@@ -95,7 +95,7 @@ export function NeedCardPreview({ criteria: c, weights, confidenceByField, missi
Budget
- max. CHF {c.budgetRange.maxPerSqm}/m²
+ max. CHF {c.budgetRange.maxPerSqm}/m²/Jahr
)}
diff --git a/src/components/match-detail/LocationIntelligencePanel.tsx b/src/components/match-detail/LocationIntelligencePanel.tsx
index e780af6..aaab91e 100644
--- a/src/components/match-detail/LocationIntelligencePanel.tsx
+++ b/src/components/match-detail/LocationIntelligencePanel.tsx
@@ -241,7 +241,7 @@ export function LocationIntelligencePanel({ property }: Props) {
{p.title}
- {p.areaSqm} m² · CHF {p.rentPricePerSqm}/m²
+ {p.areaSqm} m² · CHF {p.rentPricePerSqm}/m²/Jahr
{p.rentPricePerSqm < property.rentPricePerSqm && ' · günstiger'}
{p.rentPricePerSqm > property.rentPricePerSqm && ' · teurer'}
diff --git a/src/components/match-detail/MatchDetailPropertySections.tsx b/src/components/match-detail/MatchDetailPropertySections.tsx
index 447918d..1d80d0b 100644
--- a/src/components/match-detail/MatchDetailPropertySections.tsx
+++ b/src/components/match-detail/MatchDetailPropertySections.tsx
@@ -17,8 +17,11 @@ export function MatchDetailPropertySections({ property, match }: MatchDetailProp
const flexibleUnits = units.filter(u => u.isFlexible && u.minLettableSqm != null)
const preMarketUnits = units.filter(u => u.schattenmarktRelease?.enabled)
const otherUnits = units.filter(u => !u.schattenmarktRelease?.enabled)
- const monthlyPerSqm = Math.round(property.rentPricePerSqm / 12)
const totalMonthly = Math.round(property.areaSqm * property.rentPricePerSqm / 12)
+ const rawMonthlyPerSqm = property.rentPricePerSqm / 12
+ const monthlyPerSqmLabel = Number.isInteger(rawMonthlyPerSqm)
+ ? `CHF ${rawMonthlyPerSqm}.–`
+ : `CHF ${rawMonthlyPerSqm.toLocaleString('de-CH', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`
const minLettable = property.areaSqmMin ?? (flexibleUnits.length > 0 ? Math.min(...flexibleUnits.map(u => u.minLettableSqm!)) : undefined)
const sourceLabel = property.sourceLabel ?? property.sourceMeta?.sourceLabel ?? SOURCE_LABELS[property.sourceType] ?? property.sourceType
@@ -31,7 +34,7 @@ export function MatchDetailPropertySections({ property, match }: MatchDetailProp
Preis
-
+
{property.ancillaryCosts != null && (
diff --git a/src/components/match-detail/NeedAlignmentPanel.tsx b/src/components/match-detail/NeedAlignmentPanel.tsx
index 52d30f7..807b38a 100644
--- a/src/components/match-detail/NeedAlignmentPanel.tsx
+++ b/src/components/match-detail/NeedAlignmentPanel.tsx
@@ -56,16 +56,22 @@ function buildRows(need: Need, property: Property): AlignmentRow[] {
fit: locationFit,
})
- // Budget
+ // Budget — both values are annual CHF/m²; display as monthly for consistency with Preis section
const budgetFit: FitStatus = property.rentPricePerSqm <= need.budgetRange.maxPerSqm
? 'MATCH'
: property.rentPricePerSqm <= need.budgetRange.maxPerSqm * 1.1
? 'PARTIAL'
: 'NO_MATCH'
+ function fmtMt(annual: number): string {
+ const m = annual / 12
+ return Number.isInteger(m)
+ ? `CHF ${m}.–/m²/Mt.`
+ : `CHF ${m.toLocaleString('de-CH', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}/m²/Mt.`
+ }
rows.push({
label: 'Budget',
- needValue: `max. CHF ${need.budgetRange.maxPerSqm}/m²`,
- resultValue: `CHF ${property.rentPricePerSqm}/m²`,
+ needValue: `max. ${fmtMt(need.budgetRange.maxPerSqm)}`,
+ resultValue: fmtMt(property.rentPricePerSqm),
fit: budgetFit,
})
diff --git a/src/components/match-detail/PropertyDetailPublicSections.tsx b/src/components/match-detail/PropertyDetailPublicSections.tsx
index 66980c2..285ee32 100644
--- a/src/components/match-detail/PropertyDetailPublicSections.tsx
+++ b/src/components/match-detail/PropertyDetailPublicSections.tsx
@@ -37,8 +37,11 @@ export function PropertyDetailPublicSections({ property, highlightUnitId }: Prop
const otherUnits = (property.units ?? []).filter(u => !u.schattenmarktRelease?.enabled)
const flexibleUnits = (property.units ?? []).filter(u => u.isFlexible && u.minLettableSqm !== undefined)
- const monthlyPerSqm = Math.round(property.rentPricePerSqm / 12)
const totalMonthly = Math.round(property.areaSqm * property.rentPricePerSqm / 12)
+ const rawMonthlyPerSqm = property.rentPricePerSqm / 12
+ const monthlyPerSqmLabel = Number.isInteger(rawMonthlyPerSqm)
+ ? `CHF ${rawMonthlyPerSqm}.–`
+ : `CHF ${rawMonthlyPerSqm.toLocaleString('de-CH', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`
const minLettable = property.areaSqmMin
?? (flexibleUnits.length > 0
? Math.min(...flexibleUnits.map(u => u.minLettableSqm!))
@@ -58,7 +61,7 @@ export function PropertyDetailPublicSections({ property, highlightUnitId }: Prop
Preis
-
+
{property.ancillaryCosts != null && (
, label: 'Standort', value: property ? `${property.location.city}${property.location.district ? `, ${property.location.district}` : ''}` : '–' },
{ icon: , label: 'Nutzfläche', value: property ? `${property.areaSqm} m²` : '–' },
- { icon: , label: 'Mietpreis', value: property?.rentPricePerSqm ? `CHF ${property.rentPricePerSqm}/m²` : '–' },
+ { icon: , label: 'Mietpreis', value: property?.rentPricePerSqm ? `CHF ${property.rentPricePerSqm}/m²/Jahr` : '–' },
{ icon: , label: 'Verfügbar ab', value: property?.availabilityDate ?? '–' },
{ icon: , label: 'Objekttyp', value: property?.assetType ?? '–' },
]
diff --git a/src/components/results/UnifiedResultCard.tsx b/src/components/results/UnifiedResultCard.tsx
index c076495..868be47 100644
--- a/src/components/results/UnifiedResultCard.tsx
+++ b/src/components/results/UnifiedResultCard.tsx
@@ -44,7 +44,7 @@ export function UnifiedResultCard({ result, view = 'list' }: Props) {
propertyId: prop?.id,
propertyAddress: prop ? `${prop.title}, ${prop.location?.city ?? ''}` : undefined,
areaLabel: prop?.areaSqm ? `${prop.areaSqm.toLocaleString('de-CH')} m²` : undefined,
- rentLabel: prop?.rentPricePerSqm ? `CHF ${prop.rentPricePerSqm}/m²` : undefined,
+ rentLabel: prop?.rentPricePerSqm ? `CHF ${prop.rentPricePerSqm}/m²/Jahr` : undefined,
})
},
},
diff --git a/src/components/supply/NegotiationInsightsPanel.tsx b/src/components/supply/NegotiationInsightsPanel.tsx
index baae88e..66f6567 100644
--- a/src/components/supply/NegotiationInsightsPanel.tsx
+++ b/src/components/supply/NegotiationInsightsPanel.tsx
@@ -50,7 +50,7 @@ export function NegotiationInsightsPanel({ property }: Props) {
Ihr Preis
- CHF {property.rentPricePerSqm}/m²
+ CHF {property.rentPricePerSqm}/m²/Jahr
{marketRent && (
@@ -130,7 +130,7 @@ export function NegotiationInsightsPanel({ property }: Props) {
{n.companyName}
{n.requiredArea?.min ?? 0}–{n.requiredArea?.max ?? 0} m²
- {n.budgetRange?.maxPerSqm ? ` · max. CHF ${n.budgetRange.maxPerSqm}/m²` : ''}
+ {n.budgetRange?.maxPerSqm ? ` · max. CHF ${n.budgetRange.maxPerSqm}/m²/Jahr` : ''}
-
+
{p.contractDurationMonths && (
)}
diff --git a/src/pages/demand/MatchDetail.tsx b/src/pages/demand/MatchDetail.tsx
index 9a651af..7dd587c 100644
--- a/src/pages/demand/MatchDetail.tsx
+++ b/src/pages/demand/MatchDetail.tsx
@@ -108,7 +108,7 @@ export default function MatchDetail() {
matchScore: match.matchScore,
location: property?.location?.city,
areaLabel: property?.areaSqm ? `${property.areaSqm.toLocaleString('de-CH')} m²` : undefined,
- rentLabel: property?.rentPricePerSqm ? `CHF ${property.rentPricePerSqm}/m²` : undefined,
+ rentLabel: property?.rentPricePerSqm ? `CHF ${property.rentPricePerSqm}/m²/Jahr` : undefined,
})
}
diff --git a/src/pages/demand/Results.tsx b/src/pages/demand/Results.tsx
index 041292c..d3a306f 100644
--- a/src/pages/demand/Results.tsx
+++ b/src/pages/demand/Results.tsx
@@ -155,7 +155,7 @@ export default function Results() {
{activeNeed.budgetRange && activeNeed.budgetRange.maxPerSqm > 0 && (
- Budget: max. CHF {activeNeed.budgetRange.maxPerSqm}/m²
+ Budget: max. CHF {activeNeed.budgetRange.maxPerSqm}/m²/Jahr
)}
{activeNeed.timing?.earliestMoveIn && !isNaN(new Date(activeNeed.timing.earliestMoveIn).getTime()) && (