feat: F012 match detail view

Full decision analysis page at /demand/results/:matchId:
- MatchDetailHeader: score, badges, CTA (compare/shortlist), back button
- ExecutiveSummaryPanel: 4-row summary (fit, top reason, tradeoff, next step)
- PropertyOverviewPanel: key facts grid; signal-aware for FUTURE_AVAILABILITY
- NeedAlignmentPanel: comparison table with fit indicators (MATCH/PARTIAL/NO_MATCH)
- ScoreBreakdownPanel: hard/soft scores + modifiers + total (sidebar)
- TradeoffPanel: severity-coded list with mitigation hints
- RiskPanel: risks sorted CRITICAL→LOW with category chips
- MissingInformationPanel: priority-grouped with per-item CTAs
- SourceProvenancePanel: source type, label, URL, freshness
- FutureAvailabilityContextPanel: mandatory disclaimer + signal metadata
- NextActionsPanel: engine-ranked actions + standard actions (sidebar)
- Details button on result cards now navigates to match detail

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Sutter
2026-05-16 13:55:46 +02:00
parent ea221def74
commit 7cf8d8ba72
16 changed files with 1115 additions and 2 deletions
+3 -2
View File
@@ -1,3 +1,4 @@
import { useNavigate } from 'react-router'
import { MatchCardCompact } from '../match-card/MatchCardCompact'
import { buildMatchCardViewModel } from '../../features/matching/matchCardAdapter'
import type { UnifiedMatchResult } from '../../domain/unifiedResult'
@@ -10,6 +11,7 @@ interface Props {
}
export function UnifiedResultCard({ result, isInCompare, onCompare }: Props) {
const navigate = useNavigate()
const isFuture = result.resultType === 'FUTURE_AVAILABILITY'
const compareId = !isFuture
? (result as { property: { id: string } }).property.id
@@ -40,8 +42,7 @@ export function UnifiedResultCard({ result, isInCompare, onCompare }: Props) {
label: 'Details',
actionType: 'OPEN_DETAIL',
variant: 'primary',
disabled: true,
onClick: () => {},
onClick: () => navigate(`/demand/results/${result.matchId}`),
},
]