import { useNavigate } from 'react-router' import { MatchCardCompact } from '../match-card/MatchCardCompact' import { IntelligenceMatchCard } from '../match-card/IntelligenceMatchCard' import { buildMatchCardViewModel } from '../../features/matching/matchCardAdapter' import { resolveImageLabel } from '../../lib/propertyImageResolver' import { useCompareStore } from '../../stores/compareStore' import { usePipelineStore } from '../../stores/pipelineStore' import type { UnifiedMatchResult } from '../../domain/unifiedResult' import type { MatchCardAction } from '../match-card/MatchCardViewModel' interface Props { result: UnifiedMatchResult view?: 'list' | 'grid' } function getResultTitle(result: UnifiedMatchResult): string { if (result.resultType !== 'FUTURE_AVAILABILITY') { return result.property?.title ?? result.matchId } return result.signal?.companyName ?? result.matchId } export function UnifiedResultCard({ result, view = 'list' }: Props) { const navigate = useNavigate() const { addToCompare, removeFromCompare, isInCompare, isFull } = useCompareStore() const { openSavedDialog } = usePipelineStore() const inCompare = isInCompare(result.matchId) const isPortfolio = result.resultType === 'VERIFIED_PORTFOLIO' const actions: MatchCardAction[] = [ { id: 'shortlist', label: 'Merken', actionType: 'SAVE_SHORTLIST', variant: 'secondary', onClick: () => { const prop = result.resultType !== 'FUTURE_AVAILABILITY' ? (result as any).property : null openSavedDialog({ resultId: result.matchId, resultType: result.resultType, title: getResultTitle(result), matchScore: result.matchScore, location: prop?.location?.city, propertyId: prop?.id, propertyAddress: prop ? `${prop.title}, ${prop.location?.city ?? ''}` : undefined, areaLabel: prop?.areaSqm ? `${prop.areaSqm.toLocaleString('de-CH')} m²` : undefined, rentLabel: prop?.rentPricePerSqm ? `CHF ${prop.rentPricePerSqm}/m²/Jahr` : undefined, }) }, }, { 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', // Downgrade to secondary when the unit CTA is the primary action variant: isPortfolio ? 'secondary' : 'primary', onClick: () => navigate(`/demand/results/${result.matchId}`), }, // Portfolio properties: direct link to unit page + management inquiry form ...(isPortfolio ? [{ id: 'contact', label: 'Zur Einheit →', actionType: 'OPEN_DETAIL' as const, variant: 'primary' as const, onClick: () => { const propId = result.property.id const unitId = result.match.unitId navigate(`/demand/property/${propId}${unitId ? `?unit=${unitId}` : ''}`) }, }] : []), ] const vm = buildMatchCardViewModel(result, actions) if (view === 'grid') { const imageUrl = result.resultType !== 'FUTURE_AVAILABILITY' ? result.property.images?.[0] : undefined const lat = result.resultType !== 'FUTURE_AVAILABILITY' ? result.property.location.coordinates?.lat : undefined const lng = result.resultType !== 'FUTURE_AVAILABILITY' ? result.property.location.coordinates?.lng : undefined const cityLabel = result.resultType !== 'FUTURE_AVAILABILITY' ? result.property.location.city : result.signal.locationHint ?? undefined const overlayLabels = result.resultType !== 'FUTURE_AVAILABILITY' ? resolveImageLabel({ assetType: result.property.assetType, city: result.property.location.city, district: result.property.location.district, prestige: result.property.softFactors?.prestige, floorLevel: result.property.floorLevel, propertyId: result.property.id, }) : null return ( ) } const listImageUrl = result.resultType !== 'FUTURE_AVAILABILITY' ? result.property.images?.[0] : undefined return }