b2530f9e20
Reale Jahresbelastung (Change 6): - FitOutCostPanel zeigt Jahresmiete + amortisierte Ausbaukosten für alle fitOut-Werte - FULL/PREMIUM: Ausbau CHF 0 (bezugsfertig), SHELL/BASIC: CRB/BKP-Richtwerte amortisiert über 5 J. - Match-Card-Chip zeigt geschätzte Investition (orange wenn >100k) - FitOutInvestment-Typ + calcFitOutInvestment() in fitOutUtils.ts - BackendAIService + MockAIService mit generateFitOutAdvice (IAIService-Interface) Must-have Kriterien (Nicht prüfbar Fix): - ÖV-Anbindung: Minutengrenze aus Freitext extrahiert, gegen publicTransportMinutes geprüft - Mindestfläche: m²-Wert aus Freitext extrahiert, gegen areaSqm geprüft - Ausbaugrad: neues Keyword-Rule für FULL/PREMIUM fitOut-Datenpflege: - fitOut-Werte zu 32 fehlenden Properties ergänzt (Logistik=SHELL, Standard=BASIC, Modern=FULL) - MAB-Werte (200/150/250 CHF/m²) zu 3 BASIC-Objekten hinzugefügt Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
92 lines
2.9 KiB
TypeScript
92 lines
2.9 KiB
TypeScript
import type { AssetType } from './enums'
|
|
|
|
export interface ParsedNeedCriteria {
|
|
assetType?: AssetType
|
|
areaRange?: { min: number; max: number }
|
|
preferredLocations?: string[]
|
|
budgetRange?: { maxPerSqm: number; maxMonthlyTotal?: number; currency: string }
|
|
timing?: { earliestMoveIn: string; latestMoveIn?: string; contractDurationMonths?: number; flexibleTiming: boolean }
|
|
mustHaveCriteria?: string[]
|
|
softFactors?: { minPrestige?: number; requireParking?: boolean; maxPublicTransportMinutes?: number; requireHighVisibility?: boolean }
|
|
requireGroundFloor?: boolean
|
|
requiredFitOut?: 'BASIC' | 'FULL' | 'PREMIUM'
|
|
requiredParkingMin?: number
|
|
requireAirConditioning?: boolean
|
|
requireLoadingDock?: boolean
|
|
requireBarrierFree?: boolean
|
|
minCeilingHeightM?: number
|
|
minContractDurationMonths?: number
|
|
infrastructureRequirements?: string[]
|
|
accessibilityRequirements?: string[]
|
|
prestigeImportance?: 'LOW' | 'MEDIUM' | 'HIGH'
|
|
flexibilityNeed?: 'LOW' | 'MEDIUM' | 'HIGH'
|
|
expansionPotential?: boolean
|
|
parkingNeed?: boolean
|
|
visibilityNeed?: 'LOW' | 'MEDIUM' | 'HIGH'
|
|
footfallNeed?: 'LOW' | 'MEDIUM' | 'HIGH'
|
|
companyName?: string
|
|
notes?: string
|
|
searchRadius?: number
|
|
isAnonymous?: boolean
|
|
requiresDivisibility?: boolean
|
|
minDivisibleUnit?: number
|
|
fitOutBudgetMaxPerSqm?: number
|
|
}
|
|
|
|
export interface FollowUpQuestion {
|
|
id: string
|
|
questionText: string
|
|
targetField: string
|
|
reason: string
|
|
suggestedAnswerOptions?: string[]
|
|
importance: 'required' | 'recommended' | 'optional'
|
|
}
|
|
|
|
export interface ParseNeedResult {
|
|
extractedCriteria: ParsedNeedCriteria
|
|
confidenceByField: Record<string, number>
|
|
missingFields: string[]
|
|
assumptions: string[]
|
|
suggestedWeights: Record<string, number>
|
|
followUpQuestionCandidates: FollowUpQuestion[]
|
|
rawSummary: string
|
|
promptVersion: string
|
|
schemaVersion: string
|
|
}
|
|
|
|
export const NeedBuilderStep = {
|
|
IDLE: 'idle',
|
|
PARSING: 'parsing',
|
|
PARSED_REQUIRES_REVIEW: 'parsed_requires_review',
|
|
CLARIFICATION_REQUIRED: 'clarification_required',
|
|
WEIGHTING_REVIEW: 'weighting_review',
|
|
READY_TO_SAVE: 'ready_to_save',
|
|
SAVING: 'saving',
|
|
SAVED: 'saved',
|
|
ERROR: 'error',
|
|
} as const
|
|
export type NeedBuilderStep = typeof NeedBuilderStep[keyof typeof NeedBuilderStep]
|
|
|
|
export const WEIGHTING_KEYS = [
|
|
'area', 'location', 'budget', 'timing',
|
|
'prestige', 'accessibility', 'expansionPotential', 'flexibility',
|
|
'visibility', 'footfall', 'talentAccess', 'esg', 'taxEnvironment',
|
|
] as const
|
|
export type WeightingKey = typeof WEIGHTING_KEYS[number]
|
|
|
|
export const WEIGHTING_LABELS: Record<WeightingKey, string> = {
|
|
area: 'Fläche',
|
|
location: 'Standort',
|
|
budget: 'Budget',
|
|
timing: 'Verfügbarkeit',
|
|
prestige: 'Prestige',
|
|
accessibility: 'Erreichbarkeit',
|
|
expansionPotential: 'Expansionspotenzial',
|
|
flexibility: 'Flexibilität',
|
|
visibility: 'Sichtbarkeit',
|
|
footfall: 'Passantenfrequenz',
|
|
talentAccess: 'Talent-Zugang',
|
|
esg: 'ESG',
|
|
taxEnvironment: 'Steuerlast',
|
|
}
|