a9e038a64f
Adds MarketKpis domain type with formula-based radius scaling, a MarketKpiPanel component (vacancy rate, platform searches, avg vacancy duration, demand/supply ratio — color-coded with interpretation badges), and integrates it at the top of PropertyMarketSignalsTab. Demand/supply section labels now update with the selected radius. Mock data covers all 5 existing market reports. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
43 lines
1.7 KiB
TypeScript
43 lines
1.7 KiB
TypeScript
export type SignalCategory = 'development' | 'demand' | 'supply' | 'negotiation'
|
|
|
|
export interface PropertyMarketSignal {
|
|
id: string
|
|
category: SignalCategory
|
|
title: string
|
|
body: string
|
|
source?: string
|
|
sourceUrl?: string
|
|
date?: string
|
|
confidence?: number
|
|
}
|
|
|
|
// Key market performance indicators for a given radius.
|
|
// Base values are stored at 5 km; other radii are computed via getKpisForRadius().
|
|
export interface MarketKpis {
|
|
vacancyRatePct: number // % of comparable properties currently vacant
|
|
activePlatformSearches: number // active search requests on the platform
|
|
avgVacancyMonths: number // average months comparable properties remain vacant
|
|
demandSupplyRatio: number // demand / supply ratio (> 1 = more demand than supply)
|
|
comparableListings: number // number of comparable active listings
|
|
}
|
|
|
|
/** Scale base KPIs (at 5 km) for a larger radius. */
|
|
export function getKpisForRadius(base: MarketKpis, radiusKm: number): MarketKpis {
|
|
const f = radiusKm / 5
|
|
return {
|
|
vacancyRatePct: +Math.min(35, base.vacancyRatePct + (f - 1) * 1.8).toFixed(1),
|
|
activePlatformSearches: Math.round(base.activePlatformSearches * f * 0.85),
|
|
avgVacancyMonths: +Math.min(24, base.avgVacancyMonths * (1 + (f - 1) * 0.12)).toFixed(1),
|
|
demandSupplyRatio: +Math.max(0.3, base.demandSupplyRatio / (1 + (f - 1) * 0.18)).toFixed(1),
|
|
comparableListings: Math.round(base.comparableListings * f * 1.1),
|
|
}
|
|
}
|
|
|
|
export interface MarketReport {
|
|
propertyId: string
|
|
generatedAt: string
|
|
assetTypeLabel: string // e.g. "Büro"
|
|
kpis: MarketKpis // base values at 5 km radius
|
|
signals: PropertyMarketSignal[]
|
|
}
|