feat: score transparency on all cards + budget parser fix

- Single scoring system: MockupNeedProvider rewrites matches via calculateScore
  exclusively — allFactors always populated, no more dual-system (computeScore
  removed), weights from weightingProfile reflected in every breakdown
- ScoreInlineBreakdown: new component shows hard/soft criteria with importance
  labels (Entscheidend/Sehr wichtig/…) and formula on compact + expanded cards
- MatchCardAdapter: passes scoreBreakdown + allFactors to ViewModel
- MatchDetail: 'Zukunftssignal' label replaced with 'Future Availability'
- aiService budget parser: values < 100 treated as monthly and multiplied by 12
  to produce correct annual CHF/m²/year value — fixes 0-result searches

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Sutter
2026-05-21 20:41:46 +02:00
parent 34a4dcfb29
commit 27c53f3af1
13 changed files with 1126 additions and 299 deletions
@@ -1,5 +1,5 @@
import type { ResultType } from '../../domain/enums'
import type { TradeOff, Risk, MissingDataItem } from '../../domain/match'
import type { TradeOff, Risk, MissingDataItem, ScoreFactor } from '../../domain/match'
import type { PropertyUnit } from '../../domain/property'
export type MatchCardVariant = 'compact' | 'expanded' | 'review' | 'compare-mini'
@@ -76,6 +76,14 @@ export interface MatchCardViewModel {
preMarketUnit?: PropertyUnit // specific unit being released pre-market
preMarketAllUnits?: PropertyUnit[] // all units of the backing property
// Score transparency
scoreBreakdown?: {
hardMatchScore: number
softFactorScore: number
totalScore: number
}
allFactors?: ScoreFactor[]
// States
isSelected?: boolean
isCompareSelected?: boolean