fix: UX polish — score formula, role badges, compare view, page titles
- Score: remove hidden dataQuality/confidence modifiers from finalScore; formula now correctly shows hard×60% + soft×40% = displayed total - "Ihr Objekt" badge: only shown for PROPERTY_MANAGER/ORGANIZATION_ADMIN in both IntelligenceMatchCard and MatchCardHeader (DEMAND_USER sees Verified Portfolio as a normal listing without ownership indicator) - Compare: fix factor lookup to use allFactors (includes mid-range 45–70 scores) so Prestige, Erreichbarkeit etc. no longer show "Nicht verfügbar" - Compare: richer AI summary with overallAssessment, perPropertyAssessment (strengths/weaknesses/bestFor/keyRisk per property), and recommendation - Compare/Results: pb:10 so CompareTray never overlaps last row of content - AppShell: dynamic route names for /demand/results/:id → "Match Detail" and /demand/property/:id → "Objekt Detail" (no more UUID in header) - MatchDetail: remove "Match EF9" debug chip from sticky nav - LocationIntelligencePanel: comparable listings are now clickable links navigating to /demand/property/:id - Comparable links: blue text + hover highlight Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@ import {
|
||||
Activity, Building2, HardHat, MapPin, Percent,
|
||||
TrendingDown, TrendingUp, Train, Users, Zap,
|
||||
} from 'lucide-react'
|
||||
import { useNavigate } from 'react-router'
|
||||
import { useProperties } from '../../hooks/useProperties'
|
||||
import { getCityIntelligence } from '../../lib/locationIntelligence'
|
||||
import type { Property } from '../../domain/property'
|
||||
@@ -124,6 +125,7 @@ interface Props {
|
||||
}
|
||||
|
||||
export function LocationIntelligencePanel({ property }: Props) {
|
||||
const navigate = useNavigate()
|
||||
const { data: allProperties = [] } = useProperties()
|
||||
|
||||
if (!property) return null
|
||||
@@ -332,11 +334,16 @@ export function LocationIntelligencePanel({ property }: Props) {
|
||||
{comparables.map(p => (
|
||||
<Box
|
||||
key={p.id}
|
||||
sx={{ display: 'flex', alignItems: 'center', gap: 1.5, py: 0.75, borderBottom: '1px solid #f1f5f9' }}
|
||||
onClick={() => navigate(`/demand/property/${p.id}`)}
|
||||
sx={{
|
||||
display: 'flex', alignItems: 'center', gap: 1.5, py: 0.75,
|
||||
borderBottom: '1px solid #f1f5f9', cursor: 'pointer',
|
||||
'&:hover': { bgcolor: '#f8fafc', borderRadius: 0.5 },
|
||||
}}
|
||||
>
|
||||
<Building2 size={13} color="#64748b" />
|
||||
<Building2 size={13} color="#3b82f6" />
|
||||
<Box sx={{ flex: 1, minWidth: 0 }}>
|
||||
<Typography variant="caption" sx={{ fontWeight: 500, display: 'block', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
|
||||
<Typography variant="caption" sx={{ fontWeight: 500, display: 'block', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', color: '#1d4ed8' }}>
|
||||
{p.title}
|
||||
</Typography>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
|
||||
@@ -114,6 +114,7 @@ function StandardBreakdown({ match, taxCalculatorUrl }: StandardBreakdownProps)
|
||||
|
||||
const hardContrib = Math.round(sb.hardMatchScore * 0.60 * 10) / 10
|
||||
const softContrib = Math.round(sb.softFactorScore * 0.40 * 10) / 10
|
||||
const baseSum = Math.round((hardContrib + softContrib) * 10) / 10
|
||||
const maxHardWeight = Math.max(...hardFactors.map(f => f.weight), 0.001)
|
||||
const maxSoftWeight = Math.max(...softFactors.map(f => f.weight), 0.001)
|
||||
|
||||
@@ -195,22 +196,22 @@ function StandardBreakdown({ match, taxCalculatorUrl }: StandardBreakdownProps)
|
||||
</Typography>
|
||||
<Typography variant="caption" sx={{ fontFamily: 'monospace', color: '#1e293b', display: 'block', lineHeight: 1.6 }}>
|
||||
Hart {sb.hardMatchScore} × 60% + Soft {sb.softFactorScore} × 40%
|
||||
{' = '}{hardContrib} + {softContrib} = {sb.totalScore}
|
||||
{' = '}{hardContrib} + {softContrib} = {baseSum}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
{/* Total */}
|
||||
<Box sx={{
|
||||
display: 'flex', alignItems: 'baseline', justifyContent: 'space-between',
|
||||
bgcolor: sb.totalScore >= 78 ? '#f0fdf4' : sb.totalScore >= 52 ? '#fffbeb' : '#fef2f2',
|
||||
bgcolor: baseSum >= 78 ? '#f0fdf4' : baseSum >= 52 ? '#fffbeb' : '#fef2f2',
|
||||
p: 1.5, borderRadius: 1,
|
||||
}}>
|
||||
<Typography variant="subtitle1" sx={{ fontWeight: 700 }}>Gesamt-Score</Typography>
|
||||
<Typography
|
||||
variant="h4"
|
||||
sx={{ fontWeight: 800, color: scoreTextColor(sb.totalScore) }}
|
||||
sx={{ fontWeight: 800, color: scoreTextColor(Math.round(baseSum)) }}
|
||||
>
|
||||
{sb.totalScore}/100
|
||||
{baseSum}/100
|
||||
</Typography>
|
||||
</Box>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user