import { Box, Divider, LinearProgress, Typography } from '@mui/material' import type { ScoreFactor } from '../../domain/match' import { criterionScoreColor, criterionScoreTextColor } from '../../lib/utils' interface ScoreBreakdownData { hardMatchScore: number softFactorScore: number totalScore: number } interface Props { scoreBreakdown: ScoreBreakdownData allFactors?: ScoreFactor[] compact?: boolean } const CRITERION_LABEL: Record = { area: 'Fläche', location: 'Standort', budget: 'Budget', timing: 'Verfügbarkeit', prestige: 'Prestige', accessibility: 'Erreichbarkeit', expansionPotential: 'Expansion', flexibility: 'Flexibilität', visibility: 'Sichtbarkeit', footfall: 'Passantenfrequenz', talentAccess: 'Talent-Zugang', esg: 'ESG', taxEnvironment: 'Steuerumfeld', } const HARD_KEYS = new Set(['area', 'location', 'budget', 'timing']) function importanceLabel(weight: number, maxWeight: number): { label: string; color: string } { const ratio = maxWeight > 0 ? weight / maxWeight : 0 if (ratio >= 0.85) return { label: 'Entscheidend', color: '#152642' } if (ratio >= 0.65) return { label: 'Sehr wichtig', color: '#1d4ed8' } if (ratio >= 0.40) return { label: 'Wichtig', color: '#475569' } if (ratio >= 0.20) return { label: 'Wenig wichtig',color: '#94a3b8' } return { label: 'Unwichtig', color: '#cbd5e1' } } function FactorRow({ factor, maxWeight }: { factor: ScoreFactor; maxWeight: number }) { const label = CRITERION_LABEL[factor.criterion] ?? factor.criterion const pct = Math.round(factor.weight * 100) const imp = importanceLabel(factor.weight, maxWeight) const color = criterionScoreColor(factor.score) return ( {label} {imp.label} {pct}% {factor.score}/100 {factor.contribution.toFixed(1)} Pkt {factor.explanation} ) } export function ScoreInlineBreakdown({ scoreBreakdown: sb, allFactors, compact = false }: Props) { const hardContrib = Math.round(sb.hardMatchScore * 0.60 * 10) / 10 const softContrib = Math.round(sb.softFactorScore * 0.40 * 10) / 10 const formulaBox = ( Berechnung Hart {sb.hardMatchScore} × 60% + Soft {sb.softFactorScore} × 40% {' = '}{hardContrib} + {softContrib}{' = '} {sb.totalScore} ) // Compact: only the formula line if (compact || !allFactors || allFactors.length === 0) { return formulaBox } // Full: all criteria + formula const hardFactors = allFactors.filter(f => HARD_KEYS.has(f.criterion)) const softFactors = allFactors.filter(f => !HARD_KEYS.has(f.criterion)) const maxHardWeight = Math.max(...hardFactors.map(f => f.weight), 0.001) const maxSoftWeight = Math.max(...softFactors.map(f => f.weight), 0.001) return ( Hart-Kriterien {hardFactors.map((f, i) => )} 0 ? 2 : 1.5 }}> {sb.hardMatchScore}/100 × 60% {hardContrib} Pkt {softFactors.length > 0 && ( <> Soft-Faktoren {softFactors.map((f, i) => )} {sb.softFactorScore}/100 × 40% {softContrib} Pkt )} {formulaBox} ) }