fix: resolve all TypeScript errors and refactor oversized components

- Fix MUI v9 API: PaperProps/InputLabelProps/inputProps → slotProps in 6 components
- Add ExternalMarketResult alias, PropertyUnit import, OPERATIONS workspace config
- Fix TradeOff.description → .concern, ScoreFactor.label → .criterion
- Make schattenmarktRelease.leadTimeMonths optional, fix mock-data enum values
- Fix useMatchDetailData query typing, weightingService missing WeightProfile keys
- Split Pipeline/Compare/MatchDetail/IntelligenceMatchCard into sub-components
- Fix all test fixtures (CreateNeedInput, CreatePropertyInput, TradeOffInput, etc.)
- Add vercel.json for deployment, zero tsc errors

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Sutter
2026-05-26 00:08:35 +02:00
parent 98d2770054
commit 36570c5bdc
52 changed files with 269 additions and 143 deletions
+3
View File
@@ -61,6 +61,9 @@ describe('useCreateNeed', () => {
preferredLocations: ['Zürich'],
budgetRange: { maxPerSqm: 400, maxMonthlyTotal: 10000, currency: 'CHF' },
organizationId: 'org-test',
timing: { earliestMoveIn: '2025-01-01', latestMoveIn: '2026-01-01', flexibleTiming: true },
weightingProfile: { area: 0.3, location: 0.3, budget: 0.2, timing: 0.1, prestige: 0, accessibility: 0, expansionPotential: 0, flexibility: 0, visibility: 0, footfall: 0, talentAccess: 0, esg: 0, taxEnvironment: 0 },
confidenceInCriteria: 0.8,
})
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(result.current.data?.data.companyName).toBe('Hook Test GmbH')
@@ -71,9 +71,14 @@ describe('useCreateProperty', () => {
assetType: 'LOGISTICS',
resultType: 'VERIFIED_PORTFOLIO',
location: { city: 'Bern', country: 'CH' },
address: { street: 'Teststrasse', houseNumber: '1', postalCode: '3000', city: 'Bern', country: 'CH' },
areaSqm: 300,
rentPricePerSqm: 100,
availabilityDate: '2025-01-01',
availabilityStatus: 'AVAILABLE_NOW',
sourceType: 'DIRECT',
confidenceScore: 0.8,
dataQuality: { score: 0.8, missingCriticalFields: [], missingOptionalFields: [], freshness: 'FRESH', warnings: [] },
organizationId: 'org-test',
})
await waitFor(() => expect(result.current.isSuccess).toBe(true))
+3 -2
View File
@@ -3,6 +3,7 @@ import { useMatchDetail } from './useMatches'
import { propertyService } from '../services/propertyService'
import { needService } from '../services/needService'
import { futureSignalService } from '../services/futureSignalService'
import type { ItemResponse } from '../services/types'
import type { Property } from '../domain/property'
import type { Need } from '../domain/need'
import type { FutureSignal } from '../domain/futureSignal'
@@ -13,14 +14,14 @@ export function useMatchDetailData(matchId: string) {
const { data: match, isLoading } = useMatchDetail(matchId)
const isFuture = match?.resultType === 'FUTURE_AVAILABILITY'
const { data: property = null } = useQuery<Property | null>({
const { data: property = null } = useQuery<ItemResponse<Property | null>, Error, Property | null>({
queryKey: ['property', match?.propertyId],
queryFn: () => propertyService.getById(match!.propertyId),
enabled: !!match && !isFuture,
select: r => r.data ?? null,
})
const { data: need = null } = useQuery<Need | null>({
const { data: need = null } = useQuery<ItemResponse<Need | null>, Error, Need | null>({
queryKey: ['need', match?.needId],
queryFn: () => needService.getById(match!.needId),
enabled: !!match?.needId,
+1
View File
@@ -13,6 +13,7 @@ interface PropertyFilter {
minAreaSqm?: number
maxRentPerSqm?: number
organizationId?: string
sourceType?: string
}
export function useProperties(filter?: PropertyFilter) {
+2 -2
View File
@@ -22,13 +22,13 @@ export function useSchattenmarktSignals(properties: Property[]): FutureSignal[]
for (const unit of releasedUnits) {
const availableFrom = unit.schattenmarktRelease?.availableFrom ?? unit.leaseEndDate ?? p.leaseEndDate
if (!availableFrom) continue
const triggerDate = getTriggerDate(availableFrom, rel.leadTimeMonths)
const triggerDate = getTriggerDate(availableFrom, rel.leadTimeMonths ?? 0)
if (MOCK_TODAY < triggerDate) continue
signals.push(buildUnitSignal(p, unit, availableFrom))
}
} else {
// Backward compat: property-level signal (no explicit unit releases defined)
const triggerDate = getEarliestTriggerDate(p, rel.leadTimeMonths)
const triggerDate = getEarliestTriggerDate(p, rel.leadTimeMonths ?? 0)
if (!triggerDate || MOCK_TODAY < triggerDate) continue
signals.push(buildPropertySignal(p))
}
+1 -2
View File
@@ -1,12 +1,11 @@
import { useMemo } from 'react'
import { useMatches, useMatchesByNeed } from './useMatches'
import { useMatchesByNeed } from './useMatches'
import { useProperties } from './useProperties'
import { useFutureSignals } from './useFutureSignals'
import { useSchattenmarktSignals } from './useSchattenmarktSignals'
import type {
UnifiedMatchResult,
VerifiedPortfolioResult,
FutureAvailabilityResult,
} from '../domain/unifiedResult'
export function useUnifiedResults(needId?: string) {