feat: Objekt→Einheit architecture — unit-level pre-market, property detail page, click-through from cards

- Domain: PropertyUnit extended with propertyId + schattenmarktRelease per unit
- Domain: FutureAvailabilityResult carries resolved property + unit
- useSchattenmarktSignals: generates unit-level signals (schattenmarkt-{propId}-{unitId})
- useUnifiedResults: resolves backing property + unit on FUTURE_AVAILABILITY fast path
- IUnitProvider + MockupUnitProvider: first-class unit access and mutation
- matchCardAdapter: maps preMarketUnit, preMarketAllUnits, propertyId, unitId to ViewModel
- IntelligenceMatchCard: PRE-MARKET VERIFIED shows unit info strip + "Zur Einheit →" button
- PropertyDetailView: unit-level toggles + date pickers inside PreMarketPanel
- New page: /demand/property/:propertyId with unit table, status chips, inquiry form
- App.tsx: demand route /demand/property/:propertyId registered
- Mock data: prop-001/007/037 units updated with correct lease dates + unit-level schattenmarktRelease

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Sutter
2026-05-20 19:47:59 +02:00
parent 66aabde1dc
commit d902feb6c0
14 changed files with 578 additions and 18 deletions
+10 -2
View File
@@ -36,10 +36,11 @@ export function buildMatchCardViewModel(
const isFuture = resultType === 'FUTURE_AVAILABILITY'
const property = !isFuture
? (result as VerifiedPortfolioResult | ExternalMarketResult).property
: undefined
: (result as FutureAvailabilityResult).property
const signal = isFuture
? (result as FutureAvailabilityResult).signal
: undefined
const unit = isFuture ? (result as FutureAvailabilityResult).unit : undefined
const city = property?.location?.city
const district = property?.location?.district
@@ -47,6 +48,9 @@ export function buildMatchCardViewModel(
? `${city}${district ? `, ${district}` : ''}`
: signal?.locationHint ?? ''
// For PRE-MARKET: title comes from unit if available, then signal, then property
const availabilityLabel =
property?.availabilityDate ??
(signal?.timeHorizonMonths ? `~${signal.timeHorizonMonths} Monate` : undefined)
@@ -69,8 +73,8 @@ export function buildMatchCardViewModel(
return {
id: result.matchId,
title:
property?.title ??
signal?.title ??
property?.title ??
signal?.companyName ??
signal?.locationHint ??
'',
@@ -116,5 +120,9 @@ export function buildMatchCardViewModel(
signalConfirmedFacts: signal?.confirmedFacts,
signalUnconfirmedFacts: signal?.unconfirmedFacts,
signalAreaSqmEstimate: signal?.areaSqmEstimate,
propertyId: property?.id ?? signal?.propertyId,
unitId: unit?.id ?? signal?.unitId,
preMarketUnit: unit,
preMarketAllUnits: property?.units,
}
}