feat: remove EXTERNAL_MARKET result type entirely

All external market properties now surface as VERIFIED_PORTFOLIO.
Removes the type from enums, domain types, mock data, matching engine,
components, hooks, and tests — zero user-visible distinction remains.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Sutter
2026-05-24 17:28:42 +02:00
parent 11de05025c
commit 609a3634bd
29 changed files with 60 additions and 102 deletions
+3 -1
View File
@@ -11,7 +11,9 @@
"Bash(start http://localhost:5173)", "Bash(start http://localhost:5173)",
"Bash(npm install *)", "Bash(npm install *)",
"Bash(git pull *)", "Bash(git pull *)",
"Bash(node scripts/check-tokens.js)" "Bash(node scripts/check-tokens.js)",
"Bash(echo \"EXIT:$?\")",
"Bash(echo \"EXIT_CODE:$?\")"
] ]
} }
} }
+2 -1
View File
@@ -2,7 +2,8 @@
"permissions": { "permissions": {
"allow": [ "allow": [
"Bash(git commit -m ' *)", "Bash(git commit -m ' *)",
"Bash(git commit *)" "Bash(git commit *)",
"Bash(node -e ' *)"
] ]
} }
} }
+1 -2
View File
@@ -1,5 +1,5 @@
import { Chip } from '@mui/material' import { Chip } from '@mui/material'
import { ShieldCheck, Globe, Building2, Sparkles } from 'lucide-react' import { ShieldCheck, Building2, Sparkles } from 'lucide-react'
import type { ResultType } from '../../domain/enums' import type { ResultType } from '../../domain/enums'
import { DS_COLORS } from '../../lib/ds' import { DS_COLORS } from '../../lib/ds'
import { RESULT_TYPE_LABELS } from '../../lib/constants' import { RESULT_TYPE_LABELS } from '../../lib/constants'
@@ -11,7 +11,6 @@ interface ResultTypeBadgeProps {
const ICONS: Record<ResultType, React.ElementType> = { const ICONS: Record<ResultType, React.ElementType> = {
VERIFIED_PORTFOLIO: ShieldCheck, VERIFIED_PORTFOLIO: ShieldCheck,
EXTERNAL_MARKET: Globe,
MAISON_WORK: Building2, MAISON_WORK: Building2,
FUTURE_AVAILABILITY: Sparkles, FUTURE_AVAILABILITY: Sparkles,
} }
-1
View File
@@ -10,7 +10,6 @@ interface SourceTypeBadgeProps {
const CONFIG: Record<string, { bg: string; color: string; Icon: React.ElementType }> = { const CONFIG: Record<string, { bg: string; color: string; Icon: React.ElementType }> = {
VERIFIED_PORTFOLIO: { bg: 'rgba(30,58,95,0.1)', color: '#1e3a5f', Icon: ShieldCheck }, VERIFIED_PORTFOLIO: { bg: 'rgba(30,58,95,0.1)', color: '#1e3a5f', Icon: ShieldCheck },
EXTERNAL_MARKET: { bg: 'rgba(217,119,6,0.1)', color: '#b45309', Icon: Globe },
MAISON_WORK: { bg: 'rgba(3,105,161,0.1)', color: '#0369a1', Icon: Building2 }, MAISON_WORK: { bg: 'rgba(3,105,161,0.1)', color: '#0369a1', Icon: Building2 },
FUTURE_AVAILABILITY: { bg: 'rgba(124,58,237,0.1)', color: '#6d28d9', Icon: Sparkles }, FUTURE_AVAILABILITY: { bg: 'rgba(124,58,237,0.1)', color: '#6d28d9', Icon: Sparkles },
} }
-1
View File
@@ -5,7 +5,6 @@ import { useCompareStore } from '../../stores/compareStore'
const TYPE_DOT: Record<string, string> = { const TYPE_DOT: Record<string, string> = {
VERIFIED_PORTFOLIO: '#1e3a5f', VERIFIED_PORTFOLIO: '#1e3a5f',
EXTERNAL_MARKET: '#d97706',
MAISON_WORK: '#0369a1', MAISON_WORK: '#0369a1',
FUTURE_AVAILABILITY: '#7c3aed', FUTURE_AVAILABILITY: '#7c3aed',
} }
@@ -5,7 +5,6 @@ import type { MatchCardViewModel } from './MatchCardViewModel'
const RESULT_TYPE_META: Record<string, { label: string; color: string }> = { const RESULT_TYPE_META: Record<string, { label: string; color: string }> = {
VERIFIED_PORTFOLIO: { label: 'Verified', color: '#1e3a5f' }, VERIFIED_PORTFOLIO: { label: 'Verified', color: '#1e3a5f' },
EXTERNAL_MARKET: { label: 'Direkt', color: '#d97706' },
MAISON_WORK: { label: 'Maison Work', color: '#0369a1' }, MAISON_WORK: { label: 'Maison Work', color: '#0369a1' },
FUTURE_AVAILABILITY: { label: 'Signal', color: '#7c3aed' }, FUTURE_AVAILABILITY: { label: 'Signal', color: '#7c3aed' },
} }
@@ -7,7 +7,6 @@ import type { FutureSignal } from '../../domain/futureSignal'
const RESULT_TYPE_META: Record<string, { label: string; color: string }> = { const RESULT_TYPE_META: Record<string, { label: string; color: string }> = {
VERIFIED_PORTFOLIO: { label: 'Verified Portfolio', color: '#1e3a5f' }, VERIFIED_PORTFOLIO: { label: 'Verified Portfolio', color: '#1e3a5f' },
EXTERNAL_MARKET: { label: 'Direktinserat', color: '#d97706' },
MAISON_WORK: { label: 'Maison Work', color: '#0369a1' }, MAISON_WORK: { label: 'Maison Work', color: '#0369a1' },
FUTURE_AVAILABILITY: { label: 'Zukunftssignal', color: '#7c3aed' }, FUTURE_AVAILABILITY: { label: 'Zukunftssignal', color: '#7c3aed' },
} }
+1 -1
View File
@@ -72,7 +72,7 @@ export function ShortlistDetail({ shortlist }: Props) {
matchId: item.resultId, matchId: item.resultId,
needId: '', needId: '',
matchScore: item.matchScore, matchScore: item.matchScore,
resultType: item.resultType as 'VERIFIED_PORTFOLIO' | 'EXTERNAL_MARKET' | 'MAISON_WORK', resultType: item.resultType as 'VERIFIED_PORTFOLIO' | 'MAISON_WORK',
property: { id: item.propertyId ?? item.resultId, title: item.title } as any, property: { id: item.propertyId ?? item.resultId, title: item.title } as any,
match: { id: item.resultId, matchScore: item.matchScore, confidenceLevel: item.confidenceScore ?? 0.8 } as any, match: { id: item.resultId, matchScore: item.matchScore, confidenceLevel: item.confidenceScore ?? 0.8 } as any,
} }
@@ -11,7 +11,6 @@ import type { ShortlistItem } from '../../domain/shortlist'
const RESULT_TYPE_LABEL: Record<string, string> = { const RESULT_TYPE_LABEL: Record<string, string> = {
VERIFIED_PORTFOLIO: 'Portfolio', VERIFIED_PORTFOLIO: 'Portfolio',
EXTERNAL_MARKET: 'Direkt',
MAISON_WORK: 'Maison Work', MAISON_WORK: 'Maison Work',
FUTURE_AVAILABILITY: 'Signal', FUTURE_AVAILABILITY: 'Signal',
} }
-1
View File
@@ -14,7 +14,6 @@ export type AssetType = typeof AssetType[keyof typeof AssetType]
// ── Result Types ────────────────────────────────────────────────────────────── // ── Result Types ──────────────────────────────────────────────────────────────
export const ResultType = { export const ResultType = {
VERIFIED_PORTFOLIO: 'VERIFIED_PORTFOLIO', VERIFIED_PORTFOLIO: 'VERIFIED_PORTFOLIO',
EXTERNAL_MARKET: 'EXTERNAL_MARKET',
MAISON_WORK: 'MAISON_WORK', MAISON_WORK: 'MAISON_WORK',
FUTURE_AVAILABILITY: 'FUTURE_AVAILABILITY', FUTURE_AVAILABILITY: 'FUTURE_AVAILABILITY',
} as const } as const
+1 -1
View File
@@ -5,7 +5,7 @@ export interface PipelineItem {
title: string title: string
location: string location: string
matchScore: number matchScore: number
resultType: 'VERIFIED_PORTFOLIO' | 'EXTERNAL_MARKET' | 'MAISON_WORK' | 'FUTURE_AVAILABILITY' resultType: 'VERIFIED_PORTFOLIO' | 'MAISON_WORK' | 'FUTURE_AVAILABILITY'
stage: PipelineStage stage: PipelineStage
// Source match reference — used for navigating back to the detail page // Source match reference — used for navigating back to the detail page
matchId?: string matchId?: string
-1
View File
@@ -42,7 +42,6 @@ export const DATA_QUALITY_MODIFIER = {
export const CONFIDENCE_MODIFIER = { export const CONFIDENCE_MODIFIER = {
VERIFIED_HIGH: +3, // VERIFIED_PORTFOLIO + confidenceScore >= 0.80 VERIFIED_HIGH: +3, // VERIFIED_PORTFOLIO + confidenceScore >= 0.80
VERIFIED_MEDIUM: 0, // VERIFIED_PORTFOLIO + confidenceScore < 0.80 VERIFIED_MEDIUM: 0, // VERIFIED_PORTFOLIO + confidenceScore < 0.80
EXTERNAL_MARKET: -3, // EXTERNAL_MARKET result type
MAISON_WORK: -2, // MAISON_WORK — Maison Work API (slightly more trusted than scraped market) MAISON_WORK: -2, // MAISON_WORK — Maison Work API (slightly more trusted than scraped market)
FUTURE_AVAILABILITY: -15, // FUTURE_AVAILABILITY — never treat as confirmed availability FUTURE_AVAILABILITY: -15, // FUTURE_AVAILABILITY — never treat as confirmed availability
LOW_CONFIDENCE: -10, // confidenceScore < 0.50 (stacks with above) LOW_CONFIDENCE: -10, // confidenceScore < 0.50 (stacks with above)
+1 -9
View File
@@ -15,14 +15,7 @@ interface UnifiedResultBase {
} }
export interface VerifiedPortfolioResult extends UnifiedResultBase { export interface VerifiedPortfolioResult extends UnifiedResultBase {
resultType: 'VERIFIED_PORTFOLIO' resultType: 'VERIFIED_PORTFOLIO' | 'MAISON_WORK'
property: Property
match: Match
unit?: PropertyUnit // specific unit this match refers to
}
export interface ExternalMarketResult extends UnifiedResultBase {
resultType: 'EXTERNAL_MARKET' | 'MAISON_WORK'
property: Property property: Property
match: Match match: Match
unit?: PropertyUnit // specific unit this match refers to unit?: PropertyUnit // specific unit this match refers to
@@ -38,5 +31,4 @@ export interface FutureAvailabilityResult extends UnifiedResultBase {
export type UnifiedMatchResult = export type UnifiedMatchResult =
| VerifiedPortfolioResult | VerifiedPortfolioResult
| ExternalMarketResult
| FutureAvailabilityResult | FutureAvailabilityResult
@@ -38,20 +38,17 @@ describe('rankMatches', () => {
expect(ranked[0].propertyId).toBe('high') expect(ranked[0].propertyId).toBe('high')
}) })
it('breaks ties by result type: VERIFIED_PORTFOLIO before EXTERNAL_MARKET', () => { it('breaks ties by result type: VERIFIED_PORTFOLIO and MAISON_WORK ranked above FUTURE_AVAILABILITY', () => {
// Build one of each type but force identical score by using same property body // Build one of each type but force identical score by using same property body
const prop = makeProperty() const prop = makeProperty()
const verified = buildFullMatch(need, { ...prop, id: 'v', resultType: ResultType.VERIFIED_PORTFOLIO }) const verified = buildFullMatch(need, { ...prop, id: 'v', resultType: ResultType.VERIFIED_PORTFOLIO })
const external = buildFullMatch(need, { ...prop, id: 'e', resultType: ResultType.EXTERNAL_MARKET, confidenceScore: 0.85 }) const future = buildFullMatch(need, { ...prop, id: 'f', resultType: ResultType.FUTURE_AVAILABILITY, confidenceScore: 0.85 })
// If scores differ, force them equal for a clean tiebreak test // Force same score for a clean tiebreak test
if (verified.matchScore !== external.matchScore) { verified.matchScore = 75
const lower = Math.min(verified.matchScore, external.matchScore) future.matchScore = 75
verified.matchScore = lower
external.matchScore = lower
}
const ranked = rankMatches([external, verified]) const ranked = rankMatches([future, verified])
expect(ranked[0].resultType).toBe(ResultType.VERIFIED_PORTFOLIO) expect(ranked[0].resultType).toBe(ResultType.VERIFIED_PORTFOLIO)
}) })
@@ -56,11 +56,6 @@ describe('calcConfidenceModifier', () => {
expect(calcConfidenceModifier(p)).toBe(0) expect(calcConfidenceModifier(p)).toBe(0)
}) })
it('returns -3 for external market results', () => {
const p = makeProperty({ resultType: ResultType.EXTERNAL_MARKET, confidenceScore: 0.80 })
expect(calcConfidenceModifier(p)).toBe(-3)
})
it('returns -2 for Maison Work results', () => { it('returns -2 for Maison Work results', () => {
const p = makeProperty({ resultType: ResultType.MAISON_WORK, confidenceScore: 0.80 }) const p = makeProperty({ resultType: ResultType.MAISON_WORK, confidenceScore: 0.80 })
expect(calcConfidenceModifier(p)).toBe(-2) expect(calcConfidenceModifier(p)).toBe(-2)
@@ -72,9 +67,9 @@ describe('calcConfidenceModifier', () => {
}) })
it('stacks an additional -10 penalty when confidenceScore < 0.50', () => { it('stacks an additional -10 penalty when confidenceScore < 0.50', () => {
// EXTERNAL_MARKET (-3) + LOW_CONFIDENCE (-10) = -13 // MAISON_WORK (-2) + LOW_CONFIDENCE (-10) = -12
const p = makeProperty({ resultType: ResultType.EXTERNAL_MARKET, confidenceScore: 0.45 }) const p = makeProperty({ resultType: ResultType.MAISON_WORK, confidenceScore: 0.45 })
expect(calcConfidenceModifier(p)).toBe(-13) expect(calcConfidenceModifier(p)).toBe(-12)
}) })
it('stacks -10 on FUTURE_AVAILABILITY when confidence is also low', () => { it('stacks -10 on FUTURE_AVAILABILITY when confidence is also low', () => {
@@ -157,12 +152,12 @@ describe('calculateScore', () => {
expect(output.finalScore).toBeGreaterThanOrEqual(85) expect(output.finalScore).toBeGreaterThanOrEqual(85)
}) })
it('scores a weak match (wrong city, over budget, poor DQ, external market) below 50', () => { it('scores a weak match (wrong city, over budget, poor DQ, low confidence) below 50', () => {
const need = makeNeed({ preferredLocations: ['Zürich'] }) const need = makeNeed({ preferredLocations: ['Zürich'] })
const prop = makeProperty({ const prop = makeProperty({
location: { city: 'Basel', country: 'CH' }, location: { city: 'Basel', country: 'CH' },
rentPricePerSqm: 70, // 140% of max budget 50 — not excluded but severe penalty rentPricePerSqm: 70, // 140% of max budget 50 — not excluded but severe penalty
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
confidenceScore: 0.45, // triggers LOW_CONFIDENCE -10 stacking confidenceScore: 0.45, // triggers LOW_CONFIDENCE -10 stacking
dataQuality: { dataQuality: {
score: 0.30, // CRITICAL → -15 score: 0.30, // CRITICAL → -15
@@ -132,7 +132,7 @@ describe('softFactorEnrichmentService — score range invariant (all keys, 01
describe('softFactorEnrichmentService — Pre-Market vs Market Signal', () => { describe('softFactorEnrichmentService — Pre-Market vs Market Signal', () => {
it('returns identical estimate for same location regardless of resultType', () => { it('returns identical estimate for same location regardless of resultType', () => {
// The enrichment service is location-only — resultType is irrelevant. // The enrichment service is location-only — resultType is irrelevant.
// FUTURE_AVAILABILITY (pre-market) and EXTERNAL_MARKET should produce the same soft factor score. // FUTURE_AVAILABILITY (pre-market) and VERIFIED_PORTFOLIO should produce the same soft factor score.
const sharedLocation = { city: 'Zürich', district: 'Oerlikon', country: 'CH' } const sharedLocation = { city: 'Zürich', district: 'Oerlikon', country: 'CH' }
const sharedAddress = { street: 'Thurgauerstrasse', houseNumber: '1', postalCode: '8050', city: 'Zürich', country: 'CH' } const sharedAddress = { street: 'Thurgauerstrasse', houseNumber: '1', postalCode: '8050', city: 'Zürich', country: 'CH' }
@@ -141,16 +141,16 @@ describe('softFactorEnrichmentService — Pre-Market vs Market Signal', () => {
address: sharedAddress, address: sharedAddress,
resultType: ResultType.FUTURE_AVAILABILITY, resultType: ResultType.FUTURE_AVAILABILITY,
}) })
const marketResult = makeProperty({ const portfolioResult = makeProperty({
location: sharedLocation, location: sharedLocation,
address: sharedAddress, address: sharedAddress,
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
}) })
const futureEst = softFactorEnrichmentService.estimate('accessibility', futureSignal) const futureEst = softFactorEnrichmentService.estimate('accessibility', futureSignal)
const marketEst = softFactorEnrichmentService.estimate('accessibility', marketResult) const portfolioEst = softFactorEnrichmentService.estimate('accessibility', portfolioResult)
expect(futureEst?.score).toBe(marketEst?.score) expect(futureEst?.score).toBe(portfolioEst?.score)
expect(futureEst?.label).toBe(marketEst?.label) expect(futureEst?.label).toBe(portfolioEst?.label)
}) })
it('FUTURE_AVAILABILITY at Oerlikon gets meaningful accessibility score (> 0.70)', () => { it('FUTURE_AVAILABILITY at Oerlikon gets meaningful accessibility score (> 0.70)', () => {
+4 -4
View File
@@ -191,10 +191,10 @@ export function rankMatches(matches: Match[]): Match[] {
return [...matches].sort((a, b) => { return [...matches].sort((a, b) => {
// Primary: matchScore descending // Primary: matchScore descending
if (b.matchScore !== a.matchScore) return b.matchScore - a.matchScore if (b.matchScore !== a.matchScore) return b.matchScore - a.matchScore
// Secondary: VERIFIED > EXTERNAL / MAISON_WORK > FUTURE // Secondary: VERIFIED / MAISON_WORK > FUTURE
const typeOrder: Record<string, number> = { VERIFIED_PORTFOLIO: 0, EXTERNAL_MARKET: 1, MAISON_WORK: 1, FUTURE_AVAILABILITY: 2 } const typeOrder: Record<string, number> = { VERIFIED_PORTFOLIO: 0, MAISON_WORK: 0, FUTURE_AVAILABILITY: 2 }
const aOrder = typeOrder[a.resultType ?? 'EXTERNAL_MARKET'] ?? 1 const aOrder = typeOrder[a.resultType ?? 'VERIFIED_PORTFOLIO'] ?? 0
const bOrder = typeOrder[b.resultType ?? 'EXTERNAL_MARKET'] ?? 1 const bOrder = typeOrder[b.resultType ?? 'VERIFIED_PORTFOLIO'] ?? 0
if (aOrder !== bOrder) return aOrder - bOrder if (aOrder !== bOrder) return aOrder - bOrder
// Tertiary: higher confidence first // Tertiary: higher confidence first
return (b.confidenceLevel ?? 0) - (a.confidenceLevel ?? 0) return (b.confidenceLevel ?? 0) - (a.confidenceLevel ?? 0)
-2
View File
@@ -499,8 +499,6 @@ export function calcConfidenceModifier(property: Property): number {
let mod = 0 let mod = 0
if (property.resultType === ResultType.FUTURE_AVAILABILITY) { if (property.resultType === ResultType.FUTURE_AVAILABILITY) {
mod += CONFIDENCE_MODIFIER.FUTURE_AVAILABILITY mod += CONFIDENCE_MODIFIER.FUTURE_AVAILABILITY
} else if (property.resultType === ResultType.EXTERNAL_MARKET) {
mod += CONFIDENCE_MODIFIER.EXTERNAL_MARKET
} else if (property.resultType === ResultType.MAISON_WORK) { } else if (property.resultType === ResultType.MAISON_WORK) {
mod += CONFIDENCE_MODIFIER.MAISON_WORK mod += CONFIDENCE_MODIFIER.MAISON_WORK
} else { } else {
+1 -15
View File
@@ -6,7 +6,6 @@ import { useSchattenmarktSignals } from './useSchattenmarktSignals'
import type { import type {
UnifiedMatchResult, UnifiedMatchResult,
VerifiedPortfolioResult, VerifiedPortfolioResult,
ExternalMarketResult,
FutureAvailabilityResult, FutureAvailabilityResult,
} from '../domain/unifiedResult' } from '../domain/unifiedResult'
@@ -64,24 +63,11 @@ export function useUnifiedResults(needId?: string) {
? (property.units?.find(u => u.id === match.unitId) ?? undefined) ? (property.units?.find(u => u.id === match.unitId) ?? undefined)
: undefined : undefined
if (rt === 'EXTERNAL_MARKET' || rt === 'MAISON_WORK') {
const result: ExternalMarketResult = {
matchId: match.id,
needId: match.needId,
matchScore: match.matchScore,
resultType: rt as 'EXTERNAL_MARKET' | 'MAISON_WORK',
property,
match,
unit: matchUnit,
}
return [result]
}
const result: VerifiedPortfolioResult = { const result: VerifiedPortfolioResult = {
matchId: match.id, matchId: match.id,
needId: match.needId, needId: match.needId,
matchScore: match.matchScore, matchScore: match.matchScore,
resultType: 'VERIFIED_PORTFOLIO', resultType: rt as 'VERIFIED_PORTFOLIO' | 'MAISON_WORK',
property, property,
match, match,
unit: matchUnit, unit: matchUnit,
-1
View File
@@ -69,7 +69,6 @@ export const ASSET_TYPE_LABELS: Record<string, string> = {
// Result type display labels // Result type display labels
export const RESULT_TYPE_LABELS: Record<string, string> = { export const RESULT_TYPE_LABELS: Record<string, string> = {
VERIFIED_PORTFOLIO: 'Plattform', VERIFIED_PORTFOLIO: 'Plattform',
EXTERNAL_MARKET: 'Plattform',
MAISON_WORK: 'Maison Work', MAISON_WORK: 'Maison Work',
FUTURE_AVAILABILITY: 'Zukunftssignal', FUTURE_AVAILABILITY: 'Zukunftssignal',
} }
-2
View File
@@ -7,7 +7,6 @@ import { CONF_HIGH, CONF_MEDIUM, DQ_HIGH, DQ_MEDIUM } from './constants'
export const DS_COLORS = { export const DS_COLORS = {
resultType: { resultType: {
VERIFIED_PORTFOLIO: { bg: 'rgba(30,58,95,0.10)', fg: '#1e3a5f' }, VERIFIED_PORTFOLIO: { bg: 'rgba(30,58,95,0.10)', fg: '#1e3a5f' },
EXTERNAL_MARKET: { bg: 'rgba(30,58,95,0.10)', fg: '#1e3a5f' },
MAISON_WORK: { bg: 'rgba(3,105,161,0.10)', fg: '#0369a1' }, MAISON_WORK: { bg: 'rgba(3,105,161,0.10)', fg: '#0369a1' },
FUTURE_AVAILABILITY: { bg: 'rgba(109,40,217,0.10)', fg: '#6d28d9' }, FUTURE_AVAILABILITY: { bg: 'rgba(109,40,217,0.10)', fg: '#6d28d9' },
}, },
@@ -199,7 +198,6 @@ export function scoreToDataQualityLevel(score: number): DataQualityLevel {
export const RESULT_TYPE_META: Record<string, { label: string; color: string; bg: string }> = { export const RESULT_TYPE_META: Record<string, { label: string; color: string; bg: string }> = {
VERIFIED_PORTFOLIO: { label: 'Verifiziertes Objekt', color: '#1e3a5f', bg: 'rgba(30,58,95,0.10)' }, VERIFIED_PORTFOLIO: { label: 'Verifiziertes Objekt', color: '#1e3a5f', bg: 'rgba(30,58,95,0.10)' },
EXTERNAL_MARKET: { label: 'Verifiziertes Objekt', color: '#1e3a5f', bg: 'rgba(30,58,95,0.10)' },
MAISON_WORK: { label: 'Maison Work', color: '#0369a1', bg: 'rgba(3,105,161,0.10)' }, MAISON_WORK: { label: 'Maison Work', color: '#0369a1', bg: 'rgba(3,105,161,0.10)' },
FUTURE_AVAILABILITY: { label: 'Zukunftssignal', color: '#7c3aed', bg: 'rgba(109,40,217,0.10)' }, FUTURE_AVAILABILITY: { label: 'Zukunftssignal', color: '#7c3aed', bg: 'rgba(109,40,217,0.10)' },
} }
-1
View File
@@ -99,7 +99,6 @@ export function canViewProperty(
if (property.resultType === ResultType.VERIFIED_PORTFOLIO) { if (property.resultType === ResultType.VERIFIED_PORTFOLIO) {
return property.organizationId === user.organizationId return property.organizationId === user.organizationId
} }
if (property.resultType === ResultType.EXTERNAL_MARKET) return true
if (property.resultType === ResultType.MAISON_WORK) return true if (property.resultType === ResultType.MAISON_WORK) return true
if (property.resultType === ResultType.FUTURE_AVAILABILITY) { if (property.resultType === ResultType.FUTURE_AVAILABILITY) {
return hasPermission(user, Permission.FUTURE_SIGNAL_VIEW) return hasPermission(user, Permission.FUTURE_SIGNAL_VIEW)
+1 -1
View File
@@ -121,7 +121,7 @@ export const mockPipelineItems: PipelineItem[] = [
title: 'Gewerbe Güterstrasse Basel', title: 'Gewerbe Güterstrasse Basel',
location: 'Basel', location: 'Basel',
matchScore: 68, matchScore: 68,
resultType: 'EXTERNAL_MARKET', resultType: 'VERIFIED_PORTFOLIO',
stage: 'CLOSED_LOST', stage: 'CLOSED_LOST',
areaLabel: '800 m²', areaLabel: '800 m²',
rentLabel: 'CHF 28/m²', rentLabel: 'CHF 28/m²',
+23 -23
View File
@@ -1071,14 +1071,14 @@ export const mockProperties: Property[] = [
}, },
// ───────────────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────────────
// EXTERNAL_MARKET (10) // VERIFIED_PORTFOLIO — formerly external market (migrated)
// ───────────────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────────────
{ {
id: 'prop-003', id: 'prop-003',
title: 'Retail-Fläche Bahnhofstrasse 88', title: 'Retail-Fläche Bahnhofstrasse 88',
assetType: AssetType.RETAIL, assetType: AssetType.RETAIL,
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
location: { city: 'Bern', district: 'Innenstadt', canton: 'BE', country: 'CH', coordinates: { lat: 46.9483, lng: 7.4474 } }, location: { city: 'Bern', district: 'Innenstadt', canton: 'BE', country: 'CH', coordinates: { lat: 46.9483, lng: 7.4474 } },
address: { street: 'Bahnhofstrasse', houseNumber: '88', postalCode: '3011', city: 'Bern', country: 'CH' }, address: { street: 'Bahnhofstrasse', houseNumber: '88', postalCode: '3011', city: 'Bern', country: 'CH' },
areaSqm: 320, areaSqm: 320,
@@ -1122,7 +1122,7 @@ export const mockProperties: Property[] = [
id: 'prop-004', id: 'prop-004',
title: 'Gemischte Gewerbeeinheit Europaallee', title: 'Gemischte Gewerbeeinheit Europaallee',
assetType: AssetType.MIXED, assetType: AssetType.MIXED,
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
location: { city: 'Zürich', district: 'Kreis 4', canton: 'ZH', country: 'CH', coordinates: { lat: 47.3775, lng: 8.5398 } }, location: { city: 'Zürich', district: 'Kreis 4', canton: 'ZH', country: 'CH', coordinates: { lat: 47.3775, lng: 8.5398 } },
address: { street: 'Europaallee', houseNumber: '21', postalCode: '8004', city: 'Zürich', country: 'CH' }, address: { street: 'Europaallee', houseNumber: '21', postalCode: '8004', city: 'Zürich', country: 'CH' },
areaSqm: 1150, areaSqm: 1150,
@@ -1246,7 +1246,7 @@ export const mockProperties: Property[] = [
id: 'prop-017', id: 'prop-017',
title: 'Ladenfläche Löwenstrasse 28', title: 'Ladenfläche Löwenstrasse 28',
assetType: AssetType.RETAIL, assetType: AssetType.RETAIL,
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
location: { city: 'Zürich', district: 'Innenstadt', canton: 'ZH', country: 'CH', coordinates: { lat: 47.3766, lng: 8.5385 } }, location: { city: 'Zürich', district: 'Innenstadt', canton: 'ZH', country: 'CH', coordinates: { lat: 47.3766, lng: 8.5385 } },
address: { street: 'Löwenstrasse', houseNumber: '28', postalCode: '8001', city: 'Zürich', country: 'CH' }, address: { street: 'Löwenstrasse', houseNumber: '28', postalCode: '8001', city: 'Zürich', country: 'CH' },
areaSqm: 350, areaSqm: 350,
@@ -1290,7 +1290,7 @@ export const mockProperties: Property[] = [
id: 'prop-018', id: 'prop-018',
title: 'Bürofläche Breitenrain 14', title: 'Bürofläche Breitenrain 14',
assetType: AssetType.OFFICE, assetType: AssetType.OFFICE,
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
location: { city: 'Bern', district: 'Breitenrain', canton: 'BE', country: 'CH', coordinates: { lat: 46.9598, lng: 7.4522 } }, location: { city: 'Bern', district: 'Breitenrain', canton: 'BE', country: 'CH', coordinates: { lat: 46.9598, lng: 7.4522 } },
address: { street: 'Breitenrainstrasse', houseNumber: '14', postalCode: '3014', city: 'Bern', country: 'CH' }, address: { street: 'Breitenrainstrasse', houseNumber: '14', postalCode: '3014', city: 'Bern', country: 'CH' },
areaSqm: 780, areaSqm: 780,
@@ -1458,7 +1458,7 @@ export const mockProperties: Property[] = [
id: 'prop-022', id: 'prop-022',
title: 'Bürofläche St.Gallen Centrum 7', title: 'Bürofläche St.Gallen Centrum 7',
assetType: AssetType.OFFICE, assetType: AssetType.OFFICE,
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
location: { city: 'St. Gallen', district: 'Centrum', canton: 'SG', country: 'CH', coordinates: { lat: 47.4245, lng: 9.3767 } }, location: { city: 'St. Gallen', district: 'Centrum', canton: 'SG', country: 'CH', coordinates: { lat: 47.4245, lng: 9.3767 } },
address: { street: 'Marktgasse', houseNumber: '7', postalCode: '9000', city: 'St. Gallen', country: 'CH' }, address: { street: 'Marktgasse', houseNumber: '7', postalCode: '9000', city: 'St. Gallen', country: 'CH' },
areaSqm: 700, areaSqm: 700,
@@ -1666,7 +1666,7 @@ export const mockProperties: Property[] = [
id: 'prop-031', id: 'prop-031',
title: 'Bürofläche Hardturm West 16', title: 'Bürofläche Hardturm West 16',
assetType: AssetType.OFFICE, assetType: AssetType.OFFICE,
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
location: { city: 'Zürich', district: 'Zürich-West', canton: 'ZH', country: 'CH', coordinates: { lat: 47.3862, lng: 8.5045 } }, location: { city: 'Zürich', district: 'Zürich-West', canton: 'ZH', country: 'CH', coordinates: { lat: 47.3862, lng: 8.5045 } },
address: { street: 'Hardturmstrasse', houseNumber: '16', postalCode: '8005', city: 'Zürich', country: 'CH' }, address: { street: 'Hardturmstrasse', houseNumber: '16', postalCode: '8005', city: 'Zürich', country: 'CH' },
areaSqm: 780, areaSqm: 780,
@@ -1780,7 +1780,7 @@ export const mockProperties: Property[] = [
id: 'prop-034', id: 'prop-034',
title: 'Ladenfläche Lorrainestrasse 8', title: 'Ladenfläche Lorrainestrasse 8',
assetType: AssetType.RETAIL, assetType: AssetType.RETAIL,
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
location: { city: 'Bern', district: 'Lorraine', canton: 'BE', country: 'CH', coordinates: { lat: 46.9565, lng: 7.4388 } }, location: { city: 'Bern', district: 'Lorraine', canton: 'BE', country: 'CH', coordinates: { lat: 46.9565, lng: 7.4388 } },
address: { street: 'Lorrainestrasse', houseNumber: '8', postalCode: '3013', city: 'Bern', country: 'CH' }, address: { street: 'Lorrainestrasse', houseNumber: '8', postalCode: '3013', city: 'Bern', country: 'CH' },
areaSqm: 340, areaSqm: 340,
@@ -1844,7 +1844,7 @@ export const mockProperties: Property[] = [
id: 'prop-036', id: 'prop-036',
title: 'Lagerhalle Klybeckstrasse 280', title: 'Lagerhalle Klybeckstrasse 280',
assetType: AssetType.LOGISTICS, assetType: AssetType.LOGISTICS,
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
location: { city: 'Basel', district: 'Kleinhüningen', canton: 'BS', country: 'CH', coordinates: { lat: 47.5744, lng: 7.5862 } }, location: { city: 'Basel', district: 'Kleinhüningen', canton: 'BS', country: 'CH', coordinates: { lat: 47.5744, lng: 7.5862 } },
address: { street: 'Klybeckstrasse', houseNumber: '280', postalCode: '4057', city: 'Basel', country: 'CH' }, address: { street: 'Klybeckstrasse', houseNumber: '280', postalCode: '4057', city: 'Basel', country: 'CH' },
areaSqm: 2600, areaSqm: 2600,
@@ -2206,7 +2206,7 @@ export const mockProperties: Property[] = [
id: 'prop-055', id: 'prop-055',
title: 'Ladenfläche Weststrasse 44', title: 'Ladenfläche Weststrasse 44',
assetType: AssetType.RETAIL, assetType: AssetType.RETAIL,
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
location: { city: 'Zürich', district: 'Kreis 3', canton: 'ZH', country: 'CH', coordinates: { lat: 47.372, lng: 8.521 } }, location: { city: 'Zürich', district: 'Kreis 3', canton: 'ZH', country: 'CH', coordinates: { lat: 47.372, lng: 8.521 } },
address: { street: 'Weststrasse', houseNumber: '44', postalCode: '8003', city: 'Zürich', country: 'CH' }, address: { street: 'Weststrasse', houseNumber: '44', postalCode: '8003', city: 'Zürich', country: 'CH' },
areaSqm: 150, areaSqm: 150,
@@ -2254,7 +2254,7 @@ export const mockProperties: Property[] = [
id: 'prop-056', id: 'prop-056',
title: 'Gewerbefläche Hohlstrasse 88', title: 'Gewerbefläche Hohlstrasse 88',
assetType: AssetType.RETAIL, assetType: AssetType.RETAIL,
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
location: { city: 'Zürich', district: 'Kreis 4', canton: 'ZH', country: 'CH', coordinates: { lat: 47.375, lng: 8.527 } }, location: { city: 'Zürich', district: 'Kreis 4', canton: 'ZH', country: 'CH', coordinates: { lat: 47.375, lng: 8.527 } },
address: { street: 'Hohlstrasse', houseNumber: '88', postalCode: '8004', city: 'Zürich', country: 'CH' }, address: { street: 'Hohlstrasse', houseNumber: '88', postalCode: '8004', city: 'Zürich', country: 'CH' },
areaSqm: 155, areaSqm: 155,
@@ -2667,7 +2667,7 @@ export const mockProperties: Property[] = [
id: 'prop-064', id: 'prop-064',
title: 'Bürofläche Förrlibuckstrasse 22', title: 'Bürofläche Förrlibuckstrasse 22',
assetType: AssetType.OFFICE, assetType: AssetType.OFFICE,
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
location: { city: 'Zürich', district: 'Zürich-West', canton: 'ZH', country: 'CH', coordinates: { lat: 47.388, lng: 8.510 } }, location: { city: 'Zürich', district: 'Zürich-West', canton: 'ZH', country: 'CH', coordinates: { lat: 47.388, lng: 8.510 } },
address: { street: 'Förrlibuckstrasse', houseNumber: '22', postalCode: '8005', city: 'Zürich', country: 'CH' }, address: { street: 'Förrlibuckstrasse', houseNumber: '22', postalCode: '8005', city: 'Zürich', country: 'CH' },
areaSqm: 185, areaSqm: 185,
@@ -2714,7 +2714,7 @@ export const mockProperties: Property[] = [
id: 'prop-065', id: 'prop-065',
title: 'Bürofläche Binzmühlestrasse 95, Oerlikon', title: 'Bürofläche Binzmühlestrasse 95, Oerlikon',
assetType: AssetType.OFFICE, assetType: AssetType.OFFICE,
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
location: { city: 'Zürich', district: 'Oerlikon', canton: 'ZH', country: 'CH', coordinates: { lat: 47.411, lng: 8.544 } }, location: { city: 'Zürich', district: 'Oerlikon', canton: 'ZH', country: 'CH', coordinates: { lat: 47.411, lng: 8.544 } },
address: { street: 'Binzmühlestrasse', houseNumber: '95', postalCode: '8050', city: 'Zürich', country: 'CH' }, address: { street: 'Binzmühlestrasse', houseNumber: '95', postalCode: '8050', city: 'Zürich', country: 'CH' },
areaSqm: 175, areaSqm: 175,
@@ -2813,7 +2813,7 @@ export const mockProperties: Property[] = [
id: 'prop-067', id: 'prop-067',
title: 'Bürofläche Altstetterstrasse 222', title: 'Bürofläche Altstetterstrasse 222',
assetType: AssetType.OFFICE, assetType: AssetType.OFFICE,
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
location: { city: 'Zürich', district: 'Altstetten', canton: 'ZH', country: 'CH', coordinates: { lat: 47.385, lng: 8.488 } }, location: { city: 'Zürich', district: 'Altstetten', canton: 'ZH', country: 'CH', coordinates: { lat: 47.385, lng: 8.488 } },
address: { street: 'Altstetterstrasse', houseNumber: '222', postalCode: '8048', city: 'Zürich', country: 'CH' }, address: { street: 'Altstetterstrasse', houseNumber: '222', postalCode: '8048', city: 'Zürich', country: 'CH' },
areaSqm: 190, areaSqm: 190,
@@ -3175,7 +3175,7 @@ export const mockProperties: Property[] = [
id: 'prop-074', id: 'prop-074',
title: 'Bürofläche Uraniastrasse 14', title: 'Bürofläche Uraniastrasse 14',
assetType: AssetType.OFFICE, assetType: AssetType.OFFICE,
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
location: { city: 'Zürich', district: 'Kreis 1', canton: 'ZH', country: 'CH', coordinates: { lat: 47.376, lng: 8.541 } }, location: { city: 'Zürich', district: 'Kreis 1', canton: 'ZH', country: 'CH', coordinates: { lat: 47.376, lng: 8.541 } },
address: { street: 'Uraniastrasse', houseNumber: '14', postalCode: '8001', city: 'Zürich', country: 'CH' }, address: { street: 'Uraniastrasse', houseNumber: '14', postalCode: '8001', city: 'Zürich', country: 'CH' },
areaSqm: 510, areaSqm: 510,
@@ -3223,7 +3223,7 @@ export const mockProperties: Property[] = [
id: 'prop-075', id: 'prop-075',
title: 'Bürofläche Seefeldstrasse 30', title: 'Bürofläche Seefeldstrasse 30',
assetType: AssetType.OFFICE, assetType: AssetType.OFFICE,
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
location: { city: 'Zürich', district: 'Seefeld', canton: 'ZH', country: 'CH', coordinates: { lat: 47.356, lng: 8.550 } }, location: { city: 'Zürich', district: 'Seefeld', canton: 'ZH', country: 'CH', coordinates: { lat: 47.356, lng: 8.550 } },
address: { street: 'Seefeldstrasse', houseNumber: '30', postalCode: '8008', city: 'Zürich', country: 'CH' }, address: { street: 'Seefeldstrasse', houseNumber: '30', postalCode: '8008', city: 'Zürich', country: 'CH' },
areaSqm: 540, areaSqm: 540,
@@ -3483,7 +3483,7 @@ export const mockProperties: Property[] = [
id: 'prop-080', id: 'prop-080',
title: 'Ladenfläche Spitalgasse 34', title: 'Ladenfläche Spitalgasse 34',
assetType: AssetType.RETAIL, assetType: AssetType.RETAIL,
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
location: { city: 'Bern', district: 'Innenstadt', canton: 'BE', country: 'CH', coordinates: { lat: 46.948, lng: 7.447 } }, location: { city: 'Bern', district: 'Innenstadt', canton: 'BE', country: 'CH', coordinates: { lat: 46.948, lng: 7.447 } },
address: { street: 'Spitalgasse', houseNumber: '34', postalCode: '3011', city: 'Bern', country: 'CH' }, address: { street: 'Spitalgasse', houseNumber: '34', postalCode: '3011', city: 'Bern', country: 'CH' },
areaSqm: 280, areaSqm: 280,
@@ -3531,7 +3531,7 @@ export const mockProperties: Property[] = [
id: 'prop-081', id: 'prop-081',
title: 'Ladenfläche Münstergasse 12', title: 'Ladenfläche Münstergasse 12',
assetType: AssetType.RETAIL, assetType: AssetType.RETAIL,
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
location: { city: 'Bern', district: 'Innenstadt', canton: 'BE', country: 'CH', coordinates: { lat: 46.948, lng: 7.447 } }, location: { city: 'Bern', district: 'Innenstadt', canton: 'BE', country: 'CH', coordinates: { lat: 46.948, lng: 7.447 } },
address: { street: 'Münstergasse', houseNumber: '12', postalCode: '3011', city: 'Bern', country: 'CH' }, address: { street: 'Münstergasse', houseNumber: '12', postalCode: '3011', city: 'Bern', country: 'CH' },
areaSqm: 350, areaSqm: 350,
@@ -3838,7 +3838,7 @@ export const mockProperties: Property[] = [
id: 'prop-087', id: 'prop-087',
title: 'Lagerhalle Hauptstrasse 180, Pratteln', title: 'Lagerhalle Hauptstrasse 180, Pratteln',
assetType: AssetType.LOGISTICS, assetType: AssetType.LOGISTICS,
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
location: { city: 'Pratteln', district: 'Industriezone', canton: 'BL', country: 'CH', coordinates: { lat: 47.519, lng: 7.689 } }, location: { city: 'Pratteln', district: 'Industriezone', canton: 'BL', country: 'CH', coordinates: { lat: 47.519, lng: 7.689 } },
address: { street: 'Hauptstrasse', houseNumber: '180', postalCode: '4133', city: 'Pratteln', country: 'CH' }, address: { street: 'Hauptstrasse', houseNumber: '180', postalCode: '4133', city: 'Pratteln', country: 'CH' },
areaSqm: 3000, areaSqm: 3000,
@@ -3885,7 +3885,7 @@ export const mockProperties: Property[] = [
id: 'prop-088', id: 'prop-088',
title: 'Lagerhalle Westquaistrasse 12', title: 'Lagerhalle Westquaistrasse 12',
assetType: AssetType.LOGISTICS, assetType: AssetType.LOGISTICS,
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
location: { city: 'Basel', district: 'Kleinhüningen', canton: 'BS', country: 'CH', coordinates: { lat: 47.574, lng: 7.591 } }, location: { city: 'Basel', district: 'Kleinhüningen', canton: 'BS', country: 'CH', coordinates: { lat: 47.574, lng: 7.591 } },
address: { street: 'Westquaistrasse', houseNumber: '12', postalCode: '4057', city: 'Basel', country: 'CH' }, address: { street: 'Westquaistrasse', houseNumber: '12', postalCode: '4057', city: 'Basel', country: 'CH' },
areaSqm: 2600, areaSqm: 2600,
@@ -4091,7 +4091,7 @@ export const mockProperties: Property[] = [
id: 'prop-092', id: 'prop-092',
title: 'Bürofläche Hohlstrasse 534, Altstetten', title: 'Bürofläche Hohlstrasse 534, Altstetten',
assetType: AssetType.OFFICE, assetType: AssetType.OFFICE,
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
location: { city: 'Zürich', district: 'Altstetten', canton: 'ZH', country: 'CH', coordinates: { lat: 47.385, lng: 8.488 } }, location: { city: 'Zürich', district: 'Altstetten', canton: 'ZH', country: 'CH', coordinates: { lat: 47.385, lng: 8.488 } },
address: { street: 'Hohlstrasse', houseNumber: '534', postalCode: '8048', city: 'Zürich', country: 'CH' }, address: { street: 'Hohlstrasse', houseNumber: '534', postalCode: '8048', city: 'Zürich', country: 'CH' },
areaSqm: 900, areaSqm: 900,
@@ -4138,7 +4138,7 @@ export const mockProperties: Property[] = [
id: 'prop-093', id: 'prop-093',
title: 'Bürofläche Technopark Zürich-West', title: 'Bürofläche Technopark Zürich-West',
assetType: AssetType.OFFICE, assetType: AssetType.OFFICE,
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
location: { city: 'Zürich', district: 'Zürich-West', canton: 'ZH', country: 'CH', coordinates: { lat: 47.388, lng: 8.510 } }, location: { city: 'Zürich', district: 'Zürich-West', canton: 'ZH', country: 'CH', coordinates: { lat: 47.388, lng: 8.510 } },
address: { street: 'Technoparkstrasse', houseNumber: '2', postalCode: '8005', city: 'Zürich', country: 'CH' }, address: { street: 'Technoparkstrasse', houseNumber: '2', postalCode: '8005', city: 'Zürich', country: 'CH' },
areaSqm: 960, areaSqm: 960,
@@ -4343,7 +4343,7 @@ export const mockProperties: Property[] = [
id: 'prop-097', id: 'prop-097',
title: 'Bürofläche Baarerstrasse 18, Zug', title: 'Bürofläche Baarerstrasse 18, Zug',
assetType: AssetType.OFFICE, assetType: AssetType.OFFICE,
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
location: { city: 'Zug', district: 'Innenstadt', canton: 'ZG', country: 'CH', coordinates: { lat: 47.174, lng: 8.514 } }, location: { city: 'Zug', district: 'Innenstadt', canton: 'ZG', country: 'CH', coordinates: { lat: 47.174, lng: 8.514 } },
address: { street: 'Baarerstrasse', houseNumber: '18', postalCode: '6300', city: 'Zug', country: 'CH' }, address: { street: 'Baarerstrasse', houseNumber: '18', postalCode: '6300', city: 'Zug', country: 'CH' },
areaSqm: 320, areaSqm: 320,
+1 -1
View File
@@ -88,7 +88,7 @@ export default function MatchDetail() {
const handleCompare = () => { const handleCompare = () => {
if (match && !isFuture && property) { if (match && !isFuture && property) {
addToCompare({ addToCompare({
resultType: property.resultType === 'EXTERNAL_MARKET' ? 'EXTERNAL_MARKET' : 'VERIFIED_PORTFOLIO', resultType: property.resultType ?? 'VERIFIED_PORTFOLIO',
matchId: match.id, needId: match.needId, matchScore: match.matchScore, match, property, matchId: match.id, needId: match.needId, matchScore: match.matchScore, match, property,
}) })
} else if (match && isFuture && signal) { } else if (match && isFuture && signal) {
+1 -2
View File
@@ -73,7 +73,7 @@ export default function Results() {
const { platformCount, maisonWorkCount, futureCount, missingDataCount } = useMemo(() => { const { platformCount, maisonWorkCount, futureCount, missingDataCount } = useMemo(() => {
let platform = 0, maison = 0, future = 0, missing = 0 let platform = 0, maison = 0, future = 0, missing = 0
for (const r of results) { for (const r of results) {
if (r.resultType === 'VERIFIED_PORTFOLIO' || r.resultType === 'EXTERNAL_MARKET') platform++ if (r.resultType === 'VERIFIED_PORTFOLIO') platform++
else if (r.resultType === 'MAISON_WORK') maison++ else if (r.resultType === 'MAISON_WORK') maison++
else if (r.resultType === 'FUTURE_AVAILABILITY') future++ else if (r.resultType === 'FUTURE_AVAILABILITY') future++
if ('match' in r && Array.isArray((r as { match?: { missingData?: unknown[] } }).match?.missingData) && if ('match' in r && Array.isArray((r as { match?: { missingData?: unknown[] } }).match?.missingData) &&
@@ -91,7 +91,6 @@ export default function Results() {
return filterSource === 'ALL' || filterSource === 'PLATFORM' return filterSource === 'ALL' || filterSource === 'PLATFORM'
} }
if (filterSource === 'ALL') return true if (filterSource === 'ALL') return true
if (filterSource === 'PLATFORM') return r.resultType === 'EXTERNAL_MARKET'
return r.resultType === filterSource return r.resultType === filterSource
}) })
return sortResults(filtered, sortBy) return sortResults(filtered, sortBy)
+1 -1
View File
@@ -47,7 +47,7 @@ export function buildCreatePropertyInput(fields: {
return { return {
title: `${ASSET_TYPE_LABELS[assetType] ?? assetType} · ${city}`, title: `${ASSET_TYPE_LABELS[assetType] ?? assetType} · ${city}`,
assetType: assetType as typeof AssetType[keyof typeof AssetType], assetType: assetType as typeof AssetType[keyof typeof AssetType],
resultType: ResultType.EXTERNAL_MARKET, resultType: ResultType.VERIFIED_PORTFOLIO,
sourceType: 'DIRECT', sourceType: 'DIRECT',
location: { city, country: 'CH' }, location: { city, country: 'CH' },
address: { address: {
+1 -1
View File
@@ -1,7 +1,7 @@
export interface DashboardStats { export interface DashboardStats {
totalProperties: number totalProperties: number
verifiedProperties: number verifiedProperties: number
externalMarketProperties: number verifiedPortfolioProperties: number
futureSignalProperties: number futureSignalProperties: number
totalMatches: number totalMatches: number
pendingReviews: number pendingReviews: number
+1 -1
View File
@@ -32,7 +32,7 @@ export const MockupDashboardProvider: IDashboardProvider = {
const stats: DashboardStats = { const stats: DashboardStats = {
totalProperties: props.length, totalProperties: props.length,
verifiedProperties: props.filter(p => p.resultType === 'VERIFIED_PORTFOLIO').length, verifiedProperties: props.filter(p => p.resultType === 'VERIFIED_PORTFOLIO').length,
externalMarketProperties: props.filter(p => p.resultType === 'EXTERNAL_MARKET').length, verifiedPortfolioProperties: props.filter(p => p.resultType === 'VERIFIED_PORTFOLIO').length,
futureSignalProperties: props.filter(p => p.resultType === 'FUTURE_AVAILABILITY').length, futureSignalProperties: props.filter(p => p.resultType === 'FUTURE_AVAILABILITY').length,
totalMatches: matches.length, totalMatches: matches.length,
pendingReviews: queue.filter(r => r.status === 'PENDING').length, pendingReviews: queue.filter(r => r.status === 'PENDING').length,