Files
property-match/src/components/results/UnifiedResultCard.tsx
T
Benjamin Sutter 65130efca7 feat: F015 shortlist management
3-panel Shortlists page with left list, center detail, right decision brief panel. AddToShortlistDialog wired into result feed cards and match detail. Full DRAFT→REVIEW_READY→FINALIZED workflow, AI-generated decision brief draft, duplicate prevention, and compare-view integration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 21:10:06 +02:00

65 lines
2.1 KiB
TypeScript

import { useNavigate } from 'react-router'
import { MatchCardCompact } from '../match-card/MatchCardCompact'
import { buildMatchCardViewModel } from '../../features/matching/matchCardAdapter'
import { useCompareStore } from '../../stores/compareStore'
import { useShortlistStore } from '../../stores/shortlistStore'
import type { UnifiedMatchResult } from '../../domain/unifiedResult'
import type { MatchCardAction } from '../match-card/MatchCardViewModel'
interface Props {
result: UnifiedMatchResult
}
function getResultTitle(result: UnifiedMatchResult): string {
if (result.resultType !== 'FUTURE_AVAILABILITY') {
return (result as any).property?.title ?? result.matchId
}
return (result as any).signal?.companyName ?? result.matchId
}
export function UnifiedResultCard({ result }: Props) {
const navigate = useNavigate()
const { addToCompare, removeFromCompare, isInCompare, isFull } = useCompareStore()
const { openAddDialog } = useShortlistStore()
const inCompare = isInCompare(result.matchId)
const actions: MatchCardAction[] = [
{
id: 'shortlist',
label: 'Shortlist',
actionType: 'SAVE_SHORTLIST',
variant: 'secondary',
onClick: () => openAddDialog({
resultId: result.matchId,
resultType: result.resultType,
title: getResultTitle(result),
matchScore: result.matchScore,
confidenceScore: result.match.confidenceLevel,
sourceLabel: result.resultType,
addedBy: 'admin@ideal-sharing.ch',
}),
},
{
id: 'compare',
label: inCompare ? 'Im Vergleich' : 'Vergleichen',
actionType: 'ADD_COMPARE',
variant: inCompare ? 'primary' : 'secondary',
disabled: !inCompare && isFull(),
onClick: () => {
if (inCompare) removeFromCompare(result.matchId)
else addToCompare(result)
},
},
{
id: 'details',
label: 'Details',
actionType: 'OPEN_DETAIL',
variant: 'primary',
onClick: () => navigate(`/demand/results/${result.matchId}`),
},
]
const vm = buildMatchCardViewModel(result, actions)
return <MatchCardCompact vm={vm} />
}